use of nl.ramsolutions.sw.magik.analysis.typing.types.Method in project magik-tools by StevenLooman.
the class HoverProvider method buildMethodDoc.
/**
* Build hover text for method doc.
* @param typeKeeper TypeKeeper.
* @param reasoner LocalTypeReasoner.
* @param node AstNode, METHOD_INVOCATION.
* @param methodName Name of invoked method.
* @param builder {{StringBuilder}} to fill.
*/
private void buildMethodDoc(final ITypeKeeper typeKeeper, final LocalTypeReasoner reasoner, final AstNode node, final String methodName, final StringBuilder builder) {
// Get type from reasoner.
final ExpressionResult result = reasoner.getNodeType(node);
// We know what self is.
AbstractType type = result.get(0, UndefinedType.INSTANCE);
if (type == SelfType.INSTANCE) {
final AstNode methodDefNode = node.getFirstAncestor(MagikGrammar.METHOD_DEFINITION);
if (methodDefNode == null) {
// This can happen in case of a procedure definition calling a method on _self.
type = UndefinedType.INSTANCE;
} else {
final MethodDefinitionNodeHelper helper = new MethodDefinitionNodeHelper(methodDefNode);
final GlobalReference globalRef = helper.getTypeGlobalReference();
type = typeKeeper.getType(globalRef);
}
}
// Get method info.
final Collection<Method> methods = type.getMethods(methodName);
if (methods.isEmpty()) {
this.buildMethodUnknownDoc(type, methodName, builder);
return;
}
methods.forEach(method -> this.buildMethodSignatureDoc(method, builder));
}
use of nl.ramsolutions.sw.magik.analysis.typing.types.Method in project magik-tools by StevenLooman.
the class ClassInfoTypeKeeperReader method readMethod.
private void readMethod(final String line, final BufferedReader reader) throws IOException {
// - 1 : "method" <class name> <method name> <parameters> <-- possibly no assignment parameter
// 2 : n ["private"/"classconst"/"classvar"/"iter"]*
// ["basic"/"restricted"/"internal"/pragma]* source_file
// 3+: <n lines of comments>
// Line 1
// ignore <global> and <condition> for now
final MagikType type;
final String methodName;
try (Scanner scanner = new Scanner(line)) {
// "method"
scanner.next();
final String className = scanner.next();
if (!"<global>".equals(className) && !"<condition>".equals(className)) {
final GlobalReference globalRef = GlobalReference.of(className);
methodName = scanner.next();
if (!this.typeKeeper.hasType(globalRef)) {
// LOGGER.debug("Type not found: {}, for method: {}", pakkageName, methodName);
type = null;
} else {
type = (MagikType) this.typeKeeper.getType(globalRef);
}
// <parameters>
scanner.nextLine();
} else {
// Skip line
scanner.nextLine();
type = null;
methodName = null;
}
}
// Line 2
int commentLineCount = 0;
try (Scanner scanner = new Scanner(reader.readLine())) {
commentLineCount = scanner.nextInt();
final List<String> pragmas = new ArrayList<>();
final List<String> skipList = List.of("private", "classconst", "classvar", "iter");
while (scanner.hasNext("[^/]+")) {
final String pragma = scanner.next();
if (skipList.contains(pragma)) {
continue;
}
pragmas.add(pragma);
}
// Skip path
scanner.nextLine();
}
// Line 3+
final StringBuilder commentBuilder = new StringBuilder();
for (int i = 0; i < commentLineCount; ++i) {
final String commentLine = reader.readLine();
commentBuilder.append(commentLine);
commentBuilder.append('\n');
}
final String comment = commentBuilder.toString();
if (type != null) {
for (final Method method : type.getMethods(methodName)) {
method.setDoc(comment);
}
}
reader.readLine();
}
use of nl.ramsolutions.sw.magik.analysis.typing.types.Method in project magik-tools by StevenLooman.
the class LocalTypeReasoner method walkPostMethodInvocation.
@Override
protected void walkPostMethodInvocation(final AstNode node) {
final AbstractType unsetType = this.typeKeeper.getType(SW_UNSET);
// Get called type for method.
final AstNode calledNode = node.getPreviousSibling();
final ExpressionResult calledResult = this.getNodeType(calledNode);
final AbstractType originalCalledType = calledResult.get(0, unsetType);
final AbstractType calledType = calledResult.get(0, unsetType) == SelfType.INSTANCE ? this.getMethodOwnerType(node) : calledResult.get(0, unsetType);
// Clear iterator results.
this.setIteratorType(null);
// Perform method call and store iterator result(s).
final MethodInvocationNodeHelper helper = new MethodInvocationNodeHelper(node);
final String methodName = helper.getMethodName();
final Collection<Method> methods = calledType.getMethods(methodName);
ExpressionResult callResult = null;
if (methods.isEmpty()) {
// Method not found, we cannot known what the results will be.
callResult = ExpressionResult.UNDEFINED;
this.setIteratorType(ExpressionResult.UNDEFINED);
} else {
for (final Method method : methods) {
// Call.
if (callResult == null) {
callResult = method.getCallResult();
} else {
final ExpressionResult methodResult = method.getCallResult();
callResult = new ExpressionResult(callResult, methodResult, unsetType);
}
if (originalCalledType != SelfType.INSTANCE) {
callResult = callResult.substituteType(SelfType.INSTANCE, calledType);
}
// Iterator.
final ExpressionResult loopbodyResult = method.getLoopbodyResult();
if (this.getIteratorType() == null) {
this.setIteratorType(loopbodyResult);
} else {
final ExpressionResult iterResult = new ExpressionResult(this.iteratorType, loopbodyResult, unsetType);
this.setIteratorType(iterResult);
}
if (originalCalledType != SelfType.INSTANCE) {
final ExpressionResult subbedResult = this.getIteratorType().substituteType(SelfType.INSTANCE, calledType);
this.setIteratorType(subbedResult);
}
}
}
// Store it!
// Keep linters happy.
Objects.requireNonNull(callResult);
this.setNodeType(node, callResult);
}
use of nl.ramsolutions.sw.magik.analysis.typing.types.Method in project magik-tools by StevenLooman.
the class LocalTypeReasoner method walkPostProcedureInvocation.
@Override
protected void walkPostProcedureInvocation(final AstNode node) {
final AbstractType unsetType = this.typeKeeper.getType(SW_UNSET);
// Get called type for invocation.
final AstNode calledNode = node.getPreviousSibling();
final ExpressionResult calledResult = this.getNodeType(calledNode);
AbstractType calledType = calledResult.get(0, unsetType);
final AbstractType originalCalledType = calledType;
if (calledType == SelfType.INSTANCE) {
// Replace self type with concrete type, need to know the method we call.
calledType = this.typeKeeper.getType(SW_PROCEDURE);
}
// Clear iterator results.
this.setIteratorType(null);
// Perform procedure call.
ExpressionResult callResult = null;
if (calledType instanceof ProcedureInstance) {
final ProcedureInstance procedureType = (ProcedureInstance) calledType;
final Collection<Method> methods = procedureType.getMethods("invoke()");
final Method method = methods.stream().findAny().orElse(null);
Objects.requireNonNull(method);
callResult = method.getCallResult();
final ExpressionResult loopbodyResult = method.getLoopbodyResult();
this.setIteratorType(loopbodyResult);
if (originalCalledType == SelfType.INSTANCE) {
callResult = callResult.substituteType(SelfType.INSTANCE, calledType);
final ExpressionResult subbedResult = this.getIteratorType().substituteType(SelfType.INSTANCE, calledType);
this.setIteratorType(subbedResult);
}
}
if (callResult == null) {
callResult = ExpressionResult.UNDEFINED;
this.setIteratorType(ExpressionResult.UNDEFINED);
}
// Store it!
this.setNodeType(node, callResult);
}
use of nl.ramsolutions.sw.magik.analysis.typing.types.Method in project magik-tools by StevenLooman.
the class LocalTypeReasonerTest method testReasonMethodReturnProc.
@Test
void testReasonMethodReturnProc() {
final String code = "" + "_method object.test\n" + " _return _proc@test()\n" + " >> 10\n" + " _endproc\n" + "_endmethod\n";
// Set up TypeKeeper/TypeReasoner.
final TypeKeeper typeKeeper = new TypeKeeper();
// Do analysis.
final MagikTypedFile magikFile = this.createMagikFile(code, typeKeeper);
final LocalTypeReasoner reasoner = magikFile.getTypeReasoner();
// Assert user:object.test type determined.
final AstNode topNode = magikFile.getTopNode();
final AstNode methodNode = topNode.getFirstChild(MagikGrammar.METHOD_DEFINITION);
final ExpressionResult result = reasoner.getNodeType(methodNode);
assertThat(result.size()).isEqualTo(1);
final ProcedureInstance resultType = (ProcedureInstance) result.get(0, null);
assertThat(resultType).isNotNull();
assertThat(resultType.getProcedureName()).isEqualTo("test");
final Collection<Method> procMethods = resultType.getMethods("invoke()");
assertThat(procMethods).isNotEmpty();
for (final Method procMethod : procMethods) {
final ExpressionResult procResult = procMethod.getCallResult();
assertThat(procResult.size()).isEqualTo(1);
final MagikType procResultType = (MagikType) procResult.get(0, null);
assertThat(procResultType).isNotNull();
assertThat(procResultType.getFullName()).isEqualTo("sw:integer");
}
}
Aggregations