8350212: Track source end positions of declarations that support @SuppressWarnings
Co-authored-by: Jan Lahoda <jlahoda@openjdk.org> Reviewed-by: mcimadamore
This commit is contained in:
parent
15178aa298
commit
c793de989f
@ -3697,7 +3697,7 @@ public class Lower extends TreeTranslator {
|
||||
vardefinit).setType(tree.var.type);
|
||||
indexDef.sym = tree.var.sym;
|
||||
JCBlock body = make.Block(0, List.of(indexDef, tree.body));
|
||||
body.endpos = TreeInfo.endPos(tree.body);
|
||||
body.bracePos = TreeInfo.endPos(tree.body);
|
||||
result = translate(make.
|
||||
ForLoop(List.of(init),
|
||||
cond,
|
||||
@ -4158,7 +4158,7 @@ public class Lower extends TreeTranslator {
|
||||
stmtList.append(switch2);
|
||||
|
||||
JCBlock res = make.Block(0L, stmtList.toList());
|
||||
res.endpos = TreeInfo.endPos(tree);
|
||||
res.bracePos = TreeInfo.endPos(tree);
|
||||
return res;
|
||||
} else {
|
||||
JCSwitchExpression switch2 = make.SwitchExpression(make.Ident(dollar_tmp), lb.toList());
|
||||
|
@ -500,7 +500,7 @@ public class Gen extends JCTree.Visitor {
|
||||
c.members().enter(clinit);
|
||||
List<JCStatement> clinitStats = clinitCode.toList();
|
||||
JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);
|
||||
block.endpos = TreeInfo.endPos(clinitStats.last());
|
||||
block.bracePos = TreeInfo.endPos(clinitStats.last());
|
||||
methodDefs.append(make.MethodDef(clinit, block));
|
||||
|
||||
if (!clinitTAs.isEmpty())
|
||||
@ -553,8 +553,8 @@ public class Gen extends JCTree.Visitor {
|
||||
// Find the super() invocation and append the given initializer code.
|
||||
TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.prepend(supercall)));
|
||||
|
||||
if (md.body.endpos == Position.NOPOS)
|
||||
md.body.endpos = TreeInfo.endPos(md.body.stats.last());
|
||||
if (md.body.bracePos == Position.NOPOS)
|
||||
md.body.bracePos = TreeInfo.endPos(md.body.stats.last());
|
||||
|
||||
md.sym.appendUniqueTypeAttributes(initTAs);
|
||||
}
|
||||
@ -1121,7 +1121,7 @@ public class Gen extends JCTree.Visitor {
|
||||
genStats(tree.stats, localEnv);
|
||||
// End the scope of all block-local variables in variable info.
|
||||
if (!env.tree.hasTag(METHODDEF)) {
|
||||
code.statBegin(tree.endpos);
|
||||
code.statBegin(tree.bracePos);
|
||||
code.endScopes(limit);
|
||||
code.pendingStatPos = Position.NOPOS;
|
||||
}
|
||||
|
@ -231,8 +231,8 @@ public class JavacParser implements Parser {
|
||||
|
||||
protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
|
||||
return keepEndPositions
|
||||
? new SimpleEndPosTable(this)
|
||||
: new EmptyEndPosTable(this);
|
||||
? new SimpleEndPosTable()
|
||||
: new MinimalEndPosTable();
|
||||
}
|
||||
|
||||
protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
|
||||
@ -633,12 +633,14 @@ public class JavacParser implements Parser {
|
||||
*
|
||||
* @param tree The tree to be used as index in the hashtable
|
||||
* @param dc The doc comment to associate with the tree, or null.
|
||||
* @return {@code tree}
|
||||
*/
|
||||
protected void attach(JCTree tree, Comment dc) {
|
||||
protected <T extends JCTree> T attach(T tree, Comment dc) {
|
||||
if (keepDocComments && dc != null) {
|
||||
docComments.putComment(tree, dc);
|
||||
}
|
||||
reportDanglingComments(tree, dc);
|
||||
return tree;
|
||||
}
|
||||
|
||||
/** Reports all dangling comments associated with the
|
||||
@ -702,16 +704,35 @@ public class JavacParser implements Parser {
|
||||
endPosTable.setErrorEndPos(errPos);
|
||||
}
|
||||
|
||||
protected void storeEnd(JCTree tree, int endpos) {
|
||||
endPosTable.storeEnd(tree, endpos);
|
||||
/**
|
||||
* Store ending position for a tree, the value of which is the greater of
|
||||
* last error position in {@link #endPosTable} and the given ending position.
|
||||
* @param tree tree node
|
||||
* @param endpos the ending position to associate with {@code tree}
|
||||
* @return {@code tree}
|
||||
*/
|
||||
protected <T extends JCTree> T storeEnd(T tree, int endpos) {
|
||||
return endPosTable.storeEnd(tree, endpos);
|
||||
}
|
||||
|
||||
protected <T extends JCTree> T to(T t) {
|
||||
return endPosTable.to(t);
|
||||
/**
|
||||
* Store current token's ending position for a tree, the value of which
|
||||
* will be the greater of last error position in {@link #endPosTable}
|
||||
* and the ending position of the current token.
|
||||
* @param tree tree node
|
||||
*/
|
||||
protected <T extends JCTree> T to(T tree) {
|
||||
return storeEnd(tree, token.endPos);
|
||||
}
|
||||
|
||||
protected <T extends JCTree> T toP(T t) {
|
||||
return endPosTable.toP(t);
|
||||
/**
|
||||
* Store current token's ending position for a tree, the value of which
|
||||
* will be the greater of last error position in {@link #endPosTable}
|
||||
* and the ending position of the previous token.
|
||||
* @param tree tree node
|
||||
*/
|
||||
protected <T extends JCTree> T toP(T tree) {
|
||||
return storeEnd(tree, S.prevToken().endPos);
|
||||
}
|
||||
|
||||
/** Get the start position for a tree node. The start position is
|
||||
@ -1741,7 +1762,7 @@ public class JavacParser implements Parser {
|
||||
case RBRACE: case EOF:
|
||||
JCSwitchExpression e = to(F.at(switchPos).SwitchExpression(selector,
|
||||
cases.toList()));
|
||||
e.endpos = token.pos;
|
||||
e.bracePos = token.pos;
|
||||
accept(RBRACE);
|
||||
return e;
|
||||
default:
|
||||
@ -2819,9 +2840,9 @@ public class JavacParser implements Parser {
|
||||
syntaxError(token.pos, Errors.Orphaned(token.kind));
|
||||
switchBlockStatementGroups();
|
||||
}
|
||||
// the Block node has a field "endpos" for first char of last token, which is
|
||||
// the Block node has a field "bracePos" for first char of last token, which is
|
||||
// usually but not necessarily the last char of the last token.
|
||||
t.endpos = token.pos;
|
||||
t.bracePos = token.pos;
|
||||
accept(RBRACE);
|
||||
return toP(t);
|
||||
}
|
||||
@ -3142,7 +3163,7 @@ public class JavacParser implements Parser {
|
||||
accept(LBRACE);
|
||||
List<JCCase> cases = switchBlockStatementGroups();
|
||||
JCSwitch t = to(F.at(pos).Switch(selector, cases));
|
||||
t.endpos = token.endPos;
|
||||
t.bracePos = token.endPos;
|
||||
accept(RBRACE);
|
||||
return t;
|
||||
}
|
||||
@ -3658,9 +3679,7 @@ public class JavacParser implements Parser {
|
||||
} else {
|
||||
throw new AssertionError("Unhandled annotation kind: " + kind);
|
||||
}
|
||||
|
||||
storeEnd(ann, S.prevToken().endPos);
|
||||
return ann;
|
||||
return toP(ann);
|
||||
}
|
||||
|
||||
List<JCExpression> annotationFieldValuesOpt() {
|
||||
@ -3835,9 +3854,8 @@ public class JavacParser implements Parser {
|
||||
}
|
||||
}
|
||||
JCVariableDecl result = toP(F.at(pos).VarDef(mods, name, type, init, declaredUsingVar));
|
||||
attach(result, dc);
|
||||
result.startPos = startPos;
|
||||
return result;
|
||||
return attach(result, dc);
|
||||
}
|
||||
|
||||
Name restrictedTypeName(JCExpression e, boolean shouldWarn) {
|
||||
@ -4131,7 +4149,7 @@ public class JavacParser implements Parser {
|
||||
firstTypeDecl = false;
|
||||
}
|
||||
}
|
||||
List<JCTree> topLevelDefs = isImplicitClass ? constructImplicitClass(defs.toList()) : defs.toList();
|
||||
List<JCTree> topLevelDefs = isImplicitClass ? constructImplicitClass(defs.toList(), S.prevToken().endPos) : defs.toList();
|
||||
JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(topLevelDefs);
|
||||
if (!consumedToplevelDoc)
|
||||
attach(toplevel, firstToken.docComment());
|
||||
@ -4141,13 +4159,12 @@ public class JavacParser implements Parser {
|
||||
toplevel.docComments = docComments;
|
||||
if (keepLineMap)
|
||||
toplevel.lineMap = S.getLineMap();
|
||||
this.endPosTable.setParser(null); // remove reference to parser
|
||||
toplevel.endPositions = this.endPosTable;
|
||||
return toplevel;
|
||||
}
|
||||
|
||||
// Restructure top level to be an implicitly declared class.
|
||||
private List<JCTree> constructImplicitClass(List<JCTree> origDefs) {
|
||||
private List<JCTree> constructImplicitClass(List<JCTree> origDefs, int endPos) {
|
||||
ListBuffer<JCTree> topDefs = new ListBuffer<>();
|
||||
ListBuffer<JCTree> defs = new ListBuffer<>();
|
||||
|
||||
@ -4177,6 +4194,7 @@ public class JavacParser implements Parser {
|
||||
JCClassDecl implicit = F.at(primaryPos).ClassDef(
|
||||
implicitMods, name, List.nil(), null, List.nil(), List.nil(),
|
||||
defs.toList());
|
||||
storeEnd(implicit, endPos);
|
||||
topDefs.append(implicit);
|
||||
return topDefs.toList();
|
||||
}
|
||||
@ -4192,11 +4210,12 @@ public class JavacParser implements Parser {
|
||||
accept(LBRACE);
|
||||
directives = moduleDirectiveList();
|
||||
accept(RBRACE);
|
||||
int endPos = S.prevToken().endPos;
|
||||
accept(EOF);
|
||||
|
||||
JCModuleDecl result = toP(F.at(pos).ModuleDef(mods, kind, name, directives));
|
||||
attach(result, dc);
|
||||
return result;
|
||||
JCModuleDecl result = F.at(pos).ModuleDef(mods, kind, name, directives);
|
||||
storeEnd(result, endPos);
|
||||
return attach(result, dc);
|
||||
}
|
||||
|
||||
List<JCDirective> moduleDirectiveList() {
|
||||
@ -4386,8 +4405,7 @@ public class JavacParser implements Parser {
|
||||
List<JCTree> defs = classInterfaceOrRecordBody(name, false, false);
|
||||
JCClassDecl result = toP(F.at(pos).ClassDef(
|
||||
mods, name, typarams, extending, implementing, permitting, defs));
|
||||
attach(result, dc);
|
||||
return result;
|
||||
return attach(result, dc);
|
||||
}
|
||||
|
||||
protected JCClassDecl recordDeclaration(JCModifiers mods, Comment dc) {
|
||||
@ -4434,8 +4452,7 @@ public class JavacParser implements Parser {
|
||||
defs = defs.prepend(field);
|
||||
}
|
||||
JCClassDecl result = toP(F.at(pos).ClassDef(mods, name, typarams, null, implementing, defs));
|
||||
attach(result, dc);
|
||||
return result;
|
||||
return attach(result, dc);
|
||||
}
|
||||
|
||||
Name typeName() {
|
||||
@ -4474,8 +4491,7 @@ public class JavacParser implements Parser {
|
||||
defs = classInterfaceOrRecordBody(name, true, false);
|
||||
JCClassDecl result = toP(F.at(pos).ClassDef(
|
||||
mods, name, typarams, null, extending, permitting, defs));
|
||||
attach(result, dc);
|
||||
return result;
|
||||
return attach(result, dc);
|
||||
}
|
||||
|
||||
List<JCExpression> permitsClause(JCModifiers mods, String classOrInterface) {
|
||||
@ -4522,8 +4538,7 @@ public class JavacParser implements Parser {
|
||||
JCClassDecl result = toP(F.at(pos).
|
||||
ClassDef(mods, name, List.nil(),
|
||||
null, implementing, defs));
|
||||
attach(result, dc);
|
||||
return result;
|
||||
return attach(result, dc);
|
||||
}
|
||||
|
||||
/** EnumBody = "{" { EnumeratorDeclarationList } [","]
|
||||
@ -4664,8 +4679,7 @@ public class JavacParser implements Parser {
|
||||
storeEnd(create, S.prevToken().endPos);
|
||||
ident = F.at(identPos).Ident(enumName);
|
||||
JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
|
||||
attach(result, dc);
|
||||
return result;
|
||||
return attach(result, dc);
|
||||
}
|
||||
|
||||
/** TypeList = Type {"," Type}
|
||||
@ -5097,8 +5111,7 @@ public class JavacParser implements Parser {
|
||||
toP(F.at(pos).MethodDef(mods, name, type, typarams,
|
||||
receiverParam, params, thrown,
|
||||
body, defaultValue));
|
||||
attach(result, dc);
|
||||
return result;
|
||||
return attach(result, dc);
|
||||
} finally {
|
||||
this.receiverParam = prevReceiverParam;
|
||||
}
|
||||
@ -5395,8 +5408,7 @@ public class JavacParser implements Parser {
|
||||
return mostInnerTypeToReturn;
|
||||
} else {
|
||||
mostInnerArrayType.elemtype = mostInnerTypeToReturn;
|
||||
storeEnd(type, origEndPos);
|
||||
return type;
|
||||
return storeEnd(type, origEndPos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5622,121 +5634,69 @@ public class JavacParser implements Parser {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* a functional source tree and end position mappings
|
||||
/**
|
||||
* A straightforward {@link EndPosTable} implementation.
|
||||
*/
|
||||
protected static class SimpleEndPosTable extends AbstractEndPosTable {
|
||||
|
||||
private final IntHashTable endPosMap;
|
||||
private final IntHashTable endPosMap = new IntHashTable();
|
||||
|
||||
SimpleEndPosTable(JavacParser parser) {
|
||||
super(parser);
|
||||
endPosMap = new IntHashTable();
|
||||
}
|
||||
|
||||
public void storeEnd(JCTree tree, int endpos) {
|
||||
endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
|
||||
}
|
||||
|
||||
protected <T extends JCTree> T to(T t) {
|
||||
storeEnd(t, parser.token.endPos);
|
||||
return t;
|
||||
}
|
||||
|
||||
protected <T extends JCTree> T toP(T t) {
|
||||
storeEnd(t, parser.S.prevToken().endPos);
|
||||
return t;
|
||||
@Override
|
||||
public <T extends JCTree> T storeEnd(T tree, int endpos) {
|
||||
endPosMap.put(tree, Math.max(endpos, errorEndPos));
|
||||
return tree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEndPos(JCTree tree) {
|
||||
int value = endPosMap.get(tree);
|
||||
// As long as Position.NOPOS==-1, this just returns value.
|
||||
return (value == -1) ? Position.NOPOS : value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int replaceTree(JCTree oldTree, JCTree newTree) {
|
||||
int pos = endPosMap.remove(oldTree);
|
||||
if (pos != -1) {
|
||||
if (pos != -1 && newTree != null) {
|
||||
storeEnd(newTree, pos);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
return Position.NOPOS;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* a default skeletal implementation without any mapping overhead.
|
||||
/**
|
||||
* A minimal implementation that only stores what's required.
|
||||
*/
|
||||
protected static class EmptyEndPosTable extends AbstractEndPosTable {
|
||||
protected static class MinimalEndPosTable extends SimpleEndPosTable {
|
||||
|
||||
EmptyEndPosTable(JavacParser parser) {
|
||||
super(parser);
|
||||
@Override
|
||||
public <T extends JCTree> T storeEnd(T tree, int endpos) {
|
||||
switch (tree.getTag()) {
|
||||
case MODULEDEF:
|
||||
case PACKAGEDEF:
|
||||
case CLASSDEF:
|
||||
case METHODDEF:
|
||||
case VARDEF:
|
||||
break;
|
||||
default:
|
||||
return tree;
|
||||
}
|
||||
|
||||
public void storeEnd(JCTree tree, int endpos) { /* empty */ }
|
||||
|
||||
protected <T extends JCTree> T to(T t) {
|
||||
return t;
|
||||
return super.storeEnd(tree, endpos);
|
||||
}
|
||||
|
||||
protected <T extends JCTree> T toP(T t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
public int getEndPos(JCTree tree) {
|
||||
return Position.NOPOS;
|
||||
}
|
||||
|
||||
public int replaceTree(JCTree oldTree, JCTree newTree) {
|
||||
return Position.NOPOS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected abstract static class AbstractEndPosTable implements EndPosTable {
|
||||
/**
|
||||
* The current parser.
|
||||
*/
|
||||
protected JavacParser parser;
|
||||
|
||||
/**
|
||||
* Store the last error position.
|
||||
*/
|
||||
public int errorEndPos = Position.NOPOS;
|
||||
|
||||
public AbstractEndPosTable(JavacParser parser) {
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store current token's ending position for a tree, the value of which
|
||||
* will be the greater of last error position and the ending position of
|
||||
* the current token.
|
||||
* @param t The tree.
|
||||
*/
|
||||
protected abstract <T extends JCTree> T to(T t);
|
||||
|
||||
/**
|
||||
* Store current token's ending position for a tree, the value of which
|
||||
* will be the greater of last error position and the ending position of
|
||||
* the previous token.
|
||||
* @param t The tree.
|
||||
*/
|
||||
protected abstract <T extends JCTree> T toP(T t);
|
||||
|
||||
/**
|
||||
* Set the error position during the parsing phases, the value of which
|
||||
* will be set only if it is greater than the last stored error position.
|
||||
* @param errPos The error position
|
||||
*/
|
||||
@Override
|
||||
public void setErrorEndPos(int errPos) {
|
||||
if (errPos > errorEndPos) {
|
||||
errorEndPos = errPos;
|
||||
}
|
||||
}
|
||||
|
||||
public void setParser(JavacParser parser) {
|
||||
this.parser = parser;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2025, 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
|
||||
@ -25,8 +25,21 @@
|
||||
|
||||
package com.sun.tools.javac.tree;
|
||||
|
||||
import com.sun.tools.javac.util.Position;
|
||||
|
||||
/**
|
||||
* Specifies the methods to access a mappings of syntax trees to end positions.
|
||||
*
|
||||
* <p>
|
||||
* Implementations <b>must</b> store end positions for at least these node types:
|
||||
* <ul>
|
||||
* <li>{@link JCTree.JCModuleDecl}
|
||||
* <li>{@link JCTree.JCPackageDecl}
|
||||
* <li>{@link JCTree.JCClassDecl}
|
||||
* <li>{@link JCTree.JCMethodDecl}
|
||||
* <li>{@link JCTree.JCVariableDecl}
|
||||
* </ul>
|
||||
*
|
||||
* <p><b>This is NOT part of any supported API.
|
||||
* If you write code that depends on this, you do so at your own
|
||||
* risk. This code and its internal interfaces are subject to change
|
||||
@ -40,23 +53,31 @@ public interface EndPosTable {
|
||||
* @param tree JCTree
|
||||
* @return position of the source tree or Positions.NOPOS for non-existent mapping
|
||||
*/
|
||||
public int getEndPos(JCTree tree);
|
||||
int getEndPos(JCTree tree);
|
||||
|
||||
/**
|
||||
* Store ending position for a tree, the value of which is the greater of
|
||||
* last error position and the given ending position.
|
||||
* @param tree The tree.
|
||||
* @param endpos The ending position to associate with the tree.
|
||||
* @return the {@code tree}
|
||||
*/
|
||||
public abstract void storeEnd(JCTree tree, int endpos);
|
||||
<T extends JCTree> T storeEnd(T tree, int endpos);
|
||||
|
||||
/**
|
||||
* Set the error position during the parsing phases, the value of which
|
||||
* will be set only if it is greater than the last stored error position.
|
||||
* @param errPos The error position
|
||||
*/
|
||||
void setErrorEndPos(int errPos);
|
||||
|
||||
/**
|
||||
* Give an old tree and a new tree, the old tree will be replaced with
|
||||
* the new tree, the position of the new tree will be that of the old
|
||||
* tree.
|
||||
* @param oldtree a JCTree to be replaced
|
||||
* @param newtree a JCTree to be replaced with
|
||||
* @param newtree a JCTree to be replaced with, or null to just remove {@code oldtree}
|
||||
* @return position of the old tree or Positions.NOPOS for non-existent mapping
|
||||
*/
|
||||
public int replaceTree(JCTree oldtree, JCTree newtree);
|
||||
int replaceTree(JCTree oldtree, JCTree newtree);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2025, 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
|
||||
@ -1121,7 +1121,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
/** statements */
|
||||
public List<JCStatement> stats;
|
||||
/** Position of closing brace, optional. */
|
||||
public int endpos = Position.NOPOS;
|
||||
public int bracePos = Position.NOPOS;
|
||||
/** If this block contains record pattern, it is necessary to catch
|
||||
* exceptions from the deconstructors and wrap them.
|
||||
* The {@code patternMatchingCatch} keeps the list of the deconstructor
|
||||
@ -1330,7 +1330,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
public JCExpression selector;
|
||||
public List<JCCase> cases;
|
||||
/** Position of closing brace, optional. */
|
||||
public int endpos = Position.NOPOS;
|
||||
public int bracePos = Position.NOPOS;
|
||||
public boolean hasUnconditionalPattern;
|
||||
public boolean isExhaustive;
|
||||
public boolean patternSwitch;
|
||||
@ -1430,7 +1430,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
public JCExpression selector;
|
||||
public List<JCCase> cases;
|
||||
/** Position of closing brace, optional. */
|
||||
public int endpos = Position.NOPOS;
|
||||
public int bracePos = Position.NOPOS;
|
||||
public boolean hasUnconditionalPattern;
|
||||
public boolean isExhaustive;
|
||||
public boolean patternSwitch;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2025, 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
|
||||
@ -500,12 +500,12 @@ public class TreeInfo {
|
||||
return tree.pos;
|
||||
}
|
||||
|
||||
/** The end position of given tree, if it is a block with
|
||||
* defined endpos.
|
||||
/** The closing brace position of given tree, if it is a block with
|
||||
* defined bracePos.
|
||||
*/
|
||||
public static int endPos(JCTree tree) {
|
||||
if (tree.hasTag(BLOCK) && ((JCBlock) tree).endpos != Position.NOPOS)
|
||||
return ((JCBlock) tree).endpos;
|
||||
if (tree.hasTag(BLOCK) && ((JCBlock) tree).bracePos != Position.NOPOS)
|
||||
return ((JCBlock) tree).bracePos;
|
||||
else if (tree.hasTag(SYNCHRONIZED))
|
||||
return endPos(((JCSynchronized) tree).body);
|
||||
else if (tree.hasTag(TRY)) {
|
||||
@ -513,11 +513,11 @@ public class TreeInfo {
|
||||
return endPos((t.finalizer != null) ? t.finalizer
|
||||
: (t.catchers.nonEmpty() ? t.catchers.last().body : t.body));
|
||||
} else if (tree.hasTag(SWITCH) &&
|
||||
((JCSwitch) tree).endpos != Position.NOPOS) {
|
||||
return ((JCSwitch) tree).endpos;
|
||||
((JCSwitch) tree).bracePos != Position.NOPOS) {
|
||||
return ((JCSwitch) tree).bracePos;
|
||||
} else if (tree.hasTag(SWITCH_EXPRESSION) &&
|
||||
((JCSwitchExpression) tree).endpos != Position.NOPOS) {
|
||||
return ((JCSwitchExpression) tree).endpos;
|
||||
((JCSwitchExpression) tree).bracePos != Position.NOPOS) {
|
||||
return ((JCSwitchExpression) tree).bracePos;
|
||||
} else
|
||||
return tree.pos;
|
||||
}
|
||||
@ -646,11 +646,6 @@ public class TreeInfo {
|
||||
if (tree == null)
|
||||
return Position.NOPOS;
|
||||
|
||||
if (endPosTable == null) {
|
||||
// fall back on limited info in the tree
|
||||
return endPos(tree);
|
||||
}
|
||||
|
||||
int mapPos = endPosTable.getEndPos(tree);
|
||||
if (mapPos != Position.NOPOS)
|
||||
return mapPos;
|
||||
@ -731,8 +726,8 @@ public class TreeInfo {
|
||||
|
||||
|
||||
/** A DiagnosticPosition with the preferred position set to the
|
||||
* end position of given tree, if it is a block with
|
||||
* defined endpos.
|
||||
* closing brace position of given tree, if it is a block with
|
||||
* defined closing brace position.
|
||||
*/
|
||||
public static DiagnosticPosition diagEndPos(final JCTree tree) {
|
||||
final int endPos = TreeInfo.endPos(tree);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2025, 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
|
||||
@ -141,7 +141,6 @@ class ReplParser extends JavacParser {
|
||||
storeEnd(toplevel, S.prevToken().endPos);
|
||||
}
|
||||
toplevel.lineMap = S.getLineMap();
|
||||
this.endPosTable.setParser(null); // remove reference to parser
|
||||
toplevel.endPositions = this.endPosTable;
|
||||
return toplevel;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2025, 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
|
||||
@ -151,7 +151,7 @@ public class MissingLNTEntryForFinalizerTest {
|
||||
com.sun.tools.javac.code.Type result = super.attribStat(tree, env);
|
||||
if (tree.hasTag(TRY)) {
|
||||
JCTry tryTree = (JCTry)tree;
|
||||
lineNumber = env.toplevel.lineMap.getLineNumber(tryTree.finalizer.endpos);
|
||||
lineNumber = env.toplevel.lineMap.getLineNumber(tryTree.finalizer.bracePos);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
119
test/langtools/tools/javac/parser/DeclarationEndPositions.java
Normal file
119
test/langtools/tools/javac/parser/DeclarationEndPositions.java
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2025, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8350212
|
||||
* @summary Verify ending source positions are calculated for declarations supporting SuppressWarnings
|
||||
* @modules jdk.compiler/com.sun.tools.javac.tree
|
||||
* @run main DeclarationEndPositions
|
||||
*/
|
||||
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.util.TreeScanner;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import com.sun.tools.javac.tree.TreeInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
public class DeclarationEndPositions {
|
||||
|
||||
public static void checkEndPosition(Class<? extends JCTree> nodeType, String input, String marker) throws IOException {
|
||||
|
||||
// Create source
|
||||
var source = new SimpleJavaFileObject(URI.create("file://T.java"), JavaFileObject.Kind.SOURCE) {
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
||||
return input;
|
||||
}
|
||||
};
|
||||
|
||||
// Parse source
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
JavaCompiler.CompilationTask task = compiler.getTask(null, null, null, List.of(), List.of(), List.of(source));
|
||||
Iterable<? extends CompilationUnitTree> units = ((JavacTask)task).parse();
|
||||
|
||||
// Find node and check end position
|
||||
JCTree.JCCompilationUnit unit = (JCTree.JCCompilationUnit)units.iterator().next();
|
||||
unit.accept(new TreeScanner<Void, Void>() {
|
||||
@Override
|
||||
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) {
|
||||
throw new AssertionError(String.format(
|
||||
"wrong end pos %d != %d for \"%s\" @ %d", actual, expected, input, tree.pos));
|
||||
}
|
||||
}
|
||||
return super.scan(node, aVoid);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
|
||||
// JCModuleDecl
|
||||
checkEndPosition(JCModuleDecl.class,
|
||||
"/* comment */ module fred { /* comment */ } /* comment */",
|
||||
" ^ ");
|
||||
|
||||
// JCPackageDecl
|
||||
checkEndPosition(JCPackageDecl.class,
|
||||
"/* comment */ package fred; /* comment */",
|
||||
" ^ ");
|
||||
|
||||
// JCClassDecl
|
||||
checkEndPosition(JCClassDecl.class,
|
||||
"/* comment */ class Fred { /* comment */ } /* comment */",
|
||||
" ^ ");
|
||||
|
||||
// JCMethodDecl
|
||||
checkEndPosition(JCMethodDecl.class,
|
||||
"/* comment */ class Fred { void m() { /* comment */ } } /* comment */",
|
||||
" ^ ");
|
||||
|
||||
// JCVariableDecl
|
||||
checkEndPosition(JCVariableDecl.class,
|
||||
"/* comment */ class Fred { int x; } /* comment */",
|
||||
" ^ ");
|
||||
checkEndPosition(JCVariableDecl.class,
|
||||
"/* comment */ class Fred { int x = 123; } /* comment */",
|
||||
" ^ ");
|
||||
checkEndPosition(JCVariableDecl.class,
|
||||
"/* comment */ class A { try {} catch (Error err) {} } /* comment */",
|
||||
" ^ ");
|
||||
}
|
||||
}
|
@ -2298,10 +2298,9 @@ public class JavacParserTest extends TestCase {
|
||||
|
||||
@Test //JDK-8310326
|
||||
void testUnnamedClassPositions() throws IOException {
|
||||
String code = """
|
||||
void main() {
|
||||
}
|
||||
""";
|
||||
// 0 1 2
|
||||
// 012345678901234567890
|
||||
String code = "void main() { }";
|
||||
DiagnosticCollector<JavaFileObject> coll =
|
||||
new DiagnosticCollector<>();
|
||||
JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null,
|
||||
@ -2313,7 +2312,7 @@ public class JavacParserTest extends TestCase {
|
||||
@Override
|
||||
public Void visitClass(ClassTree node, Void p) {
|
||||
assertEquals("Wrong start position", 0, sp.getStartPosition(cut, node));
|
||||
assertEquals("Wrong end position", -1, sp.getEndPosition(cut, node));
|
||||
assertEquals("Wrong end position", 15, sp.getEndPosition(cut, node));
|
||||
assertEquals("Wrong modifiers start position", -1, sp.getStartPosition(cut, node.getModifiers()));
|
||||
assertEquals("Wrong modifiers end position", -1, sp.getEndPosition(cut, node.getModifiers()));
|
||||
return super.visitClass(node, p);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2025, 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
|
||||
@ -139,7 +139,6 @@ class TrialParser extends JavacParser {
|
||||
storeEnd(toplevel, S.prevToken().endPos);
|
||||
}
|
||||
toplevel.lineMap = S.getLineMap();
|
||||
this.endPosTable.setParser(null); // remove reference to parser
|
||||
toplevel.endPositions = this.endPosTable;
|
||||
return toplevel;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user