Search in sources :

Example 6 with Parameter

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

the class MethodArgumentParameterTypeCheckTest method testNoArguments.

@Test
void testNoArguments() {
    final String code = "integer.m1()";
    final ITypeKeeper typeKeeper = new TypeKeeper();
    final MagikType integerType = (MagikType) typeKeeper.getType(GlobalReference.of("sw:integer"));
    final AbstractType symbolType = typeKeeper.getType(GlobalReference.of("sw:symbol"));
    final Parameter param1 = new Parameter("p1", Parameter.Modifier.NONE, symbolType);
    integerType.addMethod(EnumSet.noneOf(Method.Modifier.class), null, "m1()", List.of(param1), null, ExpressionResult.UNDEFINED);
    final MagikTypedCheck check = new MethodArgumentParameterTypedCheck();
    final List<MagikIssue> checkResults = this.runCheck(code, typeKeeper, check);
    assertThat(checkResults).isEmpty();
}
Also used : MagikTypedCheck(nl.ramsolutions.sw.magik.typedchecks.MagikTypedCheck) TypeKeeper(nl.ramsolutions.sw.magik.analysis.typing.TypeKeeper) ITypeKeeper(nl.ramsolutions.sw.magik.analysis.typing.ITypeKeeper) AbstractType(nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType) Parameter(nl.ramsolutions.sw.magik.analysis.typing.types.Parameter) MagikIssue(nl.ramsolutions.sw.magik.checks.MagikIssue) ITypeKeeper(nl.ramsolutions.sw.magik.analysis.typing.ITypeKeeper) MagikType(nl.ramsolutions.sw.magik.analysis.typing.types.MagikType) Test(org.junit.jupiter.api.Test)

Example 7 with Parameter

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

the class JsonTypeKeeperReader method handleMethod.

private void handleMethod(final JSONObject instruction) {
    final String typeName = instruction.getString("type_name");
    final ExpressionResult parsedResult = this.typeParser.parseExpressionResultString(typeName, SW_PAKKAGE);
    final AbstractType abstractType = (AbstractType) parsedResult.get(0, UndefinedType.INSTANCE);
    if (abstractType == UndefinedType.INSTANCE) {
        throw new InvalidParameterException("Unknown type: " + typeName);
    }
    final MagikType type = (MagikType) abstractType;
    final JSONArray modifiersArray = (JSONArray) instruction.getJSONArray("modifiers");
    final EnumSet<Method.Modifier> modifiers = StreamSupport.stream(modifiersArray.spliterator(), false).map(String.class::cast).map(String::toUpperCase).map(Method.Modifier::valueOf).collect(Collectors.toCollection(() -> EnumSet.noneOf(Method.Modifier.class)));
    final Location location = instruction.get("source_file") != JSONObject.NULL ? new Location(Path.of(instruction.getString("source_file")).toUri()) : null;
    final String methodName = instruction.getString("method_name");
    final List<Parameter> parameters = this.parseParameters(instruction.getJSONArray("parameters"));
    final Parameter assignmentParameter;
    if (methodName.contains("<<")) {
        int lastIdx = parameters.size() - 1;
        assignmentParameter = parameters.get(lastIdx);
        parameters.remove(lastIdx);
    } else {
        assignmentParameter = null;
    }
    final ExpressionResult result = this.parseExpressionResult(instruction.get("return_types"));
    final ExpressionResult loopResult = this.parseExpressionResult(instruction.get("loop_types"));
    final Method method = type.addMethod(modifiers, location, methodName, parameters, assignmentParameter, result, loopResult);
    if (instruction.get("doc") != JSONObject.NULL) {
        final String doc = instruction.getString("doc");
        method.setDoc(doc);
    }
}
Also used : ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) JSONArray(org.json.JSONArray) Method(nl.ramsolutions.sw.magik.analysis.typing.types.Method) MagikType(nl.ramsolutions.sw.magik.analysis.typing.types.MagikType) InvalidParameterException(java.security.InvalidParameterException) AbstractType(nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType) Parameter(nl.ramsolutions.sw.magik.analysis.typing.types.Parameter) Location(nl.ramsolutions.sw.magik.analysis.Location)

Example 8 with Parameter

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

the class JsonTypeKeeperReader method handleProcedure.

private void handleProcedure(final JSONObject instruction) {
    final JSONArray modifiersArray = (JSONArray) instruction.getJSONArray("modifiers");
    final EnumSet<Method.Modifier> modifiers = StreamSupport.stream(modifiersArray.spliterator(), false).map(String.class::cast).map(String::toUpperCase).map(Method.Modifier::valueOf).collect(Collectors.toCollection(() -> EnumSet.noneOf(Method.Modifier.class)));
    final Location location = instruction.get("source_file") != JSONObject.NULL ? new Location(Path.of(instruction.getString("source_file")).toUri()) : null;
    final List<Parameter> parameters = this.parseParameters(instruction.getJSONArray("parameters"));
    final ExpressionResult result = this.parseExpressionResult(instruction.get("return_types"));
    final ExpressionResult loopResult = this.parseExpressionResult(instruction.get("loop_types"));
    final String name = instruction.getString("name");
    final GlobalReference globalRef = GlobalReference.of(name);
    final String procedureName = instruction.getString("procedure_name");
    final ProcedureInstance instance = new ProcedureInstance(globalRef, procedureName);
    final Method method = instance.addMethod(modifiers, location, "invoke()", parameters, null, result, loopResult);
    this.typeKeeper.addType(instance);
    if (instruction.get("doc") != JSONObject.NULL) {
        final String doc = instruction.getString("doc");
        method.setDoc(doc);
    }
}
Also used : ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) GlobalReference(nl.ramsolutions.sw.magik.analysis.typing.types.GlobalReference) JSONArray(org.json.JSONArray) Parameter(nl.ramsolutions.sw.magik.analysis.typing.types.Parameter) Method(nl.ramsolutions.sw.magik.analysis.typing.types.Method) ProcedureInstance(nl.ramsolutions.sw.magik.analysis.typing.types.ProcedureInstance) Location(nl.ramsolutions.sw.magik.analysis.Location)

Example 9 with Parameter

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

the class LocalTypeReasoner method walkPostProcedureDefinition.

@Override
protected void walkPostProcedureDefinition(final AstNode node) {
    // Get name of procedure.
    String procName = ProcedureInstance.ANONYMOUS_PROCEDURE;
    final AstNode labelNode = node.getFirstChild(MagikGrammar.LABEL);
    if (labelNode != null) {
        final List<AstNode> labelNodeChildren = labelNode.getChildren();
        procName = labelNodeChildren.get(1).getTokenValue();
    }
    // Parameters.
    final AstNode parametersNode = node.getFirstChild(MagikGrammar.PARAMETERS);
    final List<Parameter> parameters = new ArrayList<>();
    final List<AstNode> parameterNodes = parametersNode.getChildren(MagikGrammar.PARAMETER);
    for (final AstNode parameterNode : parameterNodes) {
        final AstNode identifierNode = parameterNode.getFirstChild(MagikGrammar.IDENTIFIER);
        final String identifier = identifierNode.getTokenValue();
        final ParameterNodeHelper helper = new ParameterNodeHelper(parameterNode);
        final Parameter.Modifier modifier;
        if (helper.isOptionalParameter()) {
            modifier = Parameter.Modifier.OPTIONAL;
        } else if (helper.isGatherParameter()) {
            modifier = Parameter.Modifier.GATHER;
        } else {
            modifier = Parameter.Modifier.NONE;
        }
        final AbstractType type = this.getNodeType(parameterNode).get(0, UndefinedType.INSTANCE);
        final Parameter parameter = new Parameter(identifier, modifier, type);
        parameters.add(parameter);
    }
    // Result.
    final ExpressionResult procResult = this.getNodeType(node);
    // Loopbody result.
    final ExpressionResult loopbodyResult = this.getLoopbodyNodeType(node);
    // Create procedure instance.
    final EnumSet<Method.Modifier> modifiers = EnumSet.noneOf(Method.Modifier.class);
    final URI uri = node.getToken().getURI();
    final Location location = new Location(uri, node);
    final GlobalReference globalRef = GlobalReference.of(ProcedureInstance.ANONYMOUS_PROCEDURE);
    final ProcedureInstance procType = new ProcedureInstance(globalRef, procName);
    procType.addMethod(modifiers, location, "invoke()", parameters, null, procResult, loopbodyResult);
    // Store result.
    final ExpressionResult result = new ExpressionResult(procType);
    this.assignAtom(node, result);
}
Also used : ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) GlobalReference(nl.ramsolutions.sw.magik.analysis.typing.types.GlobalReference) ParameterNodeHelper(nl.ramsolutions.sw.magik.analysis.helpers.ParameterNodeHelper) ArrayList(java.util.ArrayList) Method(nl.ramsolutions.sw.magik.analysis.typing.types.Method) URI(java.net.URI) AbstractType(nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType) Parameter(nl.ramsolutions.sw.magik.analysis.typing.types.Parameter) ProcedureInstance(nl.ramsolutions.sw.magik.analysis.typing.types.ProcedureInstance) AstNode(com.sonar.sslr.api.AstNode) Location(nl.ramsolutions.sw.magik.analysis.Location)

Example 10 with Parameter

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

the class MagikIndexer method handleDefinition.

private void handleDefinition(final MagikFile magikFile, final MethodDefinition definition) {
    final AstNode node = definition.getNode();
    if (node.isNot(MagikGrammar.METHOD_DEFINITION)) {
        // No slot accessors, shared variables, shared constants.
        this.handleMethodDefinitionOther(magikFile, definition);
        return;
    }
    // Get exemplar.
    final GlobalReference globalRef = definition.getTypeGlobalReference();
    final AbstractType exemplarType = this.typeKeeper.getType(globalRef);
    if (exemplarType == UndefinedType.INSTANCE) {
        LOGGER.warn("Unknown type: {}", globalRef);
        return;
    }
    // Combine parameter types with method docs.
    final NewDocParser newDocParser = new NewDocParser(node);
    final Map<String, String> parameterTypes = newDocParser.getParameterTypes();
    final List<Parameter> parameters = definition.getParameters().stream().map(parameterDefinition -> {
        final String name = parameterDefinition.getName();
        final AbstractType type;
        if (!parameterTypes.containsKey(name)) {
            type = UndefinedType.INSTANCE;
        } else {
            final String parameterType = parameterTypes.get(name);
            type = this.typeParser.parseTypeString(parameterType, globalRef.getPakkage());
        }
        final Parameter.Modifier modifier = MagikIndexer.PARAMETER_MODIFIER_MAPPING.get(parameterDefinition.getModifier());
        return new Parameter(name, modifier, type);
    }).collect(Collectors.toList());
    final ParameterDefinition assignParamDef = definition.getAssignmentParameter();
    final Parameter assignmentParameter = assignParamDef != null ? new Parameter(assignParamDef.getName(), MagikIndexer.PARAMETER_MODIFIER_MAPPING.get(assignParamDef.getModifier())) : null;
    // Combine iterator types with method docs.
    final ExpressionResult loopResult = newDocParser.getLoopTypes().stream().map(type -> this.typeParser.parseTypeString(type, globalRef.getPakkage())).collect(ExpressionResult.COLLECTOR);
    // Combine return types with method docs.
    final ExpressionResult callResult = newDocParser.getReturnTypes().stream().map(type -> this.typeParser.parseTypeString(type, globalRef.getPakkage())).collect(ExpressionResult.COLLECTOR);
    // Create method.
    final MagikType magikType = (MagikType) exemplarType;
    final EnumSet<Method.Modifier> modifiers = definition.getModifiers().stream().map(modifier -> MagikIndexer.METHOD_MODIFIER_MAPPING.get(modifier)).collect(Collectors.toCollection(() -> EnumSet.noneOf(Method.Modifier.class)));
    final URI uri = magikFile.getUri();
    final Location location = new Location(uri, node);
    final String methodName = definition.getMethodName();
    final Method method = magikType.addMethod(modifiers, location, methodName, parameters, assignmentParameter, callResult, loopResult);
    // Method doc.
    final String methodDoc = MagikCommentExtractor.extractDocComments(node).map(Token::getValue).map(// Strip '##'
    line -> line.substring(2)).collect(Collectors.joining("\n"));
    method.setDoc(methodDoc);
    // Save used types.
    final AstNode bodyNode = node.getFirstChild(MagikGrammar.BODY);
    final GlobalScope globalScope = magikFile.getGlobalScope();
    final Scope bodyScope = globalScope.getScopeForNode(bodyNode);
    Objects.requireNonNull(bodyScope);
    bodyScope.getSelfAndDescendantScopes().stream().flatMap(scope -> scope.getScopeEntriesInScope().stream()).filter(scopeEntry -> scopeEntry.isType(ScopeEntry.Type.GLOBAL) || scopeEntry.isType(ScopeEntry.Type.DYNAMIC)).map(ScopeEntry::getIdentifier).map(identifier -> {
        AbstractType type = this.typeKeeper.getType(globalRef);
        if (type == UndefinedType.INSTANCE) {
            return null;
        } else if (type == SelfType.INSTANCE) {
            // TODO: Does this actually happen?
            type = this.typeKeeper.getType(globalRef);
        }
        return type;
    }).filter(Objects::nonNull).forEach(method::addUsedType);
    // Save called method names (thus without type).
    node.getDescendants(MagikGrammar.METHOD_INVOCATION).stream().map(invocationNode -> {
        final MethodInvocationNodeHelper invocationHelper = new MethodInvocationNodeHelper(invocationNode);
        return invocationHelper.getMethodName();
    }).forEach(method::addCalledMethod);
    // Save used slot names.
    node.getDescendants(MagikGrammar.SLOT).stream().map(slotNode -> slotNode.getFirstChild(MagikGrammar.IDENTIFIER).getTokenValue()).forEach(method::addUsedSlot);
    final Path path = Paths.get(magikFile.getUri());
    this.indexedMethods.get(path).add(method);
    LOGGER.debug("Indexed method: {}", method);
}
Also used : Method(nl.ramsolutions.sw.magik.analysis.typing.types.Method) MagikType(nl.ramsolutions.sw.magik.analysis.typing.types.MagikType) AstNode(com.sonar.sslr.api.AstNode) SlottedExemplarDefinition(nl.ramsolutions.sw.magik.analysis.definitions.SlottedExemplarDefinition) IndexedType(nl.ramsolutions.sw.magik.analysis.typing.types.IndexedType) LoggerFactory(org.slf4j.LoggerFactory) SlottedType(nl.ramsolutions.sw.magik.analysis.typing.types.SlottedType) Package(nl.ramsolutions.sw.magik.analysis.typing.types.Package) AliasType(nl.ramsolutions.sw.magik.analysis.typing.types.AliasType) IndexedExemplarDefinition(nl.ramsolutions.sw.magik.analysis.definitions.IndexedExemplarDefinition) UndefinedType(nl.ramsolutions.sw.magik.analysis.typing.types.UndefinedType) EnumerationDefinition(nl.ramsolutions.sw.magik.analysis.definitions.EnumerationDefinition) Map(java.util.Map) URI(java.net.URI) Path(java.nio.file.Path) MagikGrammar(nl.ramsolutions.sw.magik.api.MagikGrammar) EnumSet(java.util.EnumSet) MethodInvocationNodeHelper(nl.ramsolutions.sw.magik.analysis.helpers.MethodInvocationNodeHelper) MethodDefinition(nl.ramsolutions.sw.magik.analysis.definitions.MethodDefinition) TypeAnnotationHandler(nl.ramsolutions.sw.magik.analysis.typing.TypeAnnotationHandler) PackageNodeHelper(nl.ramsolutions.sw.magik.analysis.helpers.PackageNodeHelper) Set(java.util.Set) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) List(java.util.List) Stream(java.util.stream.Stream) ParameterDefinition(nl.ramsolutions.sw.magik.analysis.definitions.ParameterDefinition) GlobalDefinition(nl.ramsolutions.sw.magik.analysis.definitions.GlobalDefinition) HashMap(java.util.HashMap) SelfType(nl.ramsolutions.sw.magik.analysis.typing.types.SelfType) ITypeKeeper(nl.ramsolutions.sw.magik.analysis.typing.ITypeKeeper) HashSet(java.util.HashSet) TypeParser(nl.ramsolutions.sw.magik.analysis.typing.TypeParser) AbstractType(nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType) Location(nl.ramsolutions.sw.magik.analysis.Location) Nullable(javax.annotation.Nullable) GlobalScope(nl.ramsolutions.sw.magik.analysis.scope.GlobalScope) MagikCommentExtractor(nl.ramsolutions.sw.magik.parser.MagikCommentExtractor) GlobalReference(nl.ramsolutions.sw.magik.analysis.typing.types.GlobalReference) Token(com.sonar.sslr.api.Token) Slot(nl.ramsolutions.sw.magik.analysis.typing.types.Slot) Logger(org.slf4j.Logger) MagikFile(nl.ramsolutions.sw.magik.MagikFile) IOException(java.io.IOException) Parameter(nl.ramsolutions.sw.magik.analysis.typing.types.Parameter) NewDocParser(nl.ramsolutions.sw.magik.parser.NewDocParser) BinaryOperatorDefinition(nl.ramsolutions.sw.magik.analysis.definitions.BinaryOperatorDefinition) MixinDefinition(nl.ramsolutions.sw.magik.analysis.definitions.MixinDefinition) IntrinsicType(nl.ramsolutions.sw.magik.analysis.typing.types.IntrinsicType) PackageDefinition(nl.ramsolutions.sw.magik.analysis.definitions.PackageDefinition) Paths(java.nio.file.Paths) Definition(nl.ramsolutions.sw.magik.analysis.definitions.Definition) ScopeEntry(nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry) Scope(nl.ramsolutions.sw.magik.analysis.scope.Scope) Collections(java.util.Collections) BinaryOperator(nl.ramsolutions.sw.magik.analysis.typing.BinaryOperator) ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) Path(java.nio.file.Path) GlobalScope(nl.ramsolutions.sw.magik.analysis.scope.GlobalScope) GlobalReference(nl.ramsolutions.sw.magik.analysis.typing.types.GlobalReference) ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) Token(com.sonar.sslr.api.Token) Method(nl.ramsolutions.sw.magik.analysis.typing.types.Method) URI(java.net.URI) MagikType(nl.ramsolutions.sw.magik.analysis.typing.types.MagikType) MethodInvocationNodeHelper(nl.ramsolutions.sw.magik.analysis.helpers.MethodInvocationNodeHelper) NewDocParser(nl.ramsolutions.sw.magik.parser.NewDocParser) GlobalScope(nl.ramsolutions.sw.magik.analysis.scope.GlobalScope) Scope(nl.ramsolutions.sw.magik.analysis.scope.Scope) AbstractType(nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType) Parameter(nl.ramsolutions.sw.magik.analysis.typing.types.Parameter) AstNode(com.sonar.sslr.api.AstNode) ParameterDefinition(nl.ramsolutions.sw.magik.analysis.definitions.ParameterDefinition) Location(nl.ramsolutions.sw.magik.analysis.Location)

Aggregations

Parameter (nl.ramsolutions.sw.magik.analysis.typing.types.Parameter)11 AbstractType (nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType)10 MagikType (nl.ramsolutions.sw.magik.analysis.typing.types.MagikType)7 Method (nl.ramsolutions.sw.magik.analysis.typing.types.Method)7 ITypeKeeper (nl.ramsolutions.sw.magik.analysis.typing.ITypeKeeper)6 ExpressionResult (nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult)6 AstNode (com.sonar.sslr.api.AstNode)5 Location (nl.ramsolutions.sw.magik.analysis.Location)5 MethodInvocationNodeHelper (nl.ramsolutions.sw.magik.analysis.helpers.MethodInvocationNodeHelper)4 GlobalReference (nl.ramsolutions.sw.magik.analysis.typing.types.GlobalReference)4 URI (java.net.URI)3 List (java.util.List)3 Collectors (java.util.stream.Collectors)3 MagikTypedCheck (nl.ramsolutions.sw.magik.typedchecks.MagikTypedCheck)3 Token (com.sonar.sslr.api.Token)2 IOException (java.io.IOException)2 Path (java.nio.file.Path)2 Paths (java.nio.file.Paths)2 Collections (java.util.Collections)2 EnumSet (java.util.EnumSet)2