8247456: JShell: Handling of top-level final, abstract, and static modifiers

Reviewed-by: jlahoda
This commit is contained in:
Robert Field 2020-09-02 09:37:25 -07:00
parent a588752fd6
commit 261eb76ea2
13 changed files with 149 additions and 87 deletions

View File

@ -50,6 +50,8 @@ import jdk.jshell.Wrap.CompoundWrap;
import jdk.jshell.Wrap.Range;
import jdk.jshell.Wrap.RangeWrap;
import java.util.Set;
/**
* Produce a corralled version of the Wrap for a snippet.
*/
@ -227,17 +229,21 @@ class Corraller extends Visitor {
bodyBegin = -1;
}
}
if (bodyBegin > 0) {
//debugWrap("-visitMethodDef BEGIN: %d = '%s'\n", bodyBegin,
// source.substring(methodBegin, bodyBegin));
Range noBodyRange = new Range(methodBegin, bodyBegin);
result = new CompoundWrap(
new RangeWrap(source, noBodyRange),
resolutionExceptionBlock);
String adjustedSource;
if (bodyBegin < 0) {
adjustedSource = new MaskCommentsAndModifiers(source, Set.of("abstract")).cleared();
bodyBegin = adjustedSource.charAt(methodEnd - 1) == ';'
? methodEnd - 1
: methodEnd;
} else {
Range range = new Range(methodBegin, methodEnd);
result = new RangeWrap(source, range);
adjustedSource = source;
}
debugWrap("-visitMethodDef BEGIN: %d = '%s'\n", bodyBegin,
adjustedSource.substring(methodBegin, bodyBegin));
Range noBodyRange = new Range(methodBegin, bodyBegin);
result = new CompoundWrap(
new RangeWrap(adjustedSource, noBodyRange),
resolutionExceptionBlock);
}
// Remove initializer, if present

View File

@ -76,6 +76,9 @@ import static java.util.stream.Collectors.toSet;
import static java.util.Collections.singletonList;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN;
import static jdk.jshell.Snippet.Status.RECOVERABLE_DEFINED;
import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED;
import static jdk.jshell.Snippet.Status.VALID;
import static jdk.jshell.Util.DOIT_METHOD_NAME;
import static jdk.jshell.Util.PREFIX_PATTERN;
import static jdk.jshell.Util.expunge;
@ -777,21 +780,40 @@ class Eval {
.map(param -> dis.treeToRange(param.getType()).part(compileSource))
.collect(Collectors.joining(","));
Tree returnType = mt.getReturnType();
DiagList modDiag = modifierDiagnostics(mt.getModifiers(), dis, true);
MethodKey key = state.keyMap.keyForMethod(name, parameterTypes);
// Corralling
Wrap corralled = new Corraller(dis, key.index(), compileSource).corralMethod(mt);
DiagList modDiag = modifierDiagnostics(mt.getModifiers(), dis, false);
if (modDiag.hasErrors()) {
return compileFailResult(modDiag, userSource, Kind.METHOD);
}
Wrap guts = Wrap.classMemberWrap(compileSource);
MethodKey key = state.keyMap.keyForMethod(name, parameterTypes);
Wrap corralled;
Wrap guts;
String unresolvedSelf;
if (mt.getModifiers().getFlags().contains(Modifier.ABSTRACT)) {
if (mt.getBody() == null) {
// abstract method -- pre-corral
corralled = null; // no fall-back
guts = new Corraller(dis, key.index(), compileSource).corralMethod(mt);
unresolvedSelf = "method " + name + "(" + parameterTypes + ")";
} else {
// abstract with body, don't pollute the error message
corralled = null;
guts = Wrap.simpleWrap(compileSource);
unresolvedSelf = null;
}
} else {
// normal method
corralled = new Corraller(dis, key.index(), compileSource).corralMethod(mt);
guts = Wrap.classMemberWrap(compileSource);
unresolvedSelf = null;
}
Range typeRange = dis.treeToRange(returnType);
String signature = "(" + parameterTypes + ")" + typeRange.part(compileSource);
Snippet snip = new MethodSnippet(key, userSource, guts,
name, signature,
corralled, tds.declareReferences(), tds.bodyReferences(), modDiag);
corralled, tds.declareReferences(), tds.bodyReferences(),
unresolvedSelf, modDiag);
return singletonList(snip);
}
@ -891,6 +913,18 @@ class Eval {
ins.add(c);
Set<Unit> outs = compileAndLoad(ins);
if (si.status().isActive() && si instanceof MethodSnippet) {
// special processing for abstract methods
MethodSnippet msi = (MethodSnippet) si;
String unresolvedSelf = msi.unresolvedSelf;
if (unresolvedSelf != null) {
List<String> unresolved = new ArrayList<>(si.unresolved());
unresolved.add(unresolvedSelf);
si.setCompilationStatus(si.status() == VALID ? RECOVERABLE_DEFINED : si.status(),
unresolved, si.diagnostics());
}
}
if (!si.status().isDefined()
&& si.diagnostics().isEmpty()
&& si.unresolved().isEmpty()) {
@ -1251,6 +1285,9 @@ class Eval {
fatal = true;
break;
case ABSTRACT:
// for classes, abstract is valid
// for variables, generate an error message
// for methods, we generate a placeholder method
if (isAbstractProhibited) {
list.add(mod);
fatal = true;
@ -1266,7 +1303,7 @@ class Eval {
//final classes needed for sealed classes
break;
case STATIC:
list.add(mod);
// everything is static -- warning just adds noise when pasting
break;
}
}

View File

@ -40,8 +40,11 @@ class MaskCommentsAndModifiers {
Stream.of( "public", "protected", "private", "static" )
.collect( Collectors.toSet() );
private final static Set<String> OTHER_MODIFIERS =
Stream.of( "abstract", "strictfp", "transient", "volatile", "synchronized", "native", "default", "final" )
private final static Set<String> ALL_MODIFIERS =
Stream.of(
"public", "protected", "private",
"static", "abstract", "final",
"strictfp", "transient", "volatile", "synchronized", "native", "default" )
.collect( Collectors.toSet() );
// Builder to accumulate non-masked characters
@ -56,6 +59,9 @@ class MaskCommentsAndModifiers {
// Entire input string length
private final int length;
// Which modifiers to mask-out
private final Set<String> ignoredModifiers;
// The next character position
private int next = 0;
@ -70,9 +76,18 @@ class MaskCommentsAndModifiers {
private boolean openToken = false;
MaskCommentsAndModifiers(String s, boolean maskModifiers) {
this(s, maskModifiers, IGNORED_MODIFIERS);
}
MaskCommentsAndModifiers(String s, Set<String> ignoredModifiers) {
this(s, true, ignoredModifiers);
}
MaskCommentsAndModifiers(String s, boolean maskModifiers, Set<String> ignoredModifiers) {
this.str = s;
this.length = s.length();
this.maskModifiers = maskModifiers;
this.ignoredModifiers = ignoredModifiers;
read();
while (c >= 0) {
next();
@ -250,11 +265,11 @@ class MaskCommentsAndModifiers {
} while (Character.isJavaIdentifierPart(c));
unread();
String id = sb.toString();
if (maskModifiers && IGNORED_MODIFIERS.contains(id)) {
if (maskModifiers && ignoredModifiers.contains(id)) {
writeMask(sb);
} else {
write(sb);
if (maskModifiers && !OTHER_MODIFIERS.contains(id)) {
if (maskModifiers && !ALL_MODIFIERS.contains(id)) {
maskModifiers = false;
}
}

View File

@ -42,15 +42,18 @@ import jdk.jshell.Key.MethodKey;
public class MethodSnippet extends DeclarationSnippet {
final String signature;
final String unresolvedSelf;
private String qualifiedParameterTypes;
MethodSnippet(MethodKey key, String userSource, Wrap guts,
String name, String signature, Wrap corralled,
Collection<String> declareReferences, Collection<String> bodyReferences,
String unresolvedSelf,
DiagList syntheticDiags) {
super(key, userSource, guts, name, SubKind.METHOD_SUBKIND, corralled,
declareReferences, bodyReferences, syntheticDiags);
this.signature = signature;
this.unresolvedSelf = unresolvedSelf;
}
/**

View File

@ -237,7 +237,6 @@ final class Unit {
if (dl.hasErrors()) {
setDiagnostics(dl);
status = RECOVERABLE_NOT_DEFINED;
// overwrite orginal bytes
state.debug(DBG_GEN, "++smashingErrorDiagnostics %s\n%s\n-- diags: %s\n",
si, si.outerWrap().wrapped(), dl);
return true;

View File

@ -23,10 +23,10 @@
# questions.
#
jshell.diag.modifier.plural.fatal = Modifiers {0} not permitted in top-level declarations
jshell.diag.modifier.plural.ignore = Modifiers {0} not permitted in top-level declarations, ignored
jshell.diag.modifier.single.fatal = Modifier {0} not permitted in top-level declarations
jshell.diag.modifier.single.ignore = Modifier {0} not permitted in top-level declarations, ignored
jshell.diag.modifier.plural.fatal = Modifiers {0} not permitted
jshell.diag.modifier.plural.ignore = Modifiers {0} not permitted, ignored
jshell.diag.modifier.single.fatal = Modifier {0} not permitted
jshell.diag.modifier.single.ignore = Modifier {0} not permitted, ignored
jshell.diag.object.method.fatal = JShell method names must not match Object methods: {0}
jshell.exc.null = Snippet must not be null

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, 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
@ -23,7 +23,7 @@
/*
* @test
* @bug 8145239 8129559 8080354 8189248 8010319 8246353
* @bug 8145239 8129559 8080354 8189248 8010319 8246353 8247456
* @summary Tests for EvaluationState.classes
* @build KullaTesting TestingInputStream ExpectedDiagnostic
* @run testng ClassesTest
@ -249,29 +249,23 @@ public class ClassesTest extends KullaTesting {
public void classesIgnoredModifiers() {
assertEval("public interface A { }");
assertDeclareWarn1("static class B implements A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING));
assertDeclareWarn1("static interface C extends A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING));
assertEval("static class B implements A { }");
assertEval("static interface C extends A { }");
assertActiveKeys();
}
public void classesIgnoredModifiersAnnotation() {
assertEval("public @interface X { }");
assertEval("@X public interface A { }");
assertDeclareWarn1("@X static class B implements A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 9, 0, -1, -1, Diagnostic.Kind.WARNING));
assertDeclareWarn1("@X static interface C extends A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 9, 0, -1, -1, Diagnostic.Kind.WARNING));
assertEval("@X static class B implements A { }");
assertEval("@X static interface C extends A { }");
assertActiveKeys();
}
public void classesIgnoredModifiersOtherModifiers() {
assertEval("strictfp public interface A { }");
assertDeclareWarn1("strictfp static class B implements A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 15, 0, -1, -1, Diagnostic.Kind.WARNING));
assertDeclareWarn1("strictfp static interface C extends A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 15, 0, -1, -1, Diagnostic.Kind.WARNING));
assertEval("strictfp static class B implements A { }");
assertEval("strictfp static interface C extends A { }");
assertActiveKeys();
}

View File

@ -73,21 +73,6 @@ public class ErrorTranslationTest extends ReplToolTesting {
);
}
public void testWarnings() {
List<ReplTest> list = new ArrayList<>();
ExpectedDiagnostic[] diagnostics = new ExpectedDiagnostic[]{
newExpectedDiagnostic(0, 6, 0, -1, -1, Diagnostic.Kind.WARNING),
newExpectedDiagnostic(0, 5, 0, -1, -1, Diagnostic.Kind.WARNING)};
String[] mods = {"static"};
for (int i = 0; i < mods.length; ++i) {
for (String code : new String[] {"class A {}", "void f() {}", "int a;"}) {
final int finalI = i;
list.add(a -> assertDiagnostic(a, mods[finalI] + " " + code, diagnostics[finalI]));
}
}
test(list.toArray(new ReplTest[list.size()]));
}
@Test(enabled = false) // TODO 8132147
public void stressTest() {
Compiler compiler = new Compiler();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, 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
@ -23,7 +23,7 @@
/*
* @test
* @bug 8129559 8246353
* @bug 8129559 8246353 8247456
* @summary Test the ignoring of comments and certain modifiers
* @build KullaTesting TestingInputStream
* @run testng IgnoreTest
@ -65,8 +65,8 @@ public class IgnoreTest extends KullaTesting {
assertVariableDeclSnippet(x2, "x2", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x3 = varKey(assertEval("private int x3;"));
assertVariableDeclSnippet(x3, "x3", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x4 = (VarSnippet) assertDeclareWarn1("static int x4;", "jdk.eval.warn.illegal.modifiers");
assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
VarSnippet x4 = varKey(assertEval("static int x4;"));
assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x5 = varKey(assertEval("final int x5;"));
assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
}
@ -79,8 +79,8 @@ public class IgnoreTest extends KullaTesting {
assertVariableDeclSnippet(x2, "x2", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x3 = varKey(assertEval("@A(value=111)private int x3;"));
assertVariableDeclSnippet(x3, "x3", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x4 = (VarSnippet) assertDeclareWarn1("@A static int x4;", "jdk.eval.warn.illegal.modifiers");
assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
VarSnippet x4 = varKey(assertEval("@A static int x4;"));
assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x5 = varKey(assertEval("@A(1111) final int x5;"));
assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
}
@ -92,8 +92,8 @@ public class IgnoreTest extends KullaTesting {
assertVariableDeclSnippet(x2, "x2", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x3 = varKey(assertEval("transient private int x3;"));
assertVariableDeclSnippet(x3, "x3", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x4 = (VarSnippet) assertDeclareWarn1("volatile static int x4;", "jdk.eval.warn.illegal.modifiers");
assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
VarSnippet x4 = varKey(assertEval("volatile static int x4;"));
assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x5 = varKey(assertEval("transient final int x5;"));
assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
}
@ -105,23 +105,23 @@ public class IgnoreTest extends KullaTesting {
}
public void testMethodModifier() {
MethodSnippet m4 = (MethodSnippet) assertDeclareWarn1("static void m4() {}", "jdk.eval.warn.illegal.modifiers");
assertMethodDeclSnippet(m4, "m4", "()void", VALID, 0, 1);
MethodSnippet m4 = methodKey(assertEval("static void m4() {}"));
assertMethodDeclSnippet(m4, "m4", "()void", VALID, 0, 0);
MethodSnippet m5 = methodKey(assertEval("final void m5() {}"));
assertMethodDeclSnippet(m5, "m5", "()void", VALID, 0, 0);
}
public void testMethodModifierAnnotation() {
assertEval("@interface A { int value() default 0; }");
MethodSnippet m4 = (MethodSnippet) assertDeclareWarn1("@A static void m4() {}", "jdk.eval.warn.illegal.modifiers");
assertMethodDeclSnippet(m4, "m4", "()void", VALID, 0, 1);
MethodSnippet m4 = methodKey(assertEval("@A static void m4() {}"));
assertMethodDeclSnippet(m4, "m4", "()void", VALID, 0, 0);
MethodSnippet m5 = methodKey(assertEval("@A(value=66)final void m5() {}"));
assertMethodDeclSnippet(m5, "m5", "()void", VALID, 0, 0);
}
public void testClassModifier() {
TypeDeclSnippet c4 = (TypeDeclSnippet) assertDeclareWarn1("static class C4 {}", "jdk.eval.warn.illegal.modifiers");
assertTypeDeclSnippet(c4, "C4", VALID, CLASS_SUBKIND, 0, 1);
TypeDeclSnippet c4 = classKey(assertEval("static class C4 {}"));
assertTypeDeclSnippet(c4, "C4", VALID, CLASS_SUBKIND, 0, 0);
TypeDeclSnippet c5 = classKey(assertEval("final class C5 {}"));
assertTypeDeclSnippet(c5, "C5", VALID, CLASS_SUBKIND, 0, 0);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, 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
@ -23,7 +23,7 @@
/*
* @test
* @bug 8080357 8167643 8187359 8199762 8080353 8246353
* @bug 8080357 8167643 8187359 8199762 8080353 8246353 8247456
* @summary Tests for EvaluationState.methods
* @build KullaTesting TestingInputStream ExpectedDiagnostic
* @run testng MethodsTest
@ -36,7 +36,11 @@ import jdk.jshell.MethodSnippet;
import jdk.jshell.Snippet.Status;
import org.testng.annotations.Test;
import java.util.List;
import java.util.stream.Collectors;
import static jdk.jshell.Snippet.Status.*;
import static org.testng.Assert.assertEquals;
@Test
public class MethodsTest extends KullaTesting {
@ -216,17 +220,28 @@ public class MethodsTest extends KullaTesting {
assertActiveKeys();
}
public void methodsAbstract() {
MethodSnippet m1 = methodKey(assertEval("abstract String f();",
ste(MAIN_SNIPPET, NONEXISTENT, RECOVERABLE_DEFINED, true, null)));
assertEquals(getState().unresolvedDependencies(m1).collect(Collectors.toList()),
List.of("method f()"));
MethodSnippet m2 = methodKey(assertEval("abstract int mm(Blah b);",
ste(MAIN_SNIPPET, NONEXISTENT, RECOVERABLE_NOT_DEFINED, false, null)));
List<String> unr = getState().unresolvedDependencies(m2).collect(Collectors.toList());
assertEquals(unr.size(), 2);
unr.remove("class Blah");
unr.remove("method mm(Blah)");
assertEquals(unr.size(), 0, "unexpected entry: " + unr);
assertNumberOfActiveMethods(2);
assertActiveKeys();
}
public void methodsErrors() {
assertDeclareFail("String f();",
new ExpectedDiagnostic("compiler.err.missing.meth.body.or.decl.abstract", 0, 11, 7, -1, -1, Diagnostic.Kind.ERROR));
assertNumberOfActiveMethods(0);
assertActiveKeys();
assertDeclareFail("abstract String f();",
new ExpectedDiagnostic("jdk.eval.error.illegal.modifiers", 0, 8, 0, -1, -1, Diagnostic.Kind.ERROR));
assertNumberOfActiveMethods(0);
assertActiveKeys();
assertDeclareFail("native String f();",
new ExpectedDiagnostic("jdk.eval.error.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.ERROR));
assertNumberOfActiveMethods(0);
@ -290,10 +305,8 @@ public class MethodsTest extends KullaTesting {
assertActiveKeys();
}
public void methodsWarn() {
Snippet f = assertDeclareWarn1("static String f() {return null;}",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING),
added(VALID));
public void methodsIgnoredModifiers() {
Snippet f = methodKey(assertEval("static String f() {return null;}"));
assertNumberOfActiveMethods(1);
assertActiveKeys();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, 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
@ -22,7 +22,7 @@
*/
/*
* @test 8167643 8129559
* @test 8167643 8129559 8247456
* @summary Tests for modifiers
* @build KullaTesting TestingInputStream ExpectedDiagnostic
* @run testng ModifiersTest
@ -44,10 +44,9 @@ public class ModifiersTest extends KullaTesting {
public Object[][] getTestCases() {
List<Object[]> testCases = new ArrayList<>();
String[] ignoredModifiers = new String[] {
"static"
};
String[] silentlyIgnoredModifiers = new String[] {
"public", "protected", "private"
"public", "protected", "private", "static"
};
String[] before = new String[] {
"strictfp", "abstract", "final", "@X", "@X(value=9)"

View File

@ -699,8 +699,7 @@ public class ToolBasicTest extends ReplToolTesting {
a -> assertCommand(a, "/set feedback " + off, ""),
a -> assertCommand(a, "int a", ""),
a -> assertCommand(a, "void f() {}", ""),
a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("| Error:")),
a -> assertCommandCheckOutput(a, "static void f() {}", assertStartsWith("| Warning:"))
a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("| 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 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 8198801 8210596 8210959 8215099 8199623 8236715 8239536
* @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154 8192979 8191842 8198573 8198801 8210596 8210959 8215099 8199623 8236715 8239536 8247456
* @summary Simple jshell tool tests
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@ -270,6 +270,18 @@ public class ToolSimpleTest extends ReplToolTesting {
);
}
@Test
public void testAbstractMethod() {
test(
(a) -> assertCommand(a, "abstract int f(int x);",
"| created method f(int), however, it cannot be invoked until method f(int) is declared"),
(a) -> assertCommand(a, "f(13)",
"| attempted to call method f(int) which cannot be invoked until method f(int) is declared"),
(a) -> assertCommand(a, " abstract void m(Blah b);",
"| created method m(Blah), however, it cannot be referenced until class Blah, and method m(Blah) are declared")
);
}
// 8199623
@Test
public void testTwoForkedDrop() {