8173848: JShell: less-than causes: reached end of file while parsing
Reviewed-by: jlahoda
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Mon Feb 06 15:57:35 2017 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Mon Feb 06 09:00:02 2017 -0800
@@ -85,7 +85,7 @@
try {
Parser parser = new Parser(
() -> new Matched(scannerFactory.newScanner(s, false)),
- () -> proc.taskFactory.new ParseTask(s));
+ () -> proc.taskFactory.parse(s));
Completeness stat = parser.parseUnit();
int endPos = stat == Completeness.UNKNOWN
? s.length()
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Mon Feb 06 15:57:35 2017 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Mon Feb 06 09:00:02 2017 -0800
@@ -155,7 +155,7 @@
if (compileSource.length() == 0) {
return Collections.emptyList();
}
- ParseTask pt = state.taskFactory.new ParseTask(compileSource);
+ ParseTask pt = state.taskFactory.parse(compileSource);
List<? extends Tree> units = pt.units();
if (units.isEmpty()) {
return compileFailResult(pt, userSource, Kind.ERRONEOUS);
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java Mon Feb 06 15:57:35 2017 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java Mon Feb 06 09:00:02 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,6 @@
import static com.sun.tools.javac.parser.Tokens.TokenKind.INTERFACE;
import static com.sun.tools.javac.parser.Tokens.TokenKind.LPAREN;
import static com.sun.tools.javac.parser.Tokens.TokenKind.MONKEYS_AT;
-import static com.sun.tools.javac.parser.Tokens.TokenKind.PACKAGE;
import static com.sun.tools.javac.parser.Tokens.TokenKind.SEMI;
import static com.sun.tools.javac.parser.Tokens.TokenKind.VOID;
import com.sun.tools.javac.tree.JCTree;
@@ -48,10 +47,8 @@
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
-import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
-import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.Tag;
import static com.sun.tools.javac.tree.JCTree.Tag.IDENT;
import com.sun.tools.javac.util.List;
@@ -68,12 +65,17 @@
*/
class ReplParser extends JavacParser {
+ // force starting in expression mode
+ private final boolean forceExpression;
+
public ReplParser(ParserFactory fac,
com.sun.tools.javac.parser.Lexer S,
boolean keepDocComments,
boolean keepLineMap,
- boolean keepEndPositions) {
+ boolean keepEndPositions,
+ boolean forceExpression) {
super(fac, S, keepDocComments, keepLineMap, keepEndPositions);
+ this.forceExpression = forceExpression;
}
/**
@@ -205,7 +207,10 @@
nextToken();
} else {
// return type of method, declared type of variable, or an expression
- t = term(EXPR | TYPE);
+ // unless expression is being forced
+ t = term(forceExpression
+ ? EXPR
+ : EXPR | TYPE);
}
if (token.kind == COLON && t.hasTag(IDENT)) {
// labelled statement
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParserFactory.java Mon Feb 06 15:57:35 2017 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParserFactory.java Mon Feb 06 09:00:02 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,25 +36,26 @@
*/
class ReplParserFactory extends ParserFactory {
- public static ParserFactory instance(Context context) {
- ParserFactory instance = context.get(parserFactoryKey);
- if (instance == null) {
- instance = new ReplParserFactory(context);
- }
- return instance;
+ // force starting in expression mode
+ private final boolean forceExpression;
+
+ public static void preRegister(Context context, boolean forceExpression) {
+ context.put(parserFactoryKey, (Context.Factory<ParserFactory>)
+ (c -> new ReplParserFactory(c, forceExpression)));
}
private final ScannerFactory scannerFactory;
- protected ReplParserFactory(Context context) {
+ protected ReplParserFactory(Context context, boolean forceExpression) {
super(context);
+ this.forceExpression = forceExpression;
this.scannerFactory = ScannerFactory.instance(context);
}
@Override
public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) {
com.sun.tools.javac.parser.Lexer lexer = scannerFactory.newScanner(input, keepDocComments);
- return new ReplParser(this, lexer, keepDocComments, keepLineMap, keepEndPos);
+ return new ReplParser(this, lexer, keepDocComments, keepLineMap, keepEndPos, forceExpression);
}
@Override
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Mon Feb 06 15:57:35 2017 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Mon Feb 06 09:00:02 2017 -0800
@@ -227,7 +227,7 @@
}
private Tree.Kind guessKind(String code) {
- ParseTask pt = proc.taskFactory.new ParseTask(code);
+ ParseTask pt = proc.taskFactory.parse(code);
List<? extends Tree> units = pt.units();
if (units.isEmpty()) {
return Tree.Kind.BLOCK;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Mon Feb 06 15:57:35 2017 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Mon Feb 06 09:00:02 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,6 +61,7 @@
import javax.tools.FileObject;
import jdk.jshell.MemoryFileManager.SourceMemoryJavaFileObject;
import java.lang.Runtime.Version;
+import com.sun.source.tree.Tree.Kind;
/**
* The primary interface to the compiler API. Parsing, analysis, and
@@ -100,6 +101,23 @@
return fileManager;
}
+ // Parse a snippet and return our parse task handler
+ ParseTask parse(final String source) {
+ ParseTask pt = state.taskFactory.new ParseTask(source, false);
+ if (!pt.units().isEmpty()
+ && pt.units().get(0).getKind() == Kind.EXPRESSION_STATEMENT
+ && pt.getDiagnostics().hasOtherThanNotStatementErrors()) {
+ // It failed, it may be an expression being incorrectly
+ // parsed as having a leading type variable, example: a < b
+ // Try forcing interpretation as an expression
+ ParseTask ept = state.taskFactory.new ParseTask(source, true);
+ if (!ept.getDiagnostics().hasOtherThanNotStatementErrors()) {
+ return ept;
+ }
+ }
+ return pt;
+ }
+
private interface SourceHandler<T> {
JavaFileObject sourceToFileObject(MemoryFileManager fm, T t);
@@ -179,11 +197,11 @@
private final Iterable<? extends CompilationUnitTree> cuts;
private final List<? extends Tree> units;
- ParseTask(final String source) {
+ ParseTask(final String source, final boolean forceExpression) {
super(Stream.of(source),
new StringSourceHandler(),
"-XDallowStringFolding=false", "-proc:none");
- ReplParserFactory.instance(getContext());
+ ReplParserFactory.preRegister(getContext(), forceExpression);
cuts = parse();
units = Util.stream(cuts)
.flatMap(cut -> {
--- a/langtools/test/jdk/jshell/SimpleRegressionTest.java Mon Feb 06 15:57:35 2017 +0100
+++ b/langtools/test/jdk/jshell/SimpleRegressionTest.java Mon Feb 06 09:00:02 2017 -0800
@@ -22,7 +22,7 @@
*/
/*
- * @test 8130450 8158906 8154374 8166400 8171892
+ * @test 8130450 8158906 8154374 8166400 8171892 8173848
* @summary simple regression test
* @build KullaTesting TestingInputStream
* @run testng SimpleRegressionTest
@@ -76,6 +76,15 @@
assertEval("c;", "600");
}
+ public void testLessThanParsing() {
+ assertEval("int x = 3;", "3");
+ assertEval("int y = 4;", "4");
+ assertEval("int z = 5;", "5");
+ assertEval("x < y", "true");
+ assertEval("x < y;", "true");
+ assertEval("x < y && y < z", "true");
+ }
+
public void testNotStmtCannotResolve() {
assertDeclareFail("dfasder;", new ExpectedDiagnostic("compiler.err.cant.resolve.location", 0, 7, 0, -1, -1, Diagnostic.Kind.ERROR));
}
--- a/langtools/test/jdk/jshell/ToolSimpleTest.java Mon Feb 06 15:57:35 2017 +0100
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java Mon Feb 06 09:00:02 2017 -0800
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073
+ * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848
* @summary Simple jshell tool tests
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -74,6 +74,18 @@
}
@Test
+ public void testLessThan() {
+ test(
+ (a) -> assertCommand(a, "45", "$1 ==> 45"),
+ (a) -> assertCommand(a, "72", "$2 ==> 72"),
+ (a) -> assertCommand(a, "$1 < $2", "$3 ==> true"),
+ (a) -> assertCommand(a, "int a, b", "a ==> 0\n" +
+ "b ==> 0"),
+ (a) -> assertCommand(a, "a < b", "$6 ==> false")
+ );
+ }
+
+ @Test
public void oneLineOfError() {
test(
(a) -> assertCommand(a, "12+", null),