use of nl.ramsolutions.sw.magik.analysis.typing.types.GlobalReference 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.typing.types.GlobalReference in project magik-tools by StevenLooman.
the class MagikIndexer method fillType.
private void fillType(final MagikType magikType, final MagikFile magikFile, final AstNode node, final String packageName, final Map<String, String> slots, final List<String> parents, @Nullable final AbstractType defaultParentType) {
// Set location.
final URI uri = magikFile.getUri();
final Location location = new Location(uri, node);
magikType.setLocation(location);
// Set slots.
magikType.clearSlots();
slots.entrySet().forEach(entry -> {
final String slotName = entry.getKey();
final String slotTypeName = entry.getValue();
final AbstractType slotType = this.typeParser.parseTypeString(slotTypeName, packageName);
final Slot slot = magikType.addSlot(null, slotName);
slot.setType(slotType);
});
// Parents.
magikType.clearParents();
final PackageNodeHelper packageHelper = new PackageNodeHelper(node);
final String pakkageName = packageHelper.getCurrentPackage();
parents.stream().forEach(parent -> {
final GlobalReference parentGlobalRef = parent.indexOf(':') != -1 ? GlobalReference.of(parent) : GlobalReference.of(pakkageName, parent);
final AbstractType parentType = this.typeKeeper.getType(parentGlobalRef);
if (parentType == UndefinedType.INSTANCE) {
LOGGER.warn("Parent type not found: {} from package: {}", parent, pakkageName);
} else {
magikType.addParent(parentType);
}
});
// Default parent types ()
boolean parentNonIntrinsicType = magikType.getParents().stream().anyMatch(parentType -> parentType instanceof SlottedType || parentType instanceof IndexedType);
if (defaultParentType != null && !parentNonIntrinsicType) {
magikType.addParent(defaultParentType);
}
// Type doc.
final String typeDoc = MagikCommentExtractor.extractDocComments(node).map(Token::getValue).map(// Strip '##'
line -> line.substring(2)).collect(Collectors.joining("\n"));
magikType.setDoc(typeDoc);
}
use of nl.ramsolutions.sw.magik.analysis.typing.types.GlobalReference in project magik-tools by StevenLooman.
the class MagikIndexer method handleDefinition.
@SuppressWarnings("java:S1172")
private void handleDefinition(final MagikFile magikFile, final GlobalDefinition globalDefinition) {
final String pakkage = globalDefinition.getPackage();
final String identifier = globalDefinition.getName();
final GlobalReference globalRef = typeParser.getGlobalRefeference(identifier, pakkage);
if (this.typeKeeper.getType(globalRef) != null) {
// Don't overwrite any existing types with a AliasType.
return;
}
final String typeAnnotation = TypeAnnotationHandler.typeAnnotationForExpression(globalDefinition.getNode());
final AbstractType aliasedType = typeAnnotation != null ? this.typeParser.parseTypeString(typeAnnotation, globalDefinition.getPackage()) : UndefinedType.INSTANCE;
final AbstractType globalType = new AliasType(globalRef, aliasedType);
this.typeKeeper.addType(globalType);
final Path path = Paths.get(magikFile.getUri());
this.indexedTypes.get(path).add(globalType);
}
use of nl.ramsolutions.sw.magik.analysis.typing.types.GlobalReference 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);
}
use of nl.ramsolutions.sw.magik.analysis.typing.types.GlobalReference in project magik-tools by StevenLooman.
the class MagikIndexer method handleDefinition.
private void handleDefinition(final MagikFile magikFile, final EnumerationDefinition definition) {
final AstNode node = definition.getNode();
final GlobalReference globalRef = definition.getGlobalReference();
final MagikType type = this.typeKeeper.getType(globalRef) != UndefinedType.INSTANCE ? (MagikType) this.typeKeeper.getType(globalRef) : new SlottedType(globalRef);
this.typeKeeper.addType(type);
final Map<String, String> slots = Collections.emptyMap();
final List<String> parents = definition.getParents();
final MagikType defaultParentType = (MagikType) this.typeKeeper.getType(GlobalReference.of("sw:enumeration_value"));
this.fillType(type, magikFile, node, globalRef.getPakkage(), slots, parents, defaultParentType);
final Path path = Paths.get(magikFile.getUri());
this.indexedTypes.get(path).add(type);
LOGGER.debug("Indexed type: {}", type);
}
Aggregations