Skip to content

Commit 5291430

Browse files
committed
Refactor to fix more bugs and increase regression test coverage.
1 parent d31e7b4 commit 5291430

File tree

10 files changed

+137
-74
lines changed

10 files changed

+137
-74
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5715,13 +5715,14 @@ private Type capture(Type type) {
57155715
}
57165716

57175717
private void setSyntheticVariableType(JCVariableDecl tree, Type type) {
5718-
// Only set an ending position when the source contains an explicit type (i.e., "var")
5719-
if (tree.declaredUsingVar()) {
5720-
make.at(tree.varPos(), tree.varPos() + names.var.length(), env.toplevel.endPositions);
5718+
if (type.isErroneous()) {
5719+
tree.vartype = make.at(tree.pos()).Erroneous();
5720+
} else if (tree.declaredUsingVar()) { // set the type's start and end positions to match the "var" keyword
5721+
Assert.check(tree.typePos != Position.NOPOS);
5722+
tree.vartype = make.at(tree.typePos, tree.typePos + names.var.length(), env.toplevel.endPositions).Type(type);
57215723
} else {
5722-
make.at(tree.pos());
5724+
tree.vartype = make.at(tree.pos()).Type(type);
57235725
}
5724-
tree.vartype = type.isErroneous() ? make.Erroneous() : make.Type(type);
57255726
}
57265727

57275728
public void validateTypeAnnotations(JCTree tree, boolean sigOnly) {

src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,14 +1005,12 @@ public JCPattern parsePattern(int pos, JCModifiers mods, JCExpression parsedType
10051005
pattern = toP(F.at(token.pos).AnyPattern());
10061006
}
10071007
else {
1008-
int declaredUsingVarPos = Position.NOPOS;
1008+
int varTypePos = Position.NOPOS;
10091009
if (parsedType == null) {
10101010
boolean var = token.kind == IDENTIFIER && token.name() == names.var;
1011-
if (var) {
1012-
declaredUsingVarPos = token.pos;
1013-
}
10141011
e = unannotatedType(allowVar, TYPE | NOLAMBDA);
10151012
if (var) {
1013+
varTypePos = e.pos;
10161014
e = null;
10171015
}
10181016
} else {
@@ -1050,9 +1048,10 @@ public void visitAnnotatedType(JCAnnotatedType tree) {
10501048
if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) {
10511049
name = names.empty;
10521050
}
1053-
JCVariableDecl var = toP(F.at(varPos).VarDef(mods, name, e, null, declaredUsingVarPos));
1051+
JCVariableDecl var = toP(F.at(varPos).VarDef(mods, name, e, null,
1052+
varTypePos != Position.NOPOS ? JCVariableDecl.DeclKind.VAR : JCVariableDecl.DeclKind.EXPLICIT,
1053+
varTypePos));
10541054
if (e == null) {
1055-
var.startPos = pos;
10561055
if (var.name == names.underscore && !allowVar) {
10571056
log.error(DiagnosticFlag.SYNTAX, varPos, Errors.UseOfUnderscoreNotAllowed);
10581057
}
@@ -2194,7 +2193,8 @@ JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitPara
21942193
if (param.vartype != null
21952194
&& restrictedTypeName(param.vartype, true) != null) {
21962195
checkSourceLevel(param.pos, Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS);
2197-
param.startPos = TreeInfo.getStartPos(param.vartype);
2196+
param.declKind = JCVariableDecl.DeclKind.VAR;
2197+
param.typePos = TreeInfo.getStartPos(param.vartype);
21982198
param.vartype = null;
21992199
}
22002200
}
@@ -3808,7 +3808,7 @@ JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean r
38083808
*/
38093809
JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
38103810
boolean reqInit, Comment dc, boolean localDecl, boolean compound) {
3811-
int varPos = Position.NOPOS;
3811+
boolean declaredUsingVar = false;
38123812
JCExpression init = null;
38133813
type = bracketsOpt(type);
38143814

@@ -3834,7 +3834,7 @@ JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression ty
38343834
syntaxError(token.pos, Errors.Expected(EQ));
38353835
}
38363836

3837-
int startPos = Position.NOPOS;
3837+
int varTypePos = Position.NOPOS;
38383838
JCTree elemType = TreeInfo.innermostType(type, true);
38393839
if (elemType.hasTag(IDENT)) {
38403840
Name typeName = ((JCIdent) elemType).name;
@@ -3845,20 +3845,18 @@ JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression ty
38453845
//error - 'var' and arrays
38463846
reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedArray(typeName));
38473847
} else {
3848-
varPos = elemType.pos;
3848+
declaredUsingVar = true;
3849+
varTypePos = elemType.pos;
38493850
if (compound)
38503851
//error - 'var' in compound local var decl
38513852
reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedCompound(typeName));
3852-
startPos = TreeInfo.getStartPos(mods);
3853-
if (startPos == Position.NOPOS)
3854-
startPos = TreeInfo.getStartPos(type);
38553853
//implicit type
38563854
type = null;
38573855
}
38583856
}
38593857
}
3860-
JCVariableDecl result = toP(F.at(pos).VarDef(mods, name, type, init, varPos));
3861-
result.startPos = startPos;
3858+
JCVariableDecl result = toP(F.at(pos).VarDef(mods, name, type, init,
3859+
declaredUsingVar ? JCVariableDecl.DeclKind.VAR : JCVariableDecl.DeclKind.EXPLICIT, varTypePos));
38623860
return attach(result, dc);
38633861
}
38643862

@@ -3972,8 +3970,11 @@ JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean
39723970
name = names.empty;
39733971
}
39743972

3975-
return toP(F.at(pos).VarDef(mods, name, type, null,
3976-
type != null && type.hasTag(IDENT) && ((JCIdent)type).name == names.var ? type.pos : Position.NOPOS));
3973+
boolean declaredUsingVar = type != null && type.hasTag(IDENT) && ((JCIdent)type).name == names.var;
3974+
JCVariableDecl.DeclKind declKind = declaredUsingVar ? JCVariableDecl.DeclKind.VAR :
3975+
type != null ? JCVariableDecl.DeclKind.EXPLICIT : JCVariableDecl.DeclKind.IMPLICIT;
3976+
int typePos = type != null ? type.pos : pos;
3977+
return toP(F.at(pos).VarDef(mods, name, type, null, declKind, typePos));
39773978
}
39783979

39793980
/** Resources = Resource { ";" Resources }

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,13 @@ public Tag getTag() {
10101010
* A variable definition.
10111011
*/
10121012
public static class JCVariableDecl extends JCStatement implements VariableTree {
1013+
1014+
public enum DeclKind {
1015+
EXPLICIT, // "SomeType name"
1016+
IMPLICIT, // "name"
1017+
VAR, // "var name"
1018+
}
1019+
10131020
/** variable modifiers */
10141021
public JCModifiers mods;
10151022
/** variable name */
@@ -1022,37 +1029,40 @@ public static class JCVariableDecl extends JCStatement implements VariableTree {
10221029
public JCExpression init;
10231030
/** symbol */
10241031
public VarSymbol sym;
1025-
/** explicit start pos */
1026-
public int startPos = Position.NOPOS;
1027-
/** if declared using "var", the "var" source position, otherwise NOPOS */
1028-
private final int varPos;
1032+
/** how the variable's type was declared */
1033+
public DeclKind declKind;
1034+
/** a source code position to use for "vartype" when null (can happen if declKind != EXPLICIT) */
1035+
public int typePos;
10291036

10301037
protected JCVariableDecl(JCModifiers mods,
10311038
Name name,
10321039
JCExpression vartype,
10331040
JCExpression init,
10341041
VarSymbol sym) {
1035-
this(mods, name, vartype, init, sym, Position.NOPOS);
1042+
this(mods, name, vartype, init, sym, DeclKind.EXPLICIT, Position.NOPOS);
10361043
}
10371044

10381045
protected JCVariableDecl(JCModifiers mods,
10391046
Name name,
10401047
JCExpression vartype,
10411048
JCExpression init,
10421049
VarSymbol sym,
1043-
int varPos) {
1050+
DeclKind declKind,
1051+
int typePos) {
10441052
this.mods = mods;
10451053
this.name = name;
10461054
this.vartype = vartype;
10471055
this.init = init;
10481056
this.sym = sym;
1049-
this.varPos = varPos;
1057+
this.declKind = declKind;
1058+
this.typePos = typePos;
1059+
Assert.check(vartype != null || typePos != Position.NOPOS);
10501060
}
10511061

10521062
protected JCVariableDecl(JCModifiers mods,
10531063
JCExpression nameexpr,
10541064
JCExpression vartype) {
1055-
this(mods, null, vartype, null, null, Position.NOPOS);
1065+
this(mods, null, vartype, null, null, DeclKind.EXPLICIT, Position.NOPOS);
10561066
this.nameexpr = nameexpr;
10571067
if (nameexpr.hasTag(Tag.IDENT)) {
10581068
this.name = ((JCIdent)nameexpr).name;
@@ -1067,11 +1077,7 @@ public boolean isImplicitlyTyped() {
10671077
}
10681078

10691079
public boolean declaredUsingVar() {
1070-
return varPos != Position.NOPOS;
1071-
}
1072-
1073-
public int varPos() {
1074-
return varPos;
1080+
return declKind == DeclKind.VAR;
10751081
}
10761082

10771083
@Override

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ public JCTree visitVariable(VariableTree node, P p) {
551551
JCExpression vartype = copy(t.vartype, p);
552552
if (t.nameexpr == null) {
553553
JCExpression init = copy(t.init, p);
554-
return M.at(t.pos).VarDef(mods, t.name, vartype, init);
554+
return M.at(t.pos).VarDef(mods, t.name, vartype, init, t.declKind, t.typePos);
555555
} else {
556556
JCExpression nameexpr = copy(t.nameexpr, p);
557557
return M.at(t.pos).ReceiverVarDef(mods, nameexpr, vartype);

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -610,17 +610,14 @@ public static int getStartPos(JCTree tree) {
610610
}
611611
case VARDEF: {
612612
JCVariableDecl node = (JCVariableDecl)tree;
613-
if (node.startPos != Position.NOPOS) {
614-
return node.startPos;
615-
} else if (node.mods.pos != Position.NOPOS) {
613+
if (node.mods.pos != Position.NOPOS) {
616614
return node.mods.pos;
617-
} else if (node.vartype == null || node.vartype.pos == Position.NOPOS) {
618-
//if there's no type (partially typed lambda parameter)
619-
//simply return node position
620-
return node.pos;
621-
} else {
615+
} else if (node.vartype != null) {
622616
return getStartPos(node.vartype);
617+
} else if (node.typePos != Position.NOPOS) {
618+
return node.typePos;
623619
}
620+
break;
624621
}
625622
case BINDINGPATTERN: {
626623
JCBindingPattern node = (JCBindingPattern)tree;

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,9 @@ public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype,
254254
return setPos(new JCVariableDecl(mods, name, vartype, init, null));
255255
}
256256

257-
public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init, int varPos) {
258-
return setPos(new JCVariableDecl(mods, name, vartype, init, null, varPos));
257+
public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init,
258+
JCVariableDecl.DeclKind declKind, int typePos) {
259+
return setPos(new JCVariableDecl(mods, name, vartype, init, null, declKind, typePos));
259260
}
260261

261262
public JCVariableDecl ReceiverVarDef(JCModifiers mods, JCExpression name, JCExpression vartype) {

src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ public Void visitMethod(MethodTree node, Void p) {
768768
@Override
769769
public Void visitVariable(VariableTree node, Void p) {
770770
int pos = ((JCTree) node).pos;
771-
if (sp.getEndPosition(cut, node.getType()) == (-1)) {
771+
if (node instanceof JCTree.JCVariableDecl varDecl && varDecl.declaredUsingVar()) {
772772
Token varCandidate = findTokensBefore(pos, TokenKind.IDENTIFIER);
773773
if (varCandidate != null && "var".equals(varCandidate.name().toString())) {
774774
addKeyword.accept(varCandidate);

test/langtools/tools/javac/parser/DeclarationEndPositions.java

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949

5050
public class DeclarationEndPositions {
5151

52-
public static void checkEndPosition(Class<? extends JCTree> nodeType, String input, String marker) throws IOException {
52+
public static void checkPositions(Class<? extends JCTree> nodeType, String input, String markers) throws IOException {
5353

5454
// Create source
5555
var source = new SimpleJavaFileObject(URI.create("file://T.java"), JavaFileObject.Kind.SOURCE) {
@@ -71,11 +71,26 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept
7171
public Void scan(Tree node, Void aVoid) {
7272
if (nodeType.isInstance(node)) {
7373
JCTree tree = (JCTree)node;
74-
int actual = TreeInfo.getEndPos(tree, unit.endPositions);
75-
int expected = marker.indexOf('^') + 1;
76-
if (actual != expected) {
74+
75+
// Verify declaration start and end positions
76+
int start = tree.getStartPosition();
77+
if (markers.charAt(start) != '<') {
78+
throw new AssertionError(String.format(
79+
"wrong %s pos %d for \"%s\" in \"%s\"", "start", start, tree, input));
80+
}
81+
int end = TreeInfo.getEndPos(tree, unit.endPositions);
82+
if (markers.charAt(end - 1) != '>') {
7783
throw new AssertionError(String.format(
78-
"wrong end pos %d != %d for \"%s\" @ %d", actual, expected, input, tree.pos));
84+
"wrong %s pos %d for \"%s\" in \"%s\"", "end", end, tree, input));
85+
}
86+
87+
// For variable declarations using "var", verify the "var" position
88+
if (tree instanceof JCVariableDecl varDecl && varDecl.declaredUsingVar()) {
89+
int vpos = varDecl.typePos;
90+
if (!input.substring(vpos).startsWith("var")) {
91+
throw new AssertionError(String.format(
92+
"wrong %s pos %d for \"%s\" in \"%s\"", "var", vpos, tree, input));
93+
}
7994
}
8095
}
8196
return super.scan(node, aVoid);
@@ -86,34 +101,71 @@ public Void scan(Tree node, Void aVoid) {
86101
public static void main(String... args) throws Exception {
87102

88103
// JCModuleDecl
89-
checkEndPosition(JCModuleDecl.class,
104+
checkPositions(JCModuleDecl.class,
90105
"/* comment */ module fred { /* comment */ } /* comment */",
91-
" ^ ");
106+
" <---------------------------> ");
92107

93108
// JCPackageDecl
94-
checkEndPosition(JCPackageDecl.class,
109+
checkPositions(JCPackageDecl.class,
95110
"/* comment */ package fred; /* comment */",
96-
" ^ ");
111+
" <-----------> ");
97112

98113
// JCClassDecl
99-
checkEndPosition(JCClassDecl.class,
114+
checkPositions(JCClassDecl.class,
100115
"/* comment */ class Fred { /* comment */ } /* comment */",
101-
" ^ ");
116+
" <--------------------------> ");
102117

103118
// JCMethodDecl
104-
checkEndPosition(JCMethodDecl.class,
119+
checkPositions(JCMethodDecl.class,
105120
"/* comment */ class Fred { void m() { /* comment */ } } /* comment */",
106-
" ^ ");
121+
" <------------------------> ");
107122

108123
// JCVariableDecl
109-
checkEndPosition(JCVariableDecl.class,
124+
checkPositions(JCVariableDecl.class,
110125
"/* comment */ class Fred { int x; } /* comment */",
111-
" ^ ");
112-
checkEndPosition(JCVariableDecl.class,
126+
" <----> ");
127+
checkPositions(JCVariableDecl.class,
113128
"/* comment */ class Fred { int x = 123; } /* comment */",
114-
" ^ ");
115-
checkEndPosition(JCVariableDecl.class,
116-
"/* comment */ class A { try {} catch (Error err) {} } /* comment */",
117-
" ^ ");
129+
" <----------> ");
130+
checkPositions(JCVariableDecl.class,
131+
"/* comment */ class Fred { final int x = 123; } /* comment */",
132+
" <----------------> ");
133+
checkPositions(JCVariableDecl.class,
134+
"/* comment */ class Fred { final int x = 123, y = 456; } /* comment */",
135+
" <---------------->--------> ");
136+
checkPositions(JCVariableDecl.class,
137+
"/* comment */ class A { void m() { try {} catch (Error err) {} } } /* comment */",
138+
" <-------> ");
139+
140+
// JCVariableDecl with "var" declarations
141+
checkPositions(JCVariableDecl.class,
142+
"class A { void m() { var foo; } }",
143+
" <------> ");
144+
checkPositions(JCVariableDecl.class,
145+
"class A { void m() { var foo = 42; } }",
146+
" <-----------> ");
147+
checkPositions(JCVariableDecl.class,
148+
"class A { void m() { final var foo = 42; } }",
149+
" <-----------------> ");
150+
151+
checkPositions(JCVariableDecl.class,
152+
"class A { void m() { java.util.function.Consumer<Byte> = foo -> { } } }",
153+
" <-> ");
154+
checkPositions(JCVariableDecl.class,
155+
"class A { void m() { java.util.function.Consumer<Byte> = (foo) -> { } } }",
156+
" <-> ");
157+
checkPositions(JCVariableDecl.class,
158+
"class A { void m() { java.util.function.Consumer<Byte> = (var foo) -> { } } }",
159+
" <-----> ");
160+
checkPositions(JCVariableDecl.class,
161+
"class A { void m() { java.util.function.Consumer<Byte> = (final var foo) -> { } } }",
162+
" <-----------> ");
163+
164+
checkPositions(JCVariableDecl.class,
165+
"class A { record R(int x) { } void m() { switch (null) { case R(var x) -> {} default -> {} } } }",
166+
" <---> <---> ");
167+
checkPositions(JCVariableDecl.class,
168+
"class A { record R(int x) { } void m() { switch (null) { case R(final var x) -> {} default -> {} } } }",
169+
" <---> <---------> ");
118170
}
119171
}

test/langtools/tools/javac/patterns/PrettyTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@ boolean t(Object o) {
7272
boolean _ = true;
7373
b = o instanceof String s;
7474
b = o instanceof R(String s);
75-
b = o instanceof R(/*missing*/ s);
76-
b = o instanceof R2(R(/*missing*/ s), String t);
77-
b = o instanceof R2(R(/*missing*/ s), /*missing*/ t);
75+
b = o instanceof R(var s);
76+
b = o instanceof R2(R(var s), String t);
77+
b = o instanceof R2(R(var s), var t);
7878
b = o instanceof R(String _);
79-
b = o instanceof R2(R(/*missing*/ _), /*missing*/ _);
80-
b = o instanceof R2(R(_), /*missing*/ t);
79+
b = o instanceof R2(R(var _), var _);
80+
b = o instanceof R2(R(_), var t);
8181
}
8282
\n\
8383
class R {

0 commit comments

Comments
 (0)