Method naming fixes (#1024)

This commit is contained in:
Marcin Kostrzewa 2020-07-22 12:01:35 +02:00 committed by GitHub
parent ded61865a4
commit 6137c6559b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 340 additions and 152 deletions

View File

@ -96,6 +96,8 @@ Text.it ~behavior =
## Runs a suite of tests, consisting of multiple `describe` blocks.
Returns a `Suite` object containing the test report.
> Example
Suite.run <|
describe "Number" <|
@ -107,5 +109,20 @@ Suite.run ~specs =
r = State.run Suite (Suite Nil) <|
specs
State.get Suite
code = if r.is_fail then 1 else 0
System.exit code
r
## Runs a suite of tests, consisting of multiple `describe` blocks.
Exits the process with code `1` if the suite failed and `0` otherwise.
> Example
Suite.run <|
describe "Number" <|
it "should define addition" <|
2+3 . should_equal 5
it "should define multiplication" <|
2*3 . should_equal 6
Suite.runMain ~specs =
r = this.run specs
code = if r.is_fail then 1 else 0
System.exit code

View File

@ -10,8 +10,9 @@ import org.enso.languageserver.boot.LanguageServerConfig
import org.enso.pkg.PackageManager
import org.enso.polyglot.{LanguageInfo, Module, PolyglotContext}
import org.enso.version.VersionDescription
import org.graalvm.polyglot.Value
import org.graalvm.polyglot.{PolyglotException, Value}
import scala.jdk.CollectionConverters._
import scala.util.Try
/** The main CLI entry point class. */
@ -143,7 +144,10 @@ object Main {
new HelpFormatter().printHelp(LanguageInfo.ID, options)
/** Terminates the process with a failure exit code. */
private def exitFail(): Unit = System.exit(1)
private def exitFail(): Nothing = {
System.exit(1)
throw new IllegalStateException("impossible to reach here")
}
/** Terminates the process with a success exit code. */
private def exitSuccess(): Unit = System.exit(0)
@ -189,7 +193,7 @@ object Main {
}
val mainFile = main.get
val mainModuleName = pkg.get.moduleNameForFile(mainFile).toString
runPackage(context, mainModuleName)
runPackage(context, mainModuleName, file)
} else {
runSingleFile(context, file)
}
@ -198,22 +202,81 @@ object Main {
private def runPackage(
context: PolyglotContext,
mainModuleName: String
mainModuleName: String,
projectPath: File
): Unit = {
val topScope = context.getTopScope
val mainModule = topScope.getModule(mainModuleName)
runMain(mainModule)
runMain(mainModule, Some(projectPath))
}
private def runSingleFile(context: PolyglotContext, file: File): Unit = {
val mainModule = context.evalModule(file)
runMain(mainModule)
runMain(mainModule, Some(file))
}
private def runMain(mainModule: Module): Value = {
private def printPolyglotException(
exception: PolyglotException,
relativeTo: Option[File]
): Unit = {
val fullStack = exception.getPolyglotStackTrace.asScala.toList
val dropInitJava = fullStack.reverse
.dropWhile(_.getLanguage.getId != LanguageInfo.ID)
.reverse
println(s"Execution finished with an error: ${exception.getMessage}")
dropInitJava.foreach { frame =>
val langId =
if (frame.isHostFrame) "java" else frame.getLanguage.getId
val fmtFrame = if (frame.getLanguage.getId == LanguageInfo.ID) {
val fName = frame.getRootName
val src = Option(frame.getSourceLocation)
.map { sourceLoc =>
val ident = Option(sourceLoc.getSource.getPath)
.map { path =>
relativeTo match {
case None => path
case Some(root) =>
val absRoot = root.getAbsoluteFile
if (path.startsWith(absRoot.getAbsolutePath)) {
val rootDir =
if (absRoot.isDirectory) absRoot
else absRoot.getParentFile
rootDir.toPath.relativize(new File(path).toPath).toString
} else {
path
}
}
}
.getOrElse(sourceLoc.getSource.getName)
val loc = if (sourceLoc.getStartLine == sourceLoc.getEndLine) {
val line = sourceLoc.getStartLine
val start = sourceLoc.getStartColumn
val end = sourceLoc.getEndColumn
s"$line:$start-$end"
} else {
s"${sourceLoc.getStartLine}-${sourceLoc.getEndLine}"
}
s"$ident:$loc"
}
.getOrElse("Internal")
s"$fName($src)"
} else {
frame.toString
}
println(s" at <$langId> $fmtFrame")
}
}
private def runMain(mainModule: Module, rootPkgPath: Option[File]): Value = {
val mainCons = mainModule.getAssociatedConstructor
val mainFun = mainModule.getMethod(mainCons, "main")
mainFun.execute(mainCons.newInstance())
try {
mainFun.execute(mainCons.newInstance())
} catch {
case e: PolyglotException =>
printPolyglotException(e, rootPkgPath)
exitFail()
}
}
/**
@ -226,7 +289,7 @@ object Main {
new ContextFactory().create("", System.in, System.out, Repl(TerminalIO()))
val mainModule =
context.evalModule(dummySourceToTriggerRepl, replModuleName)
runMain(mainModule)
runMain(mainModule, None)
exitSuccess()
}
@ -299,7 +362,6 @@ object Main {
val line: CommandLine = Try(parser.parse(options, args)).getOrElse {
printHelp(options)
exitFail()
return
}
if (line.hasOption(HELP_OPTION)) {
printHelp(options)

View File

@ -8,10 +8,14 @@ import com.oracle.truffle.api.frame.FrameInstanceVisitor;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrumentation.*;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.RootNode;
import org.enso.interpreter.node.EnsoRootNode;
import org.enso.interpreter.node.ExpressionNode;
import org.enso.interpreter.node.MethodRootNode;
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode;
import org.enso.interpreter.runtime.tag.IdentifiedTag;
import org.enso.interpreter.runtime.type.Types;
import org.enso.pkg.QualifiedName;
import java.util.HashMap;
import java.util.Map;
@ -114,7 +118,8 @@ public class IdExecutionInstrument extends TruffleInstrument {
/** Information about the function call. */
public static class FunctionCallInfo {
private final String callTargetName;
private final QualifiedName moduleName;
private final QualifiedName typeName;
private final String functionName;
/**
@ -123,16 +128,34 @@ public class IdExecutionInstrument extends TruffleInstrument {
* @param call the function call.
*/
public FunctionCallInfo(FunctionCallInstrumentationNode.FunctionCall call) {
this.callTargetName = call.getFunction().getCallTarget().getRootNode().getQualifiedName();
this.functionName = call.getFunction().getName();
RootNode rootNode = call.getFunction().getCallTarget().getRootNode();
if (rootNode instanceof MethodRootNode) {
MethodRootNode methodNode = (MethodRootNode) rootNode;
moduleName = methodNode.getModuleScope().getModule().getName();
typeName = methodNode.getAtomConstructor().getQualifiedName();
functionName = methodNode.getMethodName();
} else if (rootNode instanceof EnsoRootNode) {
moduleName = ((EnsoRootNode) rootNode).getModuleScope().getModule().getName();
typeName = null;
functionName = rootNode.getName();
} else {
moduleName = null;
typeName = null;
functionName = rootNode.getQualifiedName();
}
}
/** @return call target name. */
public String getCallTargetName() {
return callTargetName;
/** @return the name of the module this function was defined in, or null if not available. */
public QualifiedName getModuleName() {
return moduleName;
}
/** @return function name. */
/** @return the name of the type this method was defined for, or null if not a method. */
public QualifiedName getTypeName() {
return typeName;
}
/** @return the name of this function. */
public String getFunctionName() {
return functionName;
}

View File

@ -22,19 +22,16 @@ import org.enso.interpreter.runtime.state.Stateful;
public class ClosureRootNode extends EnsoRootNode {
@Child private ExpressionNode body;
private final String qualifiedName;
private ClosureRootNode(
ClosureRootNode(
Language language,
LocalScope localScope,
ModuleScope moduleScope,
ExpressionNode body,
SourceSection section,
String name,
String qualifiedName) {
String name) {
super(language, localScope, moduleScope, name, section);
this.body = body;
this.qualifiedName = qualifiedName;
}
/**
@ -54,10 +51,9 @@ public class ClosureRootNode extends EnsoRootNode {
ModuleScope moduleScope,
ExpressionNode body,
SourceSection section,
String name,
String qualifiedName) {
String name) {
return new ClosureRootNode(
language, localScope, moduleScope, body, section, name, qualifiedName);
language, localScope, moduleScope, body, section, name);
}
/**
@ -74,14 +70,4 @@ public class ClosureRootNode extends EnsoRootNode {
state = FrameUtil.getObjectSafe(frame, this.getStateFrameSlot());
return new Stateful(state, result);
}
/**
* Returns a qualified name that uniquely identifies the node.
*
* @return a qualified name of this node.
*/
@Override
public String getQualifiedName() {
return qualifiedName;
}
}

View File

@ -0,0 +1,94 @@
package org.enso.interpreter.node;
import com.oracle.truffle.api.dsl.ReportPolymorphism;
import com.oracle.truffle.api.frame.FrameUtil;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.source.SourceSection;
import org.enso.interpreter.Language;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.scope.LocalScope;
import org.enso.interpreter.runtime.scope.ModuleScope;
import org.enso.interpreter.runtime.state.Stateful;
@ReportPolymorphism
@NodeInfo(shortName = "Method", description = "A root node for Enso methods.")
public class MethodRootNode extends ClosureRootNode {
private final AtomConstructor atomConstructor;
private final String methodName;
private MethodRootNode(
Language language,
LocalScope localScope,
ModuleScope moduleScope,
ExpressionNode body,
SourceSection section,
AtomConstructor atomConstructor,
String methodName) {
super(
language,
localScope,
moduleScope,
body,
section,
shortName(atomConstructor.getName(), methodName));
this.atomConstructor = atomConstructor;
this.methodName = methodName;
}
private static String shortName(String atomName, String methodName) {
return atomName + "." + methodName;
}
/**
* Creates an instance of this node.
*
* @param language the language identifier
* @param localScope a description of the local scope
* @param moduleScope a description of the module scope
* @param body the program body to be executed
* @param section a mapping from {@code body} to the program source
* @param atomConstructor the constructor this method is defined for
* @param methodName the name of this method
* @return a node representing the specified closure
*/
public static MethodRootNode build(
Language language,
LocalScope localScope,
ModuleScope moduleScope,
ExpressionNode body,
SourceSection section,
AtomConstructor atomConstructor,
String methodName) {
return new MethodRootNode(
language, localScope, moduleScope, body, section, atomConstructor, methodName);
}
/**
* Computes the fully qualified name of this method.
*
* <p>The name has a form of [method's module]::[qualified type name]::[method name].
*
* @return the qualified name of this method.
*/
@Override
public String getQualifiedName() {
return getModuleScope().getModule().getName().toString()
+ "::"
+ atomConstructor.getQualifiedName().toString()
+ "::"
+ methodName;
}
/** @return the constructor this method was defined for */
public AtomConstructor getAtomConstructor() {
return atomConstructor;
}
/** @return the method name */
public String getMethodName() {
return methodName;
}
}

View File

@ -6,9 +6,12 @@ import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.Source;
import org.enso.interpreter.Language;
import org.enso.interpreter.runtime.Context;
import org.enso.interpreter.runtime.Module;
import org.enso.pkg.QualifiedName;
import java.io.File;
/**
* This node handles static transformation of the input AST before execution and represents the root
* of an Enso program.
@ -48,15 +51,26 @@ public class ProgramRootNode extends RootNode {
public Object execute(VirtualFrame frame) {
if (module == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
QualifiedName name = QualifiedName.simpleName(canonicalizeName(sourceCode.getName()));
Context ctx = lookupContextReference(Language.class).get();
module =
new Module(
QualifiedName.simpleName(sourceCode.getName()),
sourceCode.getCharacters().toString());
sourceCode.getPath() != null
? new Module(name, ctx.getTruffleFile(new File(sourceCode.getPath())))
: new Module(name, sourceCode.getCharacters().toString());
}
// Note [Static Passes]
return module;
}
private String canonicalizeName(String name) {
String[] segs = name.split("\\.");
if (segs.length == 0) {
return "Unnamed";
} else {
return segs[0];
}
}
/* Note [Static Passes]
* ~~~~~~~~~~~~~~~~~~~~
* Almost all of the static analysis functionality required by the interpreter requires access to

View File

@ -58,9 +58,7 @@ public abstract class EvalNode extends BaseNode {
RootCallTarget parseExpression(LocalScope scope, ModuleScope moduleScope, String expression) {
LocalScope localScope = scope.createChild();
InlineContext inlineContext =
InlineContext.fromJava(
localScope, moduleScope, isTail());
InlineContext inlineContext = InlineContext.fromJava(localScope, moduleScope, isTail());
ExpressionNode expr =
lookupContextReference(Language.class)
.get()
@ -81,8 +79,7 @@ public abstract class EvalNode extends BaseNode {
moduleScope,
expr,
null,
"<dynamic_eval>",
null);
"<eval>");
return Truffle.getRuntime().createCallTarget(framedNode);
}

View File

@ -39,10 +39,10 @@ public class Module implements TruffleObject {
private boolean isParsed = false;
private boolean isIndexed = false;
private IR ir;
private final QualifiedName name;
private QualifiedName name;
private Module(TruffleFile sourceFile, Rope literalSource,
boolean isParsed, IR ir, QualifiedName name) {
private Module(
TruffleFile sourceFile, Rope literalSource, boolean isParsed, IR ir, QualifiedName name) {
this.sourceFile = sourceFile;
this.literalSource = literalSource;
this.isParsed = isParsed;
@ -205,17 +205,10 @@ public class Module implements TruffleObject {
/**
* Renames a project part of the QualifiedName of this module.
*
* @param oldName the old project name
* @param newName the new project name
* @return a module with the updated QualifiedName
*/
public Module renameProject(String oldName, String newName) {
if (name.path().head().equals(oldName)) {
QualifiedName renamed = name.renameProject(oldName, newName);
return new Module(sourceFile, literalSource, false, ir, renamed);
} else {
return this;
}
public void renameProject(String newName) {
this.name = name.renameProject(newName);
}
/** @return the indexed flag. */

View File

@ -18,6 +18,7 @@ import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
import org.enso.interpreter.runtime.scope.ModuleScope;
import org.enso.pkg.QualifiedName;
import java.util.HashMap;
import java.util.Map;
@ -181,4 +182,9 @@ public class AtomConstructor implements TruffleObject {
}
return newInstance(arguments);
}
/** @return the fully qualified name of this constructor. */
public QualifiedName getQualifiedName() {
return definitionScope.getModule().getName().createChild(getName());
}
}

View File

@ -28,7 +28,7 @@ public class ModuleScope {
*/
public ModuleScope(Module module) {
this.module = module;
this.associatedType = new AtomConstructor(module.getName().module(), this).initializeFields();
this.associatedType = new AtomConstructor(module.getName().item(), this).initializeFields();
}
/**

View File

@ -24,21 +24,18 @@ import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* Represents the top scope of Enso execution, containing all the importable modules.
*/
/** Represents the top scope of Enso execution, containing all the importable modules. */
@ExportLibrary(InteropLibrary.class)
public class TopLevelScope implements TruffleObject {
private final Builtins builtins;
private final Map<String, Module> modules;
private final Scope scope = Scope.newBuilder("top_scope", this).build();
/**
* Creates a new instance of top scope.
*
* @param builtins the automatically-imported builtin module.
* @param modules the initial modules this scope contains.
* @param modules the initial modules this scope contains.
*/
public TopLevelScope(Builtins builtins, Map<String, Module> modules) {
this.builtins = builtins;
@ -70,7 +67,7 @@ public class TopLevelScope implements TruffleObject {
/**
* Creates and registers a new module with given name and source file.
*
* @param name the module name.
* @param name the module name.
* @param sourceFile the module source file.
* @return the newly created module.
*/
@ -89,19 +86,17 @@ public class TopLevelScope implements TruffleObject {
public void renameProjectInModules(String oldName, String newName) {
String separator = QualifiedName$.MODULE$.separator();
List<String> keys =
modules
.keySet()
.stream()
modules.keySet().stream()
.filter(name -> name.startsWith(oldName + separator))
.collect(Collectors.toList());
keys
.stream()
keys.stream()
.map(modules::remove)
.map(module -> module.renameProject(oldName, newName))
.forEach(module -> {
modules.put(module.getName().toString(), module);
});
.forEach(
module -> {
module.renameProject(newName);
modules.put(module.getName().toString(), module);
});
}
/**
@ -140,9 +135,7 @@ public class TopLevelScope implements TruffleObject {
MethodNames.TopScope.UNREGISTER_MODULE);
}
/**
* Handles member invocation through the polyglot API.
*/
/** Handles member invocation through the polyglot API. */
@ExportMessage
abstract static class InvokeMember {
private static Module getModule(

View File

@ -39,6 +39,7 @@ import org.enso.interpreter.node.expression.literal.{
import org.enso.interpreter.node.scope.{AssignmentNode, ReadLocalVariableNode}
import org.enso.interpreter.node.{
ClosureRootNode,
MethodRootNode,
ExpressionNode => RuntimeExpression
}
import org.enso.interpreter.runtime.Context
@ -217,34 +218,39 @@ class IrToTruffle(
dataflowInfo
)
val funNode = methodDef.body match {
val cons = moduleScope
.getConstructor(typeName)
.orElseThrow(() =>
new VariableDoesNotExistException(methodDef.typeName.name)
)
val function = methodDef.body match {
case fn: IR.Function =>
expressionProcessor.processFunctionBody(
fn.arguments,
fn.body,
methodDef.location,
Some(methodDef.methodName.name)
val (body, arguments) =
expressionProcessor.buildFunctionBody(fn.arguments, fn.body)
val rootNode = MethodRootNode.build(
language,
expressionProcessor.scope,
moduleScope,
body,
makeSection(methodDef.location),
cons,
methodDef.methodName.name
)
val callTarget = Truffle.getRuntime.createCallTarget(rootNode)
new RuntimeFunction(
callTarget,
null,
new FunctionSchema(
FunctionSchema.CallStrategy.CALL_LOOP,
arguments: _*
)
)
case _ =>
throw new CompilerError(
"Method bodies must be functions at the point of codegen."
)
}
val function = new RuntimeFunction(
funNode.getCallTarget,
null,
new FunctionSchema(
FunctionSchema.CallStrategy.CALL_LOOP,
funNode.getArgs: _*
)
)
val cons = moduleScope
.getConstructor(typeName)
.orElseThrow(() =>
new VariableDoesNotExistException(methodDef.typeName.name)
)
moduleScope.registerMethod(cons, methodDef.methodName.name, function)
})
}
@ -300,7 +306,7 @@ class IrToTruffle(
val scopeName: String
) {
private var currentVarName = "anonymous"
private var currentVarName = "<anonymous>"
// === Construction =======================================================
@ -412,15 +418,14 @@ class IrToTruffle(
childScope,
moduleScope,
blockNode,
null,
s"default::$scopeName",
null
makeSection(block.location),
currentVarName
)
val callTarget = Truffle.getRuntime.createCallTarget(defaultRootNode)
setLocation(CreateThunkNode.build(callTarget), block.location)
} else {
val statementExprs = block.expressions.map(this.run(_)).toArray
val statementExprs = block.expressions.map(this.run).toArray
val retExpr = this.run(block.returnValue)
val blockNode = BlockNode.build(statementExprs, retExpr)
@ -520,8 +525,7 @@ class IrToTruffle(
val branchCodeNode = childProcessor.processFunctionBody(
arg,
branch.expression,
branch.location,
None
branch.location
)
val branchNode = CatchAllBranchNode.build(branchCodeNode)
@ -542,8 +546,7 @@ class IrToTruffle(
val branchCodeNode = childProcessor.processFunctionBody(
fieldsAsArgs,
branch.expression,
branch.location,
None
branch.location
)
moduleScope.getConstructor(constructor.name).toScala match {
@ -659,8 +662,7 @@ class IrToTruffle(
val fn = child.processFunctionBody(
function.arguments,
function.body,
function.location,
None
function.location
)
fn
@ -755,20 +757,19 @@ class IrToTruffle(
setLocation(ErrorNode.build(payload), error.location)
}
/** Generates code for an Enso function body.
/**
* Processes function arguments, generates arguments reads and creates
* a node to represent the whole method body.
*
* @param arguments the arguments to the function
* @param body the body of the function
* @param location the location at which the function exists in the source
* @param name the name of the function
* @return a truffle node representing the described function
* @param arguments the argument definitions
* @param body the body definition
* @return a node for the final shape of function body and pre-processed
* argument definitions.
*/
def processFunctionBody(
def buildFunctionBody(
arguments: List[IR.DefinitionArgument],
body: IR.Expression,
location: Option[IdentifiedLocation],
name: Option[String]
): CreateFunctionNode = {
body: IR.Expression
): (BlockNode, Array[ArgumentDefinition]) = {
val argFactory = new DefinitionArgumentProcessor(scopeName, scope)
val argDefinitions = new Array[ArgumentDefinition](arguments.size)
@ -809,24 +810,35 @@ class IrToTruffle(
val bodyExpr = this.run(body)
val fnBodyNode = BlockNode.build(argExpressions.toArray, bodyExpr)
fnBodyNode.setTail(bodyIsTail)
(fnBodyNode, argDefinitions)
}
/** Generates code for an Enso function body.
*
* @param arguments the arguments to the function
* @param body the body of the function
* @param location the location at which the function exists in the source
* @return a truffle node representing the described function
*/
def processFunctionBody(
arguments: List[IR.DefinitionArgument],
body: IR.Expression,
location: Option[IdentifiedLocation]
): CreateFunctionNode = {
val (fnBodyNode, argDefinitions) = buildFunctionBody(arguments, body)
val fnRootNode = ClosureRootNode.build(
language,
scope,
moduleScope,
fnBodyNode,
makeSection(location),
scopeName,
name
.map(moduleScope.getModule.getName.createChild)
.map(_.toString)
.orNull
scopeName
)
val callTarget = Truffle.getRuntime.createCallTarget(fnRootNode)
val expr = CreateFunctionNode.build(callTarget, argDefinitions)
fnBodyNode.setTail(bodyIsTail)
setLocation(expr, location)
}
@ -987,7 +999,7 @@ class IrToTruffle(
argumentExpression.setTail(argExpressionIsTail)
val displayName =
s"call_argument<${name.getOrElse(String.valueOf(position))}>"
s"argument<${name.getOrElse(String.valueOf(position))}>"
val section = value.location
.map(loc => source.createSection(loc.start, loc.end))
@ -1000,8 +1012,7 @@ class IrToTruffle(
moduleScope,
argumentExpression,
section,
displayName,
null
displayName
)
)
@ -1077,8 +1088,7 @@ class IrToTruffle(
moduleScope,
defaultExpression,
null,
s"default::$scopeName::${arg.name}",
null
s"<default::$scopeName::${arg.name}>"
)
CreateThunkNode.build(

View File

@ -22,7 +22,6 @@ import org.enso.interpreter.instrument.{
Visualisation
}
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode.FunctionCall
import org.enso.pkg.QualifiedName
import org.enso.polyglot.runtime.Runtime.Api
import org.enso.polyglot.runtime.Runtime.Api.ContextId
@ -255,10 +254,9 @@ trait ProgramExecutionSupport {
)(implicit ctx: RuntimeContext): Option[Api.MethodPointer] =
for {
call <- Option(value.getCallInfo)
qualifiedName <- QualifiedName.fromString(call.getCallTargetName)
moduleName <- qualifiedName.getParent
functionName <- QualifiedName.fromString(call.getFunctionName)
typeName <- functionName.getParent
moduleName <- Option(call.getModuleName)
functionName = call.getFunctionName
typeName <- Option(call.getTypeName).map(_.item)
module <- OptionConverters.toScala(
ctx.executionService.getContext.getTopScope
.getModule(moduleName.toString)
@ -266,8 +264,8 @@ trait ProgramExecutionSupport {
modulePath <- Option(module.getPath)
} yield Api.MethodPointer(
new File(modulePath),
typeName.toString,
functionName.module
typeName,
functionName
)
}

View File

@ -1,15 +1,15 @@
package org.enso.pkg
/**
* Represents a qualified name of a source module.
* Represents a qualified name of a source item.
*
* @param path the names of the package and directories the module is
* @param path the names of the package and directories the item is
* contained in
* @param module the name of the module
* @param item the name of the item
*/
case class QualifiedName(path: List[String], module: String) {
case class QualifiedName(path: List[String], item: String) {
override def toString: String =
(path :+ module).mkString(QualifiedName.separator)
(path :+ item).mkString(QualifiedName.separator)
/**
* Get the parent of this qualified name.
@ -26,21 +26,16 @@ case class QualifiedName(path: List[String], module: String) {
* @return a new qualified name based on this name.
*/
def createChild(name: String): QualifiedName =
QualifiedName(path :+ module, name)
QualifiedName(path :+ item, name)
/**
* Renames a project part of this [[QualifiedName]].
*
* @param oldName the old project name
* @param newName the new project name
* @return a [[QualifiedName]] with the updated project name
*/
def renameProject(oldName: String, newName: String): QualifiedName = {
if (path.head == oldName) {
this.copy(path = newName :: path.tail)
} else {
this
}
def renameProject(newName: String): QualifiedName = {
this.copy(path = newName :: path.tail)
}
}

View File

@ -2,6 +2,6 @@ import Base.Test
import Test.List_Spec
import Test.Number_Spec
main = Suite.run <|
main = Suite.runMain <|
List_Spec.spec
Number_Spec.spec