diff --git a/src/org/rascalmpl/library/lang/rascal/tests/basic/Locations.rsc b/src/org/rascalmpl/library/lang/rascal/tests/basic/Locations.rsc index c0a674c3e27..2d9e4bdf301 100644 --- a/src/org/rascalmpl/library/lang/rascal/tests/basic/Locations.rsc +++ b/src/org/rascalmpl/library/lang/rascal/tests/basic/Locations.rsc @@ -518,4 +518,11 @@ test bool extensionSetSimple() // we don't want backslashes in windows -test bool correctTempPathResolverOnWindows() = /\\/ !:= resolveLocation(|tmp:///|).path; \ No newline at end of file +test bool correctTempPathResolverOnWindows() = /\\/ !:= resolveLocation(|tmp:///|).path; + +test bool encodingIsTheSameForPathAdditionAndTemplateInstantation() + = |file:///<"some path">/<"with spaces">| == |file:///| + "some path" + "with spaces"; + +test bool encodingDecodingPaths() + = (|file:///| + x).path == ((/^\// := x) ? x : "/") + when x := "some path right?"; \ No newline at end of file diff --git a/src/org/rascalmpl/semantics/dynamic/PathPart.java b/src/org/rascalmpl/semantics/dynamic/PathPart.java index b2a4def8fbc..4230b59f133 100644 --- a/src/org/rascalmpl/semantics/dynamic/PathPart.java +++ b/src/org/rascalmpl/semantics/dynamic/PathPart.java @@ -12,14 +12,21 @@ *******************************************************************************/ package org.rascalmpl.semantics.dynamic; +import java.net.URI; +import java.net.URISyntaxException; + import org.rascalmpl.ast.Expression; import org.rascalmpl.ast.PathChars; import org.rascalmpl.ast.PathTail; import org.rascalmpl.ast.PrePathChars; +import org.rascalmpl.exceptions.RuntimeExceptionFactory; import org.rascalmpl.interpreter.IEvaluator; import org.rascalmpl.interpreter.result.Result; +import org.rascalmpl.interpreter.result.ResultFactory; +import org.rascalmpl.uri.URIUtil; import io.usethesource.vallang.IConstructor; import io.usethesource.vallang.ISourceLocation; +import io.usethesource.vallang.IString; import io.usethesource.vallang.IValue; public abstract class PathPart extends org.rascalmpl.ast.PathPart { @@ -37,9 +44,29 @@ public Result interpret(IEvaluator> __eval) { Result pre = this.getPre().interpret(__eval); Result expr = this.getExpression().interpret(__eval); - Result tail = this.getTail().interpret(__eval); - - return pre.add(expr).add(tail); + // here we have to encode the string for us in the path part of a uri + // the trick is to use new File which does the encoding for us, in + // a way that conforms to the current OS where we are running. So if someone + // is splicing a windows path here, with the slashes the other way around, + // they are first interpreted as path separators and not encoded as %slash + // However, first we need to map the expression result to string by using + // the `add` semantics of strings: + IString path = (IString) ResultFactory.makeResult(TF.stringType(), VF.string(""), __eval) + .add(expr).getValue(); + + try { + // reuse our URI encoders here on the unencoded expression part + URI tmp = URIUtil.create("x", "", "/" + path.getValue()); + // but get the path out directly anyway, unencoded! + path = VF.string(tmp.getRawPath()); + + // connect the pre, middle and end pieces + Result tail = this.getTail().interpret(__eval); + return pre.add(ResultFactory.makeResult(TF.stringType(), path, __eval)).add(tail); + } + catch (URISyntaxException e) { + throw RuntimeExceptionFactory.malformedURI(path.getValue(), getExpression(), __eval.getStackTrace()); + } } } diff --git a/src/org/rascalmpl/semantics/dynamic/PathTail.java b/src/org/rascalmpl/semantics/dynamic/PathTail.java index ebe8a3807b7..219ed87cc1c 100644 --- a/src/org/rascalmpl/semantics/dynamic/PathTail.java +++ b/src/org/rascalmpl/semantics/dynamic/PathTail.java @@ -12,13 +12,21 @@ *******************************************************************************/ package org.rascalmpl.semantics.dynamic; +import java.net.URI; +import java.net.URISyntaxException; + import org.rascalmpl.ast.Expression; import org.rascalmpl.ast.MidPathChars; import org.rascalmpl.ast.PostPathChars; +import org.rascalmpl.exceptions.RuntimeExceptionFactory; import org.rascalmpl.interpreter.IEvaluator; import org.rascalmpl.interpreter.result.Result; +import org.rascalmpl.interpreter.result.ResultFactory; +import org.rascalmpl.uri.URIUtil; + import io.usethesource.vallang.IConstructor; import io.usethesource.vallang.ISourceLocation; +import io.usethesource.vallang.IString; import io.usethesource.vallang.IValue; public abstract class PathTail extends org.rascalmpl.ast.PathTail { @@ -34,9 +42,25 @@ public Mid(ISourceLocation __param1, IConstructor tree, MidPathChars __param2, E public Result interpret(IEvaluator> __eval) { Result mid = this.getMid().interpret(__eval); Result expr = this.getExpression().interpret(__eval); - Result tail = this.getTail().interpret(__eval); - return mid.add(expr).add(tail); + // The semantics of .add is used here to coerce different kinds of values + // to path strings (e.g. parse trees, string constants, type names) + IString path = (IString) ResultFactory.makeResult(TF.stringType(), VF.string(""), __eval) + .add(expr).getValue(); + + try { + // reuse our URI encoders here on the unencoded expression part + URI tmp = URIUtil.create("x", "", "/" + path.getValue()); + // but get the path out directly anyway, unencoded! + path = VF.string(tmp.getRawPath()); + + // connect the pre, middle and end pieces + Result tail = this.getTail().interpret(__eval); + return mid.add(ResultFactory.makeResult(TF.stringType(), path, __eval)).add(tail); + } + catch (URISyntaxException e) { + throw RuntimeExceptionFactory.malformedURI(path.getValue(), getExpression(), __eval.getStackTrace()); + } } } diff --git a/src/org/rascalmpl/test/infrastructure/RascalJUnitTestRunner.java b/src/org/rascalmpl/test/infrastructure/RascalJUnitTestRunner.java index a6dbd00c481..30f7abbfbcf 100644 --- a/src/org/rascalmpl/test/infrastructure/RascalJUnitTestRunner.java +++ b/src/org/rascalmpl/test/infrastructure/RascalJUnitTestRunner.java @@ -222,7 +222,7 @@ public Description getDescription() { // the order of the tests aren't decided by this list so no need to randomly order them. for (AbstractFunction f : tests) { - modDesc.addChild(Description.createTestDescription(clazz, computeTestName(f.getName(), f.getAst().getLocation()))); + modDesc.addChild(Description.createTestDescription(module, computeTestName(f.getName(), f.getAst().getLocation()))); } } catch (Throwable e) { @@ -241,7 +241,7 @@ public Class annotationType() { return true; } catch (IOException e) { - Description testDesc = Description.createTestDescription(clazz, prefix + " compilation failed: " + e.getMessage(), new CompilationFailed() { + Description testDesc = Description.createTestDescription(module, prefix + " compilation failed: " + e.getMessage(), new CompilationFailed() { @Override public Class annotationType() { return getClass(); @@ -264,7 +264,6 @@ public void run(final RunNotifier notifier) { if (desc == null) { desc = getDescription(); } - notifier.fireTestRunStarted(desc); for (Description mod : desc.getChildren()) { // TODO: this will never match because we are on the level of module descriptions now. @@ -280,8 +279,6 @@ public void run(final RunNotifier notifier) { TestEvaluator runner = new TestEvaluator(evaluator, listener); runner.test(mod.getDisplayName()); } - - notifier.fireTestRunFinished(new Result()); } private final class Listener implements ITestResultListener { @@ -308,7 +305,7 @@ private Description getDescription(String name, ISourceLocation loc) { @Override public void start(String context, int count) { - notifier.fireTestRunStarted(module); + // notifier.fireTestRunStarted(module); } @Override @@ -331,7 +328,7 @@ public void report(boolean successful, String test, ISourceLocation loc, String @Override public void done() { - notifier.fireTestRunFinished(new Result()); + // notifier.fireTestRunFinished(new Result()); } } }