Skip to content

Commit 08d731a

Browse files
authored
fix/issue 2679 (#2680)
* make sure errors are attached with the importing module if the imported module does not exist anymore to prevent later NPEs and loss of information on the current state of the import graph * changed reloader root location from reloader:/// to prompt:/// to remove a superfluous scheme and to highlight to the user that the origin of the reloading mechanism is the REPL. If a module was imported by the REPL and the reload fails because the file has dissappeared, then this will be the error location
1 parent ceb1554 commit 08d731a

2 files changed

Lines changed: 18 additions & 11 deletions

File tree

src/org/rascalmpl/repl/rascal/RascalInterpreterREPL.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ public ICommandOutput handleInput(String command) throws InterruptedException, P
231231
changes.addAll(dirtyModules);
232232
if (!changes.isEmpty()) {
233233
dirtyModules.removeAll(changes);
234-
eval.reloadModules(eval.getMonitor(), changes, URIUtil.rootLocation("reloader"));
234+
eval.reloadModules(eval.getMonitor(), changes, URIUtil.rootLocation("prompt"));
235235
}
236236
return printer.outputResult(eval.eval(eval.getMonitor(), command, PROMPT_LOCATION));
237237
}

src/org/rascalmpl/semantics/dynamic/Import.java

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ public static ITree parseModuleAndFragments(char[] data, ISourceLocation locatio
480480
ISet extend = Modules.getExtends(top);
481481
eval.getMonitor().jobTodo(jobName, extend.size());
482482
for (IValue mod : extend) {
483-
evalImport(eval, (IConstructor) mod);
483+
evalImport(eval, env, (IConstructor) mod);
484484
eval.getMonitor().jobStep(jobName, "extending for " + name, 1);
485485
if (eval.isInterrupted()) {
486486
throw new InterruptException(eval.getStackTrace(), eval.getCurrentAST().getLocation());
@@ -503,7 +503,7 @@ public static ITree parseModuleAndFragments(char[] data, ISourceLocation locatio
503503
ISet imports = Modules.getImports(top);
504504
eval.getMonitor().jobTodo(jobName, imports.size());
505505
for (IValue mod : imports) {
506-
evalImport(eval, (IConstructor) mod);
506+
evalImport(eval, env, (IConstructor) mod);
507507
eval.getMonitor().jobStep(jobName, "importing for " + name, 1);
508508
if (eval.isInterrupted()) {
509509
throw new InterruptException(eval.getStackTrace(), eval.getCurrentAST().getLocation());
@@ -515,7 +515,7 @@ public static ITree parseModuleAndFragments(char[] data, ISourceLocation locatio
515515
ISet externals = Modules.getExternals(top);
516516
eval.getMonitor().jobTodo(jobName, externals.size());
517517
for (IValue mod : externals) {
518-
evalImport(eval, (IConstructor) mod);
518+
evalImport(eval, env, (IConstructor) mod);
519519
eval.getMonitor().jobStep(jobName, "external importing for " + name, 1);
520520
if (eval.isInterrupted()) {
521521
throw new InterruptException(eval.getStackTrace(), eval.getCurrentAST().getLocation());
@@ -575,28 +575,35 @@ private static void declareTypesWhichDoNotNeedImportedModulesAlready(IEvaluator<
575575
eval.__getTypeDeclarator().evaluateDeclarations(decls, eval.getCurrentEnvt(), true);
576576
}
577577

578-
public static void evalImport(IEvaluator<Result<IValue>> eval, IConstructor mod) {
578+
/**
579+
* Evaluate an import/extend statement in the current module environment, effectively implementing the semantics of import and extend,
580+
* and handle any errors that may occur.
581+
*
582+
* NB. all errors that flow up to here are reported with the importing module because they make the import/extend unavailable here.
583+
* Errors inside of those modules that do not impact this module directly, should have been reported earlier with the module in question, during {@link #loadModule()}.
584+
* It is possible that the ModuleEnvironment for the imported/extended module does not even exist here anymore.
585+
*/
586+
public static void evalImport(IEvaluator<Result<IValue>> eval, ModuleEnvironment importer, IConstructor mod) {
579587
org.rascalmpl.ast.Import imp = (org.rascalmpl.ast.Import) getBuilder().buildValue(mod);
580-
String name = Names.fullName(imp.getModule().getName());
581588

582589
try {
583590
imp.interpret(eval);
584591
}
585-
catch (Throw rascalException) {
592+
catch (Throw rascalException) {
586593
// when a global initializer throws a runtime exception
587-
handleLoadError(eval.getHeap().getModule(name), rascalException.getMessage(), rascalException.getLocation(), rascalException.getTrace().toString());
594+
handleLoadError(importer, rascalException.getMessage(), rascalException.getLocation(), rascalException.getTrace().toString());
588595
}
589596
catch (CyclicExtend | CyclicImportExtend e) {
590597
// when we end up in a cycle which we can't implement
591-
handleLoadError(eval.getHeap().getModule(name), e.getMessage(), e.getLocation(), "");
598+
handleLoadError(importer, e.getMessage(), e.getLocation(), "");
592599
}
593600
catch (StaticError e) {
594601
// all other static errors
595-
handleLoadError(eval.getHeap().getModule(name), e.getMessage(), e.getLocation(), "");
602+
handleLoadError(importer, e.getMessage(), e.getLocation(), "");
596603
}
597604
catch (Throwable e) {
598605
// all internal implementation errors that mess up a module's loading
599-
handleLoadError(eval.getHeap().getModule(name), e.getMessage(), imp.getLocation(),
606+
handleLoadError(importer, e.getMessage(), imp.getLocation(),
600607
Arrays.stream(e.getStackTrace())
601608
.map(Object::toString)
602609
.collect(Collectors.joining("\n")));

0 commit comments

Comments
 (0)