diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 9c9672151c7da..70efe7d38b729 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1264,14 +1264,14 @@ public void visitVarDef(JCVariableDecl tree) { if (tree.init == null) { //cannot use 'var' without initializer log.error(tree, Errors.CantInferLocalVarType(tree.name, Fragments.LocalMissingInit)); - tree.vartype = make.Erroneous(); + tree.vartype = make.at(tree.pos()).Erroneous(); } else { Fragment msg = canInferLocalVarType(tree); if (msg != null) { //cannot use 'var' with initializer which require an explicit target //(e.g. lambda, method reference, array initializer). log.error(tree, Errors.CantInferLocalVarType(tree.name, msg)); - tree.vartype = make.Erroneous(); + tree.vartype = make.at(tree.pos()).Erroneous(); } } } @@ -5717,6 +5717,9 @@ private Type capture(Type type) { private void setSyntheticVariableType(JCVariableDecl tree, Type type) { if (type.isErroneous()) { tree.vartype = make.at(tree.pos()).Erroneous(); + } else if (tree.declaredUsingVar()) { // set the type's start and end positions to match the "var" keyword + Assert.check(tree.typePos != Position.NOPOS); + tree.vartype = make.at(tree.typePos, tree.typePos + names.var.length(), env.toplevel.endPositions).Type(type); } else { tree.vartype = make.at(tree.pos()).Type(type); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index 7ebcd0c844b2a..bb29bcbfbcb3d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -1005,10 +1005,12 @@ public JCPattern parsePattern(int pos, JCModifiers mods, JCExpression parsedType pattern = toP(F.at(token.pos).AnyPattern()); } else { + int varTypePos = Position.NOPOS; if (parsedType == null) { boolean var = token.kind == IDENTIFIER && token.name() == names.var; e = unannotatedType(allowVar, TYPE | NOLAMBDA); if (var) { + varTypePos = e.pos; e = null; } } else { @@ -1046,9 +1048,10 @@ public void visitAnnotatedType(JCAnnotatedType tree) { if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) { name = names.empty; } - JCVariableDecl var = toP(F.at(varPos).VarDef(mods, name, e, null)); + JCVariableDecl var = toP(F.at(varPos).VarDef(mods, name, e, null, + varTypePos != Position.NOPOS ? JCVariableDecl.DeclKind.VAR : JCVariableDecl.DeclKind.EXPLICIT, + varTypePos)); if (e == null) { - var.startPos = pos; if (var.name == names.underscore && !allowVar) { log.error(DiagnosticFlag.SYNTAX, varPos, Errors.UseOfUnderscoreNotAllowed); } @@ -2190,7 +2193,8 @@ JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitPara if (param.vartype != null && restrictedTypeName(param.vartype, true) != null) { checkSourceLevel(param.pos, Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS); - param.startPos = TreeInfo.getStartPos(param.vartype); + param.declKind = JCVariableDecl.DeclKind.VAR; + param.typePos = TreeInfo.getStartPos(param.vartype); param.vartype = null; } } @@ -3830,7 +3834,7 @@ JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression ty syntaxError(token.pos, Errors.Expected(EQ)); } - int startPos = Position.NOPOS; + int varTypePos = Position.NOPOS; JCTree elemType = TreeInfo.innermostType(type, true); if (elemType.hasTag(IDENT)) { Name typeName = ((JCIdent) elemType).name; @@ -3842,19 +3846,17 @@ JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression ty reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedArray(typeName)); } else { declaredUsingVar = true; + varTypePos = elemType.pos; if (compound) //error - 'var' in compound local var decl reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedCompound(typeName)); - startPos = TreeInfo.getStartPos(mods); - if (startPos == Position.NOPOS) - startPos = TreeInfo.getStartPos(type); //implicit type type = null; } } } - JCVariableDecl result = toP(F.at(pos).VarDef(mods, name, type, init, declaredUsingVar)); - result.startPos = startPos; + JCVariableDecl result = toP(F.at(pos).VarDef(mods, name, type, init, + declaredUsingVar ? JCVariableDecl.DeclKind.VAR : JCVariableDecl.DeclKind.EXPLICIT, varTypePos)); return attach(result, dc); } @@ -3968,8 +3970,11 @@ JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean name = names.empty; } - return toP(F.at(pos).VarDef(mods, name, type, null, - type != null && type.hasTag(IDENT) && ((JCIdent)type).name == names.var)); + boolean declaredUsingVar = type != null && type.hasTag(IDENT) && ((JCIdent)type).name == names.var; + JCVariableDecl.DeclKind declKind = declaredUsingVar ? JCVariableDecl.DeclKind.VAR : + type != null ? JCVariableDecl.DeclKind.EXPLICIT : JCVariableDecl.DeclKind.IMPLICIT; + int typePos = type != null ? type.pos : pos; + return toP(F.at(pos).VarDef(mods, name, type, null, declKind, typePos)); } /** Resources = Resource { ";" Resources } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java index debc10c9ff87e..eeb6f8e1b624a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -463,7 +463,15 @@ public String toString() { /** Set position field and return this tree. */ public JCTree setPos(int pos) { + return setPos(pos, Position.NOPOS, null); + } + + /** Set start and end position and return this tree. + */ + public JCTree setPos(int pos, int endPos, EndPosTable endPosTable) { this.pos = pos; + if (endPos != Position.NOPOS && endPosTable != null) + endPosTable.storeEnd(this, endPos); return this; } @@ -1002,6 +1010,13 @@ public Tag getTag() { * A variable definition. */ public static class JCVariableDecl extends JCStatement implements VariableTree { + + public enum DeclKind { + EXPLICIT, // "SomeType name" + IMPLICIT, // "name" + VAR, // "var name" + } + /** variable modifiers */ public JCModifiers mods; /** variable name */ @@ -1014,17 +1029,17 @@ public static class JCVariableDecl extends JCStatement implements VariableTree { public JCExpression init; /** symbol */ public VarSymbol sym; - /** explicit start pos */ - public int startPos = Position.NOPOS; - /** declared using `var` */ - private boolean declaredUsingVar; + /** how the variable's type was declared */ + public DeclKind declKind; + /** a source code position to use for "vartype" when null (can happen if declKind != EXPLICIT) */ + public int typePos; protected JCVariableDecl(JCModifiers mods, Name name, JCExpression vartype, JCExpression init, VarSymbol sym) { - this(mods, name, vartype, init, sym, false); + this(mods, name, vartype, init, sym, DeclKind.EXPLICIT, Position.NOPOS); } protected JCVariableDecl(JCModifiers mods, @@ -1032,19 +1047,21 @@ protected JCVariableDecl(JCModifiers mods, JCExpression vartype, JCExpression init, VarSymbol sym, - boolean declaredUsingVar) { + DeclKind declKind, + int typePos) { this.mods = mods; this.name = name; this.vartype = vartype; this.init = init; this.sym = sym; - this.declaredUsingVar = declaredUsingVar; + this.declKind = declKind; + this.typePos = typePos; } protected JCVariableDecl(JCModifiers mods, JCExpression nameexpr, JCExpression vartype) { - this(mods, null, vartype, null, null, false); + this(mods, null, vartype, null, null, DeclKind.EXPLICIT, Position.NOPOS); this.nameexpr = nameexpr; if (nameexpr.hasTag(Tag.IDENT)) { this.name = ((JCIdent)nameexpr).name; @@ -1059,7 +1076,7 @@ public boolean isImplicitlyTyped() { } public boolean declaredUsingVar() { - return declaredUsingVar; + return declKind == DeclKind.VAR; } @Override diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java index 919b2325ef669..d953663a6d754 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -724,7 +724,10 @@ public void visitVarDef(JCVariableDecl tree) { print("... "); print(tree.name); } else { - printExpr(tree.vartype); + if (tree.vartype == null && tree.declaredUsingVar()) + print("var"); + else + printExpr(tree.vartype); print(' '); if (tree.name.isEmpty()) { print('_'); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java index 9c3ed3bbcd26b..9efc6a9d89527 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java @@ -551,7 +551,7 @@ public JCTree visitVariable(VariableTree node, P p) { JCExpression vartype = copy(t.vartype, p); if (t.nameexpr == null) { JCExpression init = copy(t.init, p); - return M.at(t.pos).VarDef(mods, t.name, vartype, init); + return M.at(t.pos).VarDef(mods, t.name, vartype, init, t.declKind, t.typePos); } else { JCExpression nameexpr = copy(t.nameexpr, p); return M.at(t.pos).ReceiverVarDef(mods, nameexpr, vartype); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java index ae946c5b6d64d..a66dcaad851a6 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -610,17 +610,14 @@ public static int getStartPos(JCTree tree) { } case VARDEF: { JCVariableDecl node = (JCVariableDecl)tree; - if (node.startPos != Position.NOPOS) { - return node.startPos; - } else if (node.mods.pos != Position.NOPOS) { + if (node.mods.pos != Position.NOPOS) { return node.mods.pos; - } else if (node.vartype == null || node.vartype.pos == Position.NOPOS) { - //if there's no type (partially typed lambda parameter) - //simply return node position - return node.pos; - } else { + } else if (node.vartype != null) { return getStartPos(node.vartype); + } else if (node.typePos != Position.NOPOS) { + return node.typePos; } + break; } case BINDINGPATTERN: { JCBindingPattern node = (JCBindingPattern)tree; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java index 0d0852cb91b2a..1d2798e2436bd 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -62,9 +62,17 @@ public static TreeMaker instance(Context context) { return instance; } - /** The position at which subsequent trees will be created. + /** The start position at which subsequent trees will be created. */ - public int pos = Position.NOPOS; + public int pos; + + /** The end position at which subsequent trees will be created. + */ + public int endPos; + + /** The end position table into which subsequent end positions will be stored. + */ + public EndPosTable endPosTable; /** The toplevel tree to which created trees belong. */ @@ -84,6 +92,7 @@ public static TreeMaker instance(Context context) { protected TreeMaker(Context context) { context.put(treeMakerKey, this); this.pos = Position.NOPOS; + this.endPos = Position.NOPOS; this.toplevel = null; this.names = Names.instance(context); this.syms = Symtab.instance(context); @@ -94,6 +103,7 @@ protected TreeMaker(Context context) { */ protected TreeMaker(JCCompilationUnit toplevel, Names names, Types types, Symtab syms) { this.pos = Position.FIRSTPOS; + this.endPos = Position.NOPOS; this.toplevel = toplevel; this.names = names; this.types = types; @@ -106,17 +116,38 @@ public TreeMaker forToplevel(JCCompilationUnit toplevel) { return new TreeMaker(toplevel, names, types, syms); } - /** Reassign current position. + /** Reassign current start position and set current end position to NPPOS. */ public TreeMaker at(int pos) { this.pos = pos; + this.endPos = Position.NOPOS; + this.endPosTable = null; return this; } - /** Reassign current position. + /** Reassign current start position and set current end position to NPPOS. */ public TreeMaker at(DiagnosticPosition pos) { - this.pos = (pos == null ? Position.NOPOS : pos.getStartPosition()); + return at(pos, null); + } + + /** Reassign current start and end positions based on the given DiagnosticPosition. + */ + public TreeMaker at(DiagnosticPosition pos, EndPosTable endPosTable) { + return at(pos != null ? pos.getStartPosition() : Position.NOPOS, + pos != null && endPosTable != null ? pos.getEndPosition(endPosTable) : Position.NOPOS, + endPosTable); + } + + /** Reassign current start and end positions. + * @param pos start position, or {@link Position#NOPOS} for none + * @param endPos ending position, or {@link Position#NOPOS} for none + * @param endPosTable ending position table, or null for none + */ + public TreeMaker at(int pos, int endPos, EndPosTable endPosTable) { + this.pos = pos; + this.endPos = endPos; + this.endPosTable = endPosTable; return this; } @@ -138,30 +169,22 @@ public JCCompilationUnit TopLevel(List defs) { || (node instanceof JCExpressionStatement expressionStatement && expressionStatement.expr instanceof JCErroneous), () -> node.getClass().getSimpleName()); - JCCompilationUnit tree = new JCCompilationUnit(defs); - tree.pos = pos; - return tree; + return setPos(new JCCompilationUnit(defs)); } public JCPackageDecl PackageDecl(List annotations, JCExpression pid) { Assert.checkNonNull(annotations); Assert.checkNonNull(pid); - JCPackageDecl tree = new JCPackageDecl(annotations, pid); - tree.pos = pos; - return tree; + return setPos(new JCPackageDecl(annotations, pid)); } public JCImport Import(JCFieldAccess qualid, boolean staticImport) { - JCImport tree = new JCImport(qualid, staticImport); - tree.pos = pos; - return tree; + return setPos(new JCImport(qualid, staticImport)); } public JCModuleImport ModuleImport(JCExpression moduleName) { - JCModuleImport tree = new JCModuleImport(moduleName); - tree.pos = pos; - return tree; + return setPos(new JCModuleImport(moduleName)); } public JCClassDecl ClassDef(JCModifiers mods, @@ -182,16 +205,14 @@ public JCClassDecl ClassDef(JCModifiers mods, List permitting, List defs) { - JCClassDecl tree = new JCClassDecl(mods, + return setPos(new JCClassDecl(mods, name, typarams, extending, implementing, permitting, defs, - null); - tree.pos = pos; - return tree; + null)); } public JCMethodDecl MethodDef(JCModifiers mods, @@ -217,7 +238,7 @@ public JCMethodDecl MethodDef(JCModifiers mods, JCBlock body, JCExpression defaultValue) { - JCMethodDecl tree = new JCMethodDecl(mods, + return setPos(new JCMethodDecl(mods, name, restype, typarams, @@ -226,51 +247,36 @@ public JCMethodDecl MethodDef(JCModifiers mods, thrown, body, defaultValue, - null); - tree.pos = pos; - return tree; + null)); } public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init) { - JCVariableDecl tree = new JCVariableDecl(mods, name, vartype, init, null); - tree.pos = pos; - return tree; + return setPos(new JCVariableDecl(mods, name, vartype, init, null)); } - public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init, boolean declaredUsingVar) { - JCVariableDecl tree = new JCVariableDecl(mods, name, vartype, init, null, declaredUsingVar); - tree.pos = pos; - return tree; + public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init, + JCVariableDecl.DeclKind declKind, int typePos) { + return setPos(new JCVariableDecl(mods, name, vartype, init, null, declKind, typePos)); } public JCVariableDecl ReceiverVarDef(JCModifiers mods, JCExpression name, JCExpression vartype) { - JCVariableDecl tree = new JCVariableDecl(mods, name, vartype); - tree.pos = pos; - return tree; + return setPos(new JCVariableDecl(mods, name, vartype)); } public JCSkip Skip() { - JCSkip tree = new JCSkip(); - tree.pos = pos; - return tree; + return setPos(new JCSkip()); } public JCBlock Block(long flags, List stats) { - JCBlock tree = new JCBlock(flags, stats); - tree.pos = pos; - return tree; + return setPos(new JCBlock(flags, stats)); } public JCDoWhileLoop DoLoop(JCStatement body, JCExpression cond) { - JCDoWhileLoop tree = new JCDoWhileLoop(body, cond); - tree.pos = pos; - return tree; + return setPos(new JCDoWhileLoop(body, cond)); } public JCWhileLoop WhileLoop(JCExpression cond, JCStatement body) { - JCWhileLoop tree = new JCWhileLoop(cond, body); - tree.pos = pos; - return tree; + return setPos(new JCWhileLoop(cond, body)); } public JCForLoop ForLoop(List init, @@ -278,46 +284,32 @@ public JCForLoop ForLoop(List init, List step, JCStatement body) { - JCForLoop tree = new JCForLoop(init, cond, step, body); - tree.pos = pos; - return tree; + return setPos(new JCForLoop(init, cond, step, body)); } public JCEnhancedForLoop ForeachLoop(JCVariableDecl var, JCExpression expr, JCStatement body) { - JCEnhancedForLoop tree = new JCEnhancedForLoop(var, expr, body); - tree.pos = pos; - return tree; + return setPos(new JCEnhancedForLoop(var, expr, body)); } public JCLabeledStatement Labelled(Name label, JCStatement body) { - JCLabeledStatement tree = new JCLabeledStatement(label, body); - tree.pos = pos; - return tree; + return setPos(new JCLabeledStatement(label, body)); } public JCSwitch Switch(JCExpression selector, List cases) { - JCSwitch tree = new JCSwitch(selector, cases); - tree.pos = pos; - return tree; + return setPos(new JCSwitch(selector, cases)); } public JCCase Case(CaseTree.CaseKind caseKind, List labels, JCExpression guard, List stats, JCTree body) { - JCCase tree = new JCCase(caseKind, labels, guard, stats, body); - tree.pos = pos; - return tree; + return setPos(new JCCase(caseKind, labels, guard, stats, body)); } public JCSwitchExpression SwitchExpression(JCExpression selector, List cases) { - JCSwitchExpression tree = new JCSwitchExpression(selector, cases); - tree.pos = pos; - return tree; + return setPos(new JCSwitchExpression(selector, cases)); } public JCSynchronized Synchronized(JCExpression lock, JCBlock body) { - JCSynchronized tree = new JCSynchronized(lock, body); - tree.pos = pos; - return tree; + return setPos(new JCSynchronized(lock, body)); } public JCTry Try(JCBlock body, List catchers, JCBlock finalizer) { @@ -328,81 +320,57 @@ public JCTry Try(List resources, JCBlock body, List catchers, JCBlock finalizer) { - JCTry tree = new JCTry(resources, body, catchers, finalizer); - tree.pos = pos; - return tree; + return setPos(new JCTry(resources, body, catchers, finalizer)); } public JCCatch Catch(JCVariableDecl param, JCBlock body) { - JCCatch tree = new JCCatch(param, body); - tree.pos = pos; - return tree; + return setPos(new JCCatch(param, body)); } public JCConditional Conditional(JCExpression cond, JCExpression thenpart, JCExpression elsepart) { - JCConditional tree = new JCConditional(cond, thenpart, elsepart); - tree.pos = pos; - return tree; + return setPos(new JCConditional(cond, thenpart, elsepart)); } public JCIf If(JCExpression cond, JCStatement thenpart, JCStatement elsepart) { - JCIf tree = new JCIf(cond, thenpart, elsepart); - tree.pos = pos; - return tree; + return setPos(new JCIf(cond, thenpart, elsepart)); } public JCExpressionStatement Exec(JCExpression expr) { - JCExpressionStatement tree = new JCExpressionStatement(expr); - tree.pos = pos; - return tree; + return setPos(new JCExpressionStatement(expr)); } public JCBreak Break(Name label) { - JCBreak tree = new JCBreak(label, null); - tree.pos = pos; - return tree; + return setPos(new JCBreak(label, null)); } public JCYield Yield(JCExpression value) { - JCYield tree = new JCYield(value, null); - tree.pos = pos; - return tree; + return setPos(new JCYield(value, null)); } public JCContinue Continue(Name label) { - JCContinue tree = new JCContinue(label, null); - tree.pos = pos; - return tree; + return setPos(new JCContinue(label, null)); } public JCReturn Return(JCExpression expr) { - JCReturn tree = new JCReturn(expr); - tree.pos = pos; - return tree; + return setPos(new JCReturn(expr)); } public JCThrow Throw(JCExpression expr) { - JCThrow tree = new JCThrow(expr); - tree.pos = pos; - return tree; + return setPos(new JCThrow(expr)); } public JCAssert Assert(JCExpression cond, JCExpression detail) { - JCAssert tree = new JCAssert(cond, detail); - tree.pos = pos; - return tree; + return setPos(new JCAssert(cond, detail)); } public JCMethodInvocation Apply(List typeargs, JCExpression fn, List args) { - JCMethodInvocation tree = new JCMethodInvocation(typeargs, fn, args); - tree.pos = pos; - return tree; + return setPos(new JCMethodInvocation(typeargs, fn, args)); } public JCNewClass NewClass(JCExpression encl, @@ -421,172 +389,120 @@ public JCNewClass SpeculativeNewClass(JCExpression encl, JCClassDecl def, boolean classDefRemoved) { - JCNewClass tree = classDefRemoved ? + return setPos(classDefRemoved ? new JCNewClass(encl, typeargs, clazz, args, def) { @Override public boolean classDeclRemoved() { return true; } } : - new JCNewClass(encl, typeargs, clazz, args, def); - tree.pos = pos; - return tree; + new JCNewClass(encl, typeargs, clazz, args, def)); } public JCNewArray NewArray(JCExpression elemtype, List dims, List elems) { - JCNewArray tree = new JCNewArray(elemtype, dims, elems); - tree.pos = pos; - return tree; + return setPos(new JCNewArray(elemtype, dims, elems)); } public JCLambda Lambda(List params, JCTree body) { - JCLambda tree = new JCLambda(params, body); - tree.pos = pos; - return tree; + return setPos(new JCLambda(params, body)); } public JCParens Parens(JCExpression expr) { - JCParens tree = new JCParens(expr); - tree.pos = pos; - return tree; + return setPos(new JCParens(expr)); } public JCAssign Assign(JCExpression lhs, JCExpression rhs) { - JCAssign tree = new JCAssign(lhs, rhs); - tree.pos = pos; - return tree; + return setPos(new JCAssign(lhs, rhs)); } public JCAssignOp Assignop(JCTree.Tag opcode, JCTree lhs, JCTree rhs) { - JCAssignOp tree = new JCAssignOp(opcode, lhs, rhs, null); - tree.pos = pos; - return tree; + return setPos(new JCAssignOp(opcode, lhs, rhs, null)); } public JCUnary Unary(JCTree.Tag opcode, JCExpression arg) { - JCUnary tree = new JCUnary(opcode, arg); - tree.pos = pos; - return tree; + return setPos(new JCUnary(opcode, arg)); } public JCBinary Binary(JCTree.Tag opcode, JCExpression lhs, JCExpression rhs) { - JCBinary tree = new JCBinary(opcode, lhs, rhs, null); - tree.pos = pos; - return tree; + return setPos(new JCBinary(opcode, lhs, rhs, null)); } public JCTypeCast TypeCast(JCTree clazz, JCExpression expr) { - JCTypeCast tree = new JCTypeCast(clazz, expr); - tree.pos = pos; - return tree; + return setPos(new JCTypeCast(clazz, expr)); } public JCInstanceOf TypeTest(JCExpression expr, JCTree clazz) { - JCInstanceOf tree = new JCInstanceOf(expr, clazz); - tree.pos = pos; - return tree; + return setPos(new JCInstanceOf(expr, clazz)); } public JCAnyPattern AnyPattern() { - JCAnyPattern tree = new JCAnyPattern(); - tree.pos = pos; - return tree; + return setPos(new JCAnyPattern()); } public JCBindingPattern BindingPattern(JCVariableDecl var) { - JCBindingPattern tree = new JCBindingPattern(var); - tree.pos = pos; - return tree; + return setPos(new JCBindingPattern(var)); } public JCDefaultCaseLabel DefaultCaseLabel() { - JCDefaultCaseLabel tree = new JCDefaultCaseLabel(); - tree.pos = pos; - return tree; + return setPos(new JCDefaultCaseLabel()); } public JCConstantCaseLabel ConstantCaseLabel(JCExpression expr) { - JCConstantCaseLabel tree = new JCConstantCaseLabel(expr); - tree.pos = pos; - return tree; + return setPos(new JCConstantCaseLabel(expr)); } public JCPatternCaseLabel PatternCaseLabel(JCPattern pat) { - JCPatternCaseLabel tree = new JCPatternCaseLabel(pat); - tree.pos = pos; - return tree; + return setPos(new JCPatternCaseLabel(pat)); } public JCRecordPattern RecordPattern(JCExpression deconstructor, List nested) { - JCRecordPattern tree = new JCRecordPattern(deconstructor, nested); - tree.pos = pos; - return tree; + return setPos(new JCRecordPattern(deconstructor, nested)); } public JCArrayAccess Indexed(JCExpression indexed, JCExpression index) { - JCArrayAccess tree = new JCArrayAccess(indexed, index); - tree.pos = pos; - return tree; + return setPos(new JCArrayAccess(indexed, index)); } public JCFieldAccess Select(JCExpression selected, Name selector) { - JCFieldAccess tree = new JCFieldAccess(selected, selector, null); - tree.pos = pos; - return tree; + return setPos(new JCFieldAccess(selected, selector, null)); } public JCMemberReference Reference(JCMemberReference.ReferenceMode mode, Name name, JCExpression expr, List typeargs) { - JCMemberReference tree = new JCMemberReference(mode, name, expr, typeargs); - tree.pos = pos; - return tree; + return setPos(new JCMemberReference(mode, name, expr, typeargs)); } public JCIdent Ident(Name name) { - JCIdent tree = new JCIdent(name, null); - tree.pos = pos; - return tree; + return setPos(new JCIdent(name, null)); } public JCLiteral Literal(TypeTag tag, Object value) { - JCLiteral tree = new JCLiteral(tag, value); - tree.pos = pos; - return tree; + return setPos(new JCLiteral(tag, value)); } public JCPrimitiveTypeTree TypeIdent(TypeTag typetag) { - JCPrimitiveTypeTree tree = new JCPrimitiveTypeTree(typetag); - tree.pos = pos; - return tree; + return setPos(new JCPrimitiveTypeTree(typetag)); } public JCArrayTypeTree TypeArray(JCExpression elemtype) { - JCArrayTypeTree tree = new JCArrayTypeTree(elemtype); - tree.pos = pos; - return tree; + return setPos(new JCArrayTypeTree(elemtype)); } public JCTypeApply TypeApply(JCExpression clazz, List arguments) { - JCTypeApply tree = new JCTypeApply(clazz, arguments); - tree.pos = pos; - return tree; + return setPos(new JCTypeApply(clazz, arguments)); } public JCTypeUnion TypeUnion(List components) { - JCTypeUnion tree = new JCTypeUnion(components); - tree.pos = pos; - return tree; + return setPos(new JCTypeUnion(components)); } public JCTypeIntersection TypeIntersection(List components) { - JCTypeIntersection tree = new JCTypeIntersection(components); - tree.pos = pos; - return tree; + return setPos(new JCTypeIntersection(components)); } public JCTypeParameter TypeParameter(Name name, List bounds) { @@ -594,40 +510,33 @@ public JCTypeParameter TypeParameter(Name name, List bounds) { } public JCTypeParameter TypeParameter(Name name, List bounds, List annos) { - JCTypeParameter tree = new JCTypeParameter(name, bounds, annos); - tree.pos = pos; - return tree; + return setPos(new JCTypeParameter(name, bounds, annos)); } public JCWildcard Wildcard(TypeBoundKind kind, JCTree type) { - JCWildcard tree = new JCWildcard(kind, type); - tree.pos = pos; - return tree; + return setPos(new JCWildcard(kind, type)); } public TypeBoundKind TypeBoundKind(BoundKind kind) { - TypeBoundKind tree = new TypeBoundKind(kind); - tree.pos = pos; - return tree; + return setPos(new TypeBoundKind(kind)); } public JCAnnotation Annotation(JCTree annotationType, List args) { - JCAnnotation tree = new JCAnnotation(Tag.ANNOTATION, annotationType, args); - tree.pos = pos; - return tree; + return setPos(new JCAnnotation(Tag.ANNOTATION, annotationType, args)); } public JCAnnotation TypeAnnotation(JCTree annotationType, List args) { - JCAnnotation tree = new JCAnnotation(Tag.TYPE_ANNOTATION, annotationType, args); - tree.pos = pos; - return tree; + return setPos(new JCAnnotation(Tag.TYPE_ANNOTATION, annotationType, args)); } public JCModifiers Modifiers(long flags, List annotations) { JCModifiers tree = new JCModifiers(flags, annotations); boolean noFlags = (flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0; - tree.pos = (noFlags && annotations.isEmpty()) ? Position.NOPOS : pos; - return tree; + if (noFlags && annotations.isEmpty()) { + tree.pos = Position.NOPOS; + return tree; + } + return setPos(tree); } public JCModifiers Modifiers(long flags) { @@ -637,50 +546,36 @@ public JCModifiers Modifiers(long flags) { @Override public JCModuleDecl ModuleDef(JCModifiers mods, ModuleKind kind, JCExpression qualid, List directives) { - JCModuleDecl tree = new JCModuleDecl(mods, kind, qualid, directives); - tree.pos = pos; - return tree; + return setPos(new JCModuleDecl(mods, kind, qualid, directives)); } @Override public JCExports Exports(JCExpression qualId, List moduleNames) { - JCExports tree = new JCExports(qualId, moduleNames); - tree.pos = pos; - return tree; + return setPos(new JCExports(qualId, moduleNames)); } @Override public JCOpens Opens(JCExpression qualId, List moduleNames) { - JCOpens tree = new JCOpens(qualId, moduleNames); - tree.pos = pos; - return tree; + return setPos(new JCOpens(qualId, moduleNames)); } @Override public JCProvides Provides(JCExpression serviceName, List implNames) { - JCProvides tree = new JCProvides(serviceName, implNames); - tree.pos = pos; - return tree; + return setPos(new JCProvides(serviceName, implNames)); } @Override public JCRequires Requires(boolean isTransitive, boolean isStaticPhase, JCExpression qualId) { - JCRequires tree = new JCRequires(isTransitive, isStaticPhase, qualId); - tree.pos = pos; - return tree; + return setPos(new JCRequires(isTransitive, isStaticPhase, qualId)); } @Override public JCUses Uses(JCExpression qualId) { - JCUses tree = new JCUses(qualId); - tree.pos = pos; - return tree; + return setPos(new JCUses(qualId)); } public JCAnnotatedType AnnotatedType(List annotations, JCExpression underlyingType) { - JCAnnotatedType tree = new JCAnnotatedType(annotations, underlyingType); - tree.pos = pos; - return tree; + return setPos(new JCAnnotatedType(annotations, underlyingType)); } public JCErroneous Erroneous() { @@ -688,15 +583,11 @@ public JCErroneous Erroneous() { } public JCErroneous Erroneous(List errs) { - JCErroneous tree = new JCErroneous(errs); - tree.pos = pos; - return tree; + return setPos(new JCErroneous(errs)); } public LetExpr LetExpr(List defs, JCExpression expr) { - LetExpr tree = new LetExpr(defs, expr); - tree.pos = pos; - return tree; + return setPos(new LetExpr(defs, expr)); } /* *************************************************************************** @@ -715,8 +606,11 @@ public JCClassDecl AnonymousClassDef(JCModifiers mods, } public LetExpr LetExpr(JCVariableDecl def, JCExpression expr) { - LetExpr tree = new LetExpr(List.of(def), expr); - tree.pos = pos; + return setPos(new LetExpr(List.of(def), expr)); + } + + private T setPos(T tree) { + tree.setPos(pos, endPos, endPosTable); return tree; } @@ -726,7 +620,7 @@ public JCIdent Ident(Symbol sym) { return (JCIdent)new JCIdent((sym.name != names.empty) ? sym.name : sym.flatName(), sym) - .setPos(pos) + .setPos(pos, endPos, endPosTable) .setType(sym.type); } @@ -734,7 +628,7 @@ public JCIdent Ident(Symbol sym) { * @param base The qualifier tree. */ public JCFieldAccess Select(JCExpression base, Symbol sym) { - return (JCFieldAccess)new JCFieldAccess(base, sym.name, sym).setPos(pos).setType(sym.type); + return (JCFieldAccess)new JCFieldAccess(base, sym.name, sym).setPos(pos, endPos, endPosTable).setType(sym.type); } /** Create a qualified identifier from a symbol, adding enough qualifications @@ -909,7 +803,7 @@ public JCVariableDecl VarDef(VarSymbol v, JCExpression init) { v.name, Type(v.type), init, - v).setPos(pos).setType(v.type); + v).setPos(pos, endPos, endPosTable).setType(v.type); } /** Create annotation trees from annotations. @@ -1055,14 +949,14 @@ public JCMethodDecl MethodDef(MethodSymbol m, Type mtype, JCBlock body) { Types(mtype.getThrownTypes()), body, null, - m).setPos(pos).setType(mtype); + m).setPos(pos, endPos, endPosTable).setType(mtype); } /** Create a type parameter tree from its name and type. */ public JCTypeParameter TypeParam(Name name, TypeVar tvar) { return (JCTypeParameter) - TypeParameter(name, Types(types.getBounds(tvar))).setPos(pos).setType(tvar); + TypeParameter(name, Types(types.getBounds(tvar))).setPos(pos, endPos, endPosTable).setType(tvar); } /** Create a list of type parameter trees from a list of type variables. diff --git a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java index 4ee629476db8c..4be25ff76a853 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java @@ -768,7 +768,7 @@ public Void visitMethod(MethodTree node, Void p) { @Override public Void visitVariable(VariableTree node, Void p) { int pos = ((JCTree) node).pos; - if (sp.getEndPosition(cut, node.getType()) == (-1)) { + if (node instanceof JCTree.JCVariableDecl varDecl && varDecl.declaredUsingVar()) { Token varCandidate = findTokensBefore(pos, TokenKind.IDENTIFIER); if (varCandidate != null && "var".equals(varCandidate.name().toString())) { addKeyword.accept(varCandidate); diff --git a/test/langtools/tools/javac/parser/DeclarationEndPositions.java b/test/langtools/tools/javac/parser/DeclarationEndPositions.java index 473d6bc2712f1..492dccfe2e898 100644 --- a/test/langtools/tools/javac/parser/DeclarationEndPositions.java +++ b/test/langtools/tools/javac/parser/DeclarationEndPositions.java @@ -49,7 +49,7 @@ public class DeclarationEndPositions { - public static void checkEndPosition(Class nodeType, String input, String marker) throws IOException { + public static void checkPositions(Class nodeType, String input, String markers) throws IOException { // Create source var source = new SimpleJavaFileObject(URI.create("file://T.java"), JavaFileObject.Kind.SOURCE) { @@ -71,11 +71,26 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept public Void scan(Tree node, Void aVoid) { if (nodeType.isInstance(node)) { JCTree tree = (JCTree)node; - int actual = TreeInfo.getEndPos(tree, unit.endPositions); - int expected = marker.indexOf('^') + 1; - if (actual != expected) { + + // Verify declaration start and end positions + int start = tree.getStartPosition(); + if (markers.charAt(start) != '<') { + throw new AssertionError(String.format( + "wrong %s pos %d for \"%s\" in \"%s\"", "start", start, tree, input)); + } + int end = TreeInfo.getEndPos(tree, unit.endPositions); + if (markers.charAt(end - 1) != '>') { throw new AssertionError(String.format( - "wrong end pos %d != %d for \"%s\" @ %d", actual, expected, input, tree.pos)); + "wrong %s pos %d for \"%s\" in \"%s\"", "end", end, tree, input)); + } + + // For variable declarations using "var", verify the "var" position + if (tree instanceof JCVariableDecl varDecl && varDecl.declaredUsingVar()) { + int vpos = varDecl.typePos; + if (!input.substring(vpos).startsWith("var")) { + throw new AssertionError(String.format( + "wrong %s pos %d for \"%s\" in \"%s\"", "var", vpos, tree, input)); + } } } return super.scan(node, aVoid); @@ -86,34 +101,71 @@ public Void scan(Tree node, Void aVoid) { public static void main(String... args) throws Exception { // JCModuleDecl - checkEndPosition(JCModuleDecl.class, + checkPositions(JCModuleDecl.class, "/* comment */ module fred { /* comment */ } /* comment */", - " ^ "); + " <---------------------------> "); // JCPackageDecl - checkEndPosition(JCPackageDecl.class, + checkPositions(JCPackageDecl.class, "/* comment */ package fred; /* comment */", - " ^ "); + " <-----------> "); // JCClassDecl - checkEndPosition(JCClassDecl.class, + checkPositions(JCClassDecl.class, "/* comment */ class Fred { /* comment */ } /* comment */", - " ^ "); + " <--------------------------> "); // JCMethodDecl - checkEndPosition(JCMethodDecl.class, + checkPositions(JCMethodDecl.class, "/* comment */ class Fred { void m() { /* comment */ } } /* comment */", - " ^ "); + " <------------------------> "); // JCVariableDecl - checkEndPosition(JCVariableDecl.class, + checkPositions(JCVariableDecl.class, "/* comment */ class Fred { int x; } /* comment */", - " ^ "); - checkEndPosition(JCVariableDecl.class, + " <----> "); + checkPositions(JCVariableDecl.class, "/* comment */ class Fred { int x = 123; } /* comment */", - " ^ "); - checkEndPosition(JCVariableDecl.class, - "/* comment */ class A { try {} catch (Error err) {} } /* comment */", - " ^ "); + " <----------> "); + checkPositions(JCVariableDecl.class, + "/* comment */ class Fred { final int x = 123; } /* comment */", + " <----------------> "); + checkPositions(JCVariableDecl.class, + "/* comment */ class Fred { final int x = 123, y = 456; } /* comment */", + " <---------------->--------> "); + checkPositions(JCVariableDecl.class, + "/* comment */ class A { void m() { try {} catch (Error err) {} } } /* comment */", + " <-------> "); + + // JCVariableDecl with "var" declarations + checkPositions(JCVariableDecl.class, + "class A { void m() { var foo; } }", + " <------> "); + checkPositions(JCVariableDecl.class, + "class A { void m() { var foo = 42; } }", + " <-----------> "); + checkPositions(JCVariableDecl.class, + "class A { void m() { final var foo = 42; } }", + " <-----------------> "); + + checkPositions(JCVariableDecl.class, + "class A { void m() { java.util.function.Consumer = foo -> { } } }", + " <-> "); + checkPositions(JCVariableDecl.class, + "class A { void m() { java.util.function.Consumer = (foo) -> { } } }", + " <-> "); + checkPositions(JCVariableDecl.class, + "class A { void m() { java.util.function.Consumer = (var foo) -> { } } }", + " <-----> "); + checkPositions(JCVariableDecl.class, + "class A { void m() { java.util.function.Consumer = (final var foo) -> { } } }", + " <-----------> "); + + checkPositions(JCVariableDecl.class, + "class A { record R(int x) { } void m() { switch (null) { case R(var x) -> {} default -> {} } } }", + " <---> <---> "); + checkPositions(JCVariableDecl.class, + "class A { record R(int x) { } void m() { switch (null) { case R(final var x) -> {} default -> {} } } }", + " <---> <---------> "); } } diff --git a/test/langtools/tools/javac/patterns/PrettyTest.java b/test/langtools/tools/javac/patterns/PrettyTest.java index 5425127e91b1b..5f9c74b760e02 100644 --- a/test/langtools/tools/javac/patterns/PrettyTest.java +++ b/test/langtools/tools/javac/patterns/PrettyTest.java @@ -72,12 +72,12 @@ boolean t(Object o) { boolean _ = true; b = o instanceof String s; b = o instanceof R(String s); - b = o instanceof R(/*missing*/ s); - b = o instanceof R2(R(/*missing*/ s), String t); - b = o instanceof R2(R(/*missing*/ s), /*missing*/ t); + b = o instanceof R(var s); + b = o instanceof R2(R(var s), String t); + b = o instanceof R2(R(var s), var t); b = o instanceof R(String _); - b = o instanceof R2(R(/*missing*/ _), /*missing*/ _); - b = o instanceof R2(R(_), /*missing*/ t); + b = o instanceof R2(R(var _), var _); + b = o instanceof R2(R(_), var t); } \n\ class R { diff --git a/test/langtools/tools/javac/tree/VarTree.java b/test/langtools/tools/javac/tree/VarTree.java index 5ce7ec075419d..4d223f7c5401f 100644 --- a/test/langtools/tools/javac/tree/VarTree.java +++ b/test/langtools/tools/javac/tree/VarTree.java @@ -35,6 +35,8 @@ import java.net.URI; import java.util.Arrays; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; @@ -67,6 +69,12 @@ public static void main(String... args) throws Exception { "java.lang.String testVar"); test.run("java.util.function.Consumer c = (|var testVar|) -> {};", "java.lang.String testVar"); + test.run("java.util.function.Consumer c = (|final var testVar|) -> {};", + "final java.lang.String testVar"); + test.run("record Rec(int x) { }; switch (null) { case Rec(|var testVar|) -> {} default -> {} };", + "int testVar"); + test.run("record Rec(int x) { }; switch (null) { case Rec(|final var testVar|) -> {} default -> {} };", + "final int testVar"); } void run(String code, String expected) throws IOException { @@ -115,12 +123,15 @@ public Void visitVariable(VariableTree node, Void p) { private void runSpanCheck(JavacTask ct, Iterable units, String src, int spanStart, int spanEnd) { Trees trees = Trees.instance(ct); boolean[] found = new boolean[1]; + Pattern varPat = Pattern.compile("(?() { @Override public Void visitVariable(VariableTree node, Void p) { if (node.getName().contentEquals("testVar")) { + + // Verify start and position of the variable declaration int start = (int) trees.getSourcePositions().getStartPosition(cut, node); int end = (int) trees.getSourcePositions().getEndPosition(cut, node); @@ -130,10 +141,19 @@ public Void visitVariable(VariableTree node, Void p) { throw new AssertionError("Unexpected span: " + snip); } + // Verify start and position of the variable type int typeStart = (int) trees.getSourcePositions().getStartPosition(cut, node.getType()); int typeEnd = (int) trees.getSourcePositions().getEndPosition(cut, node.getType()); - if (typeStart != (-1) && typeEnd != (-1)) { + Matcher matcher; + if (node.getType() != null && (matcher = varPat.matcher(src)).find(start)) { + if (typeStart != matcher.start()) { + throw new AssertionError("Unexpected type start: " + typeStart + " != " + matcher.start()); + } + if (typeEnd != matcher.end()) { + throw new AssertionError("Unexpected type end: " + typeEnd + " != " + matcher.end()); + } + } else if (typeStart != (-1) && typeEnd != (-1)) { throw new AssertionError("Unexpected type position: " + typeStart + ", " + typeEnd); } diff --git a/test/langtools/tools/javac/tree/VarWarnPosition.java b/test/langtools/tools/javac/tree/VarWarnPosition.java index 7dae84f3542db..f1d5f4346d077 100644 --- a/test/langtools/tools/javac/tree/VarWarnPosition.java +++ b/test/langtools/tools/javac/tree/VarWarnPosition.java @@ -22,6 +22,9 @@ public class VarWarnPosition { // Test 3 Consumer c2 = (var d) -> { }; + + // Test 4 + Consumer c3 = (final var d) -> { }; } } diff --git a/test/langtools/tools/javac/tree/VarWarnPosition.out b/test/langtools/tools/javac/tree/VarWarnPosition.out index 2200c8b4ae0db..87a4ca3a1fd9d 100644 --- a/test/langtools/tools/javac/tree/VarWarnPosition.out +++ b/test/langtools/tools/javac/tree/VarWarnPosition.out @@ -3,4 +3,6 @@ VarWarnPosition.java:21:18: compiler.warn.has.been.deprecated: Depr, compiler.mi VarWarnPosition.java:21:28: compiler.warn.has.been.deprecated: Depr, compiler.misc.unnamed.package VarWarnPosition.java:24:18: compiler.warn.has.been.deprecated: Depr, compiler.misc.unnamed.package VarWarnPosition.java:24:30: compiler.warn.has.been.deprecated: Depr, compiler.misc.unnamed.package -5 warnings +VarWarnPosition.java:27:18: compiler.warn.has.been.deprecated: Depr, compiler.misc.unnamed.package +VarWarnPosition.java:27:36: compiler.warn.has.been.deprecated: Depr, compiler.misc.unnamed.package +7 warnings