use of nl.ramsolutions.sw.magik.analysis.definitions.MethodDefinition in project magik-tools by StevenLooman.
the class DuplicateMethodInFileCheck method walkPostMagik.
@Override
protected void walkPostMagik(final AstNode node) {
// Test for duplicates.
final Map<String, List<MethodDefinition>> definitions = this.methodDefinitions.stream().collect(Collectors.toMap(MethodDefinition::getName, List::of, (list1, list2) -> Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList())));
definitions.entrySet().stream().filter(entry -> entry.getValue().size() > 1).flatMap(entry -> entry.getValue().stream()).forEach(definition -> {
AstNode definitionNode = definition.getNode();
this.addIssue(definitionNode, MESSAGE);
});
}
use of nl.ramsolutions.sw.magik.analysis.definitions.MethodDefinition in project magik-tools by StevenLooman.
the class DuplicateMethodInFileCheck method walkPostMethodDefinition.
@Override
protected void walkPostMethodDefinition(final AstNode node) {
final MethodDefinitionParser parser = new MethodDefinitionParser(node);
final List<Definition> parsedDefinitions = parser.parseDefinitions();
if (parsedDefinitions.isEmpty()) {
// How does this happen?
return;
}
final MethodDefinition methodDefinition = (MethodDefinition) parsedDefinitions.get(0);
this.methodDefinitions.add(methodDefinition);
}
use of nl.ramsolutions.sw.magik.analysis.definitions.MethodDefinition in project magik-tools by StevenLooman.
the class MagikIndexer method handleDefinition.
private void handleDefinition(final Path path, final MagikFile magikFile, final Definition definition) {
if (definition instanceof PackageDefinition) {
final PackageDefinition packageDefinition = (PackageDefinition) definition;
this.handleDefinition(magikFile, packageDefinition);
} else if (definition instanceof IndexedExemplarDefinition) {
final IndexedExemplarDefinition indexedExemplarDefinition = (IndexedExemplarDefinition) definition;
this.handleDefinition(magikFile, indexedExemplarDefinition);
} else if (definition instanceof EnumerationDefinition) {
final EnumerationDefinition enumerationDefinition = (EnumerationDefinition) definition;
this.handleDefinition(magikFile, enumerationDefinition);
} else if (definition instanceof SlottedExemplarDefinition) {
final SlottedExemplarDefinition slottedExemplarDefinition = (SlottedExemplarDefinition) definition;
this.handleDefinition(magikFile, slottedExemplarDefinition);
} else if (definition instanceof MixinDefinition) {
final MixinDefinition mixinDefinition = (MixinDefinition) definition;
this.handleDefinition(magikFile, mixinDefinition);
} else if (definition instanceof MethodDefinition) {
final MethodDefinition methodDefinition = (MethodDefinition) definition;
this.handleDefinition(magikFile, methodDefinition);
} else if (definition instanceof GlobalDefinition) {
final GlobalDefinition globalDefinition = (GlobalDefinition) definition;
this.handleDefinition(magikFile, globalDefinition);
} else if (definition instanceof BinaryOperatorDefinition) {
final BinaryOperatorDefinition binaryOperatorDefinition = (BinaryOperatorDefinition) definition;
this.handleDefinition(magikFile, binaryOperatorDefinition);
}
}
use of nl.ramsolutions.sw.magik.analysis.definitions.MethodDefinition 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);
}
use of nl.ramsolutions.sw.magik.analysis.definitions.MethodDefinition in project magik-tools by StevenLooman.
the class MagikIndexer method handleMethodDefinitionOther.
private void handleMethodDefinitionOther(final MagikFile magikFile, final MethodDefinition definition) {
// Slot accessors, shared variables, shared constants.
final GlobalReference globalRef = definition.getTypeGlobalReference();
final AbstractType exemplarType = this.typeKeeper.getType(globalRef);
if (exemplarType == UndefinedType.INSTANCE) {
LOGGER.warn("Unknown type: {}", globalRef);
return;
}
// Get method return types from docs, if any.
final AstNode node = definition.getNode();
final NewDocParser methodDocParser = new NewDocParser(node);
final List<AbstractType> methodReturnTypes = methodDocParser.getReturnTypes().stream().map(typeStr -> this.typeParser.parseTypeString(typeStr, globalRef.getPakkage())).collect(Collectors.toList());
// Get slot type from docs, if any.
final AstNode statementNode = node.getFirstAncestor(MagikGrammar.STATEMENT);
final AbstractType slotType;
if (statementNode != null) {
final NewDocParser exemplarDocParser = new NewDocParser(statementNode);
final String slotName = definition.getMethodName();
final String slotTypeStr = exemplarDocParser.getSlotTypes().get(slotName);
slotType = this.typeParser.parseTypeString(slotTypeStr, globalRef.getPakkage());
} else {
slotType = UndefinedType.INSTANCE;
}
// Determine the result to use.
final ExpressionResult result = !methodReturnTypes.isEmpty() ? new ExpressionResult(methodReturnTypes) : new ExpressionResult(slotType);
// 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 List<Parameter> parameters = Collections.emptyList();
final Parameter assignmentParameter = null;
final Method method = magikType.addMethod(modifiers, location, methodName, parameters, assignmentParameter, result);
// TODO: Will this work?
// TODO: Ensure we don't pick up class comment of def_slotted_exemplar.
final String methodDoc = MagikCommentExtractor.extractDocComments(node).map(Token::getValue).collect(Collectors.joining("\n"));
method.setDoc(methodDoc);
final Path path = Paths.get(magikFile.getUri());
this.indexedMethods.get(path).add(method);
LOGGER.debug("Indexed method: {}", method);
}
Aggregations