Search in sources :

Example 1 with LocalTypeReasoner

use of nl.ramsolutions.sw.magik.analysis.typing.LocalTypeReasoner in project magik-tools by StevenLooman.

the class HoverProvider method provideHoverAtom.

/**
 * Provide hover for an atom.
 * @param magikFile Magik file.
 * @param atomNode Atom node hovered on.
 * @param builder Builder to add text to.
 */
private void provideHoverAtom(final MagikTypedFile magikFile, final AstNode atomNode, final StringBuilder builder) {
    final LocalTypeReasoner reasoner = magikFile.getTypeReasoner();
    final ExpressionResult result = reasoner.getNodeTypeSilent(atomNode);
    if (result != null) {
        LOGGER.debug("Providing hover for node: {}", atomNode.getTokenValue());
        final ITypeKeeper typeKeeper = magikFile.getTypeKeeper();
        this.buildTypeDoc(typeKeeper, reasoner, atomNode, builder);
    }
}
Also used : ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) LocalTypeReasoner(nl.ramsolutions.sw.magik.analysis.typing.LocalTypeReasoner) ITypeKeeper(nl.ramsolutions.sw.magik.analysis.typing.ITypeKeeper)

Example 2 with LocalTypeReasoner

use of nl.ramsolutions.sw.magik.analysis.typing.LocalTypeReasoner in project magik-tools by StevenLooman.

the class HoverProvider method provideHoverMethodInvocation.

/**
 * Provide hover for a method invocation.
 * @param magikFile Magik file.
 * @param hoveredNode Hovered node.
 * @param builder Builder to add text to.
 */
private void provideHoverMethodInvocation(final MagikTypedFile magikFile, final AstNode hoveredNode, final StringBuilder builder) {
    final AstNode providingNode = hoveredNode.getParent();
    final AstNode previousSiblingNode = providingNode.getPreviousSibling();
    if (previousSiblingNode != null) {
        final MethodInvocationNodeHelper helper = new MethodInvocationNodeHelper(providingNode);
        final String methodName = helper.getMethodName();
        LOGGER.debug("Providing hover for node: {}, method: {}", previousSiblingNode.getTokenValue(), methodName);
        if (methodName != null) {
            final ITypeKeeper typeKeeper = magikFile.getTypeKeeper();
            final LocalTypeReasoner reasoner = magikFile.getTypeReasoner();
            this.buildMethodDoc(typeKeeper, reasoner, previousSiblingNode, methodName, builder);
        }
    }
}
Also used : LocalTypeReasoner(nl.ramsolutions.sw.magik.analysis.typing.LocalTypeReasoner) AstNode(com.sonar.sslr.api.AstNode) MethodInvocationNodeHelper(nl.ramsolutions.sw.magik.analysis.helpers.MethodInvocationNodeHelper) ITypeKeeper(nl.ramsolutions.sw.magik.analysis.typing.ITypeKeeper)

Example 3 with LocalTypeReasoner

use of nl.ramsolutions.sw.magik.analysis.typing.LocalTypeReasoner in project magik-tools by StevenLooman.

the class MethodArgumentParameterTypedCheck method walkPostMethodInvocation.

@Override
protected void walkPostMethodInvocation(final AstNode node) {
    // Ensure there are arguments to check.
    final AstNode argumentsNode = node.getFirstChild(MagikGrammar.ARGUMENTS);
    if (argumentsNode == null) {
        return;
    }
    // Get type.
    final AbstractType calledType = this.getTypeInvokedOn(node);
    if (calledType == UndefinedType.INSTANCE) {
        // Cannot give any useful information, so abort.
        return;
    }
    // Get types for arguments.
    final LocalTypeReasoner reasoner = this.getReasoner();
    final List<AstNode> argumentNodes = argumentsNode.getChildren(MagikGrammar.ARGUMENT).stream().collect(Collectors.toList());
    final List<ExpressionResult> argumentTypes = argumentNodes.stream().map(argumentNode -> argumentNode.getFirstChild(MagikGrammar.EXPRESSION)).map(reasoner::getNodeType).collect(Collectors.toList());
    // Get methods.
    final MethodInvocationNodeHelper helper = new MethodInvocationNodeHelper(node);
    final String methodName = helper.getMethodName();
    for (final Method method : calledType.getMethods(methodName)) {
        final List<Parameter> parameters = method.getParameters();
        if (parameters.isEmpty()) {
            continue;
        }
        final List<AbstractType> parameterTypes = method.getParameters().stream().filter(parameter -> parameter.is(Parameter.Modifier.NONE) || // Don't check gather.
        parameter.is(Parameter.Modifier.OPTIONAL)).map(Parameter::getType).collect(Collectors.toList());
        // Test parameter type against argument type.
        final int size = Math.min(parameterTypes.size(), argumentTypes.size());
        IntStream.range(0, size).forEach(index -> {
            final AbstractType parameterType = parameterTypes.get(index);
            if (parameterType == UndefinedType.INSTANCE) {
                return;
            }
            final AbstractType argumentType = argumentTypes.get(index).get(0, UndefinedType.INSTANCE);
            if (!TypeMatcher.typeMatches(argumentType, parameterType)) {
                final AstNode argumentNode = argumentNodes.get(index);
                final String message = String.format(MESSAGE, argumentType.getFullName(), parameterType.getFullName());
                this.addIssue(argumentNode, message);
            }
        });
    }
}
Also used : ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) LocalTypeReasoner(nl.ramsolutions.sw.magik.analysis.typing.LocalTypeReasoner) Method(nl.ramsolutions.sw.magik.analysis.typing.types.Method) MethodInvocationNodeHelper(nl.ramsolutions.sw.magik.analysis.helpers.MethodInvocationNodeHelper) AbstractType(nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType) Parameter(nl.ramsolutions.sw.magik.analysis.typing.types.Parameter) AstNode(com.sonar.sslr.api.AstNode)

Example 4 with LocalTypeReasoner

use of nl.ramsolutions.sw.magik.analysis.typing.LocalTypeReasoner in project magik-tools by StevenLooman.

the class MagikTypedCheck method getTypeInvokedOn.

/**
 * Get type method invoked on.
 * @param node METHOD_INVOCATION node.
 * @return Type method is invoked, or UNDEFINED_TYPE.
 */
protected AbstractType getTypeInvokedOn(final AstNode node) {
    if (node.isNot(MagikGrammar.METHOD_INVOCATION)) {
        throw new IllegalStateException();
    }
    final AstNode previousSibling = node.getPreviousSibling();
    final LocalTypeReasoner reasoner = this.getReasoner();
    final ExpressionResult result = reasoner.getNodeType(previousSibling);
    final AbstractType type = result.get(0, UndefinedType.INSTANCE);
    if (type == SelfType.INSTANCE) {
        final AstNode methodDefNode = node.getFirstAncestor(MagikGrammar.METHOD_DEFINITION);
        return this.getTypeOfMethodDefinition(methodDefNode);
    }
    return type;
}
Also used : ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) AbstractType(nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType) LocalTypeReasoner(nl.ramsolutions.sw.magik.analysis.typing.LocalTypeReasoner) AstNode(com.sonar.sslr.api.AstNode)

Example 5 with LocalTypeReasoner

use of nl.ramsolutions.sw.magik.analysis.typing.LocalTypeReasoner in project magik-tools by StevenLooman.

the class MagikTypedFile method getTypeReasoner.

/**
 * Run the (cached) {{LocalTypeReasoner}} and return it.
 * @return The used LocalTypeReasoner.
 */
public synchronized LocalTypeReasoner getTypeReasoner() {
    if (this.typeReasoner == null) {
        final AstNode node = this.getTopNode();
        this.typeReasoner = new LocalTypeReasoner(this);
        this.typeReasoner.run(node);
    }
    return this.typeReasoner;
}
Also used : LocalTypeReasoner(nl.ramsolutions.sw.magik.analysis.typing.LocalTypeReasoner) AstNode(com.sonar.sslr.api.AstNode)

Aggregations

LocalTypeReasoner (nl.ramsolutions.sw.magik.analysis.typing.LocalTypeReasoner)11 AstNode (com.sonar.sslr.api.AstNode)9 ExpressionResult (nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult)8 ITypeKeeper (nl.ramsolutions.sw.magik.analysis.typing.ITypeKeeper)6 AbstractType (nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType)6 MethodInvocationNodeHelper (nl.ramsolutions.sw.magik.analysis.helpers.MethodInvocationNodeHelper)5 ArrayList (java.util.ArrayList)3 List (java.util.List)3 MagikTypedFile (nl.ramsolutions.sw.magik.MagikTypedFile)3 AstQuery (nl.ramsolutions.sw.magik.analysis.AstQuery)3 MethodDefinitionNodeHelper (nl.ramsolutions.sw.magik.analysis.helpers.MethodDefinitionNodeHelper)3 GlobalReference (nl.ramsolutions.sw.magik.analysis.typing.types.GlobalReference)3 Method (nl.ramsolutions.sw.magik.analysis.typing.types.Method)3 SelfType (nl.ramsolutions.sw.magik.analysis.typing.types.SelfType)3 UndefinedType (nl.ramsolutions.sw.magik.analysis.typing.types.UndefinedType)3 MagikGrammar (nl.ramsolutions.sw.magik.api.MagikGrammar)3 Lsp4jConversion (nl.ramsolutions.sw.magik.languageserver.Lsp4jConversion)3 Position (org.eclipse.lsp4j.Position)3 ServerCapabilities (org.eclipse.lsp4j.ServerCapabilities)3 Logger (org.slf4j.Logger)3