8173848: JShell: less-than causes: reached end of file while parsing

Reviewed-by: jlahoda
This commit is contained in:
Robert Field 2017-02-06 09:00:02 -08:00
parent eb5ba01b02
commit 43593d5bf5
8 changed files with 68 additions and 23 deletions

View File

@ -85,7 +85,7 @@ class CompletenessAnalyzer {
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()

View File

@ -155,7 +155,7 @@ class Eval {
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);

View File

@ -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.IMPORT;
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.JCCompilationUnit;
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 @@ import com.sun.tools.javac.util.Position;
*/
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 @@ class ReplParser extends JavacParser {
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

View File

@ -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 @@ import com.sun.tools.javac.util.Context;
*/
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

View File

@ -227,7 +227,7 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis {
}
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;

View File

@ -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.lang.model.util.Elements;
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 @@ class TaskFactory {
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 @@ class TaskFactory {
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 -> {

View File

@ -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 @@ public class SimpleRegressionTest extends KullaTesting {
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));
}

View File

@ -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
@ -73,6 +73,18 @@ public class ToolSimpleTest extends ReplToolTesting {
);
}
@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(