mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 18:44:38 +02:00
8017216: javac doesn't fill in end position for some errors of type not found
8019421: Javac doesn't fill in end position for some annotation related errors 8019422: Javac doesn't fill in end position for uninitialized variable errors Reviewed-by: jjg, mcimadamore
This commit is contained in:
parent
c42bcf4526
commit
c6c6fe7b5e
8 changed files with 244 additions and 32 deletions
|
@ -273,7 +273,7 @@ public class Annotate {
|
|||
continue;
|
||||
}
|
||||
JCIdent left = (JCIdent)assign.lhs;
|
||||
Symbol method = rs.resolveQualifiedMethod(left.pos(),
|
||||
Symbol method = rs.resolveQualifiedMethod(assign.rhs.pos(),
|
||||
env,
|
||||
a.type,
|
||||
left.name,
|
||||
|
|
|
@ -1948,6 +1948,8 @@ public class Attr extends JCTree.Visitor {
|
|||
clazzid1 = make.at(clazz.pos).Select(make.Type(encltype),
|
||||
((JCIdent) clazzid).name);
|
||||
|
||||
EndPosTable endPosTable = this.env.toplevel.endPositions;
|
||||
endPosTable.storeEnd(clazzid1, tree.getEndPosition(endPosTable));
|
||||
if (clazz.hasTag(ANNOTATED_TYPE)) {
|
||||
JCAnnotatedType annoType = (JCAnnotatedType) clazz;
|
||||
List<JCAnnotation> annos = annoType.annotations;
|
||||
|
|
|
@ -1339,7 +1339,7 @@ public class Flow {
|
|||
|
||||
/** A mapping from addresses to variable symbols.
|
||||
*/
|
||||
VarSymbol[] vars;
|
||||
JCVariableDecl[] vardecls;
|
||||
|
||||
/** The current class being defined.
|
||||
*/
|
||||
|
@ -1417,13 +1417,14 @@ public class Flow {
|
|||
* to the next available sequence number and entering it under that
|
||||
* index into the vars array.
|
||||
*/
|
||||
void newVar(VarSymbol sym) {
|
||||
vars = ArrayUtils.ensureCapacity(vars, nextadr);
|
||||
void newVar(JCVariableDecl varDecl) {
|
||||
VarSymbol sym = varDecl.sym;
|
||||
vardecls = ArrayUtils.ensureCapacity(vardecls, nextadr);
|
||||
if ((sym.flags() & FINAL) == 0) {
|
||||
sym.flags_field |= EFFECTIVELY_FINAL;
|
||||
}
|
||||
sym.adr = nextadr;
|
||||
vars[nextadr] = sym;
|
||||
vardecls[nextadr] = varDecl;
|
||||
inits.excl(nextadr);
|
||||
uninits.incl(nextadr);
|
||||
nextadr++;
|
||||
|
@ -1493,11 +1494,13 @@ public class Flow {
|
|||
/** Check that trackable variable is initialized.
|
||||
*/
|
||||
void checkInit(DiagnosticPosition pos, VarSymbol sym) {
|
||||
checkInit(pos, sym, "var.might.not.have.been.initialized");
|
||||
}
|
||||
void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
|
||||
if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
|
||||
trackable(sym) &&
|
||||
!inits.isMember(sym.adr)) {
|
||||
log.error(pos, "var.might.not.have.been.initialized",
|
||||
sym);
|
||||
log.error(pos, errkey, sym);
|
||||
inits.incl(sym.adr);
|
||||
}
|
||||
}
|
||||
|
@ -1599,7 +1602,7 @@ public class Flow {
|
|||
if ((def.mods.flags & STATIC) != 0) {
|
||||
VarSymbol sym = def.sym;
|
||||
if (trackable(sym))
|
||||
newVar(sym);
|
||||
newVar(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1619,7 +1622,7 @@ public class Flow {
|
|||
if ((def.mods.flags & STATIC) == 0) {
|
||||
VarSymbol sym = def.sym;
|
||||
if (trackable(sym))
|
||||
newVar(sym);
|
||||
newVar(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1678,9 +1681,22 @@ public class Flow {
|
|||
scan(tree.body);
|
||||
|
||||
if (isInitialConstructor) {
|
||||
for (int i = firstadr; i < nextadr; i++)
|
||||
if (vars[i].owner == classDef.sym)
|
||||
checkInit(TreeInfo.diagEndPos(tree.body), vars[i]);
|
||||
boolean isSynthesized = (tree.sym.flags() &
|
||||
GENERATEDCONSTR) != 0;
|
||||
for (int i = firstadr; i < nextadr; i++) {
|
||||
JCVariableDecl vardecl = vardecls[i];
|
||||
VarSymbol var = vardecl.sym;
|
||||
if (var.owner == classDef.sym) {
|
||||
// choose the diagnostic position based on whether
|
||||
// the ctor is default(synthesized) or not
|
||||
if (isSynthesized) {
|
||||
checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
|
||||
var, "var.not.initialized.in.default.constructor");
|
||||
} else {
|
||||
checkInit(TreeInfo.diagEndPos(tree.body), var);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
List<AssignPendingExit> exits = pendingExits.toList();
|
||||
pendingExits = new ListBuffer<AssignPendingExit>();
|
||||
|
@ -1691,7 +1707,7 @@ public class Flow {
|
|||
if (isInitialConstructor) {
|
||||
inits.assign(exit.exit_inits);
|
||||
for (int i = firstadr; i < nextadr; i++)
|
||||
checkInit(exit.tree.pos(), vars[i]);
|
||||
checkInit(exit.tree.pos(), vardecls[i].sym);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
@ -1706,7 +1722,7 @@ public class Flow {
|
|||
|
||||
public void visitVarDef(JCVariableDecl tree) {
|
||||
boolean track = trackable(tree.sym);
|
||||
if (track && tree.sym.owner.kind == MTH) newVar(tree.sym);
|
||||
if (track && tree.sym.owner.kind == MTH) newVar(tree);
|
||||
if (tree.init != null) {
|
||||
Lint lintPrev = lint;
|
||||
lint = lint.augment(tree.sym);
|
||||
|
@ -2239,11 +2255,11 @@ public class Flow {
|
|||
Flow.this.make = make;
|
||||
startPos = tree.pos().getStartPosition();
|
||||
|
||||
if (vars == null)
|
||||
vars = new VarSymbol[32];
|
||||
if (vardecls == null)
|
||||
vardecls = new JCVariableDecl[32];
|
||||
else
|
||||
for (int i=0; i<vars.length; i++)
|
||||
vars[i] = null;
|
||||
for (int i=0; i<vardecls.length; i++)
|
||||
vardecls[i] = null;
|
||||
firstadr = 0;
|
||||
nextadr = 0;
|
||||
pendingExits = new ListBuffer<AssignPendingExit>();
|
||||
|
@ -2255,8 +2271,8 @@ public class Flow {
|
|||
startPos = -1;
|
||||
resetBits(inits, uninits, uninitsTry, initsWhenTrue,
|
||||
initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse);
|
||||
if (vars != null) for (int i=0; i<vars.length; i++)
|
||||
vars[i] = null;
|
||||
if (vardecls != null) for (int i=0; i<vardecls.length; i++)
|
||||
vardecls[i] = null;
|
||||
firstadr = 0;
|
||||
nextadr = 0;
|
||||
pendingExits = null;
|
||||
|
|
|
@ -4053,7 +4053,7 @@ public class JavacParser implements Parser {
|
|||
endPosMap = new HashMap<JCTree, Integer>();
|
||||
}
|
||||
|
||||
protected void storeEnd(JCTree tree, int endpos) {
|
||||
public void storeEnd(JCTree tree, int endpos) {
|
||||
endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
|
||||
}
|
||||
|
||||
|
@ -4091,7 +4091,7 @@ public class JavacParser implements Parser {
|
|||
super(parser);
|
||||
}
|
||||
|
||||
protected void storeEnd(JCTree tree, int endpos) { /* empty */ }
|
||||
public void storeEnd(JCTree tree, int endpos) { /* empty */ }
|
||||
|
||||
protected <T extends JCTree> T to(T t) {
|
||||
return t;
|
||||
|
@ -4126,14 +4126,6 @@ public class JavacParser implements Parser {
|
|||
this.parser = parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected abstract void storeEnd(JCTree tree, int endpos);
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -1068,6 +1068,10 @@ compiler.err.var.might.already.be.assigned=\
|
|||
compiler.err.var.might.not.have.been.initialized=\
|
||||
variable {0} might not have been initialized
|
||||
|
||||
# 0: symbol
|
||||
compiler.err.var.not.initialized.in.default.constructor=\
|
||||
variable {0} not initialized in the default constructor
|
||||
|
||||
# 0: symbol
|
||||
compiler.err.var.might.be.assigned.in.loop=\
|
||||
variable {0} might be assigned in loop
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2013, 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
|
||||
|
@ -42,11 +42,18 @@ public interface EndPosTable {
|
|||
*/
|
||||
public 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.
|
||||
*/
|
||||
public abstract void storeEnd(JCTree tree, int endpos);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* not exist.
|
||||
* @param oldtree a JCTree to be replaced
|
||||
* @param newtree a JCTree to be replaced with
|
||||
* @return position of the old tree or Positions.NOPOS for non-existent mapping
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 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.
|
||||
*/
|
||||
|
||||
// key: compiler.err.var.not.initialized.in.default.constructor
|
||||
|
||||
class X {
|
||||
final int j;
|
||||
}
|
163
langtools/test/tools/javac/positions/TreeEndPosTest.java
Normal file
163
langtools/test/tools/javac/positions/TreeEndPosTest.java
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 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 8017216 8019422 8019421
|
||||
* @summary verify start and end positions
|
||||
* @run main TreeEndPosTest
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.DiagnosticCollector;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
public class TreeEndPosTest {
|
||||
private static JavaFileManager getJavaFileManager(JavaCompiler compiler,
|
||||
DiagnosticCollector dc) {
|
||||
return compiler.getStandardFileManager(dc, null, null);
|
||||
}
|
||||
|
||||
static class JavaSource extends SimpleJavaFileObject {
|
||||
|
||||
final String source;
|
||||
int startPos;
|
||||
int endPos;
|
||||
|
||||
private JavaSource(String filename, String source) {
|
||||
super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return source;
|
||||
}
|
||||
|
||||
static JavaSource createJavaSource(String preamble, String body,
|
||||
String postamble, String expected) {
|
||||
JavaSource js = createJavaSource(preamble, body, postamble, -1, -1);
|
||||
js.startPos = js.source.indexOf(expected);
|
||||
js.endPos = js.startPos + expected.length();
|
||||
return js;
|
||||
}
|
||||
|
||||
static JavaSource createJavaSource(String body, String expected) {
|
||||
return createJavaSource(null, body, null, expected);
|
||||
}
|
||||
|
||||
private static JavaSource createJavaSource(String preamble, String body,
|
||||
String postamble, int start, int end) {
|
||||
final String name = "Bug";
|
||||
StringBuilder code = new StringBuilder();
|
||||
if (preamble != null) {
|
||||
code.append(preamble);
|
||||
}
|
||||
code.append("public class " + name + "{");
|
||||
if (body != null) {
|
||||
code.append(body);
|
||||
}
|
||||
code.append("}");
|
||||
if (postamble != null) {
|
||||
code.append(postamble);
|
||||
}
|
||||
JavaSource js = new JavaSource(name + ".java", code.toString());
|
||||
js.startPos = start;
|
||||
js.endPos = end;
|
||||
return js;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String... args) throws IOException {
|
||||
testUninitializedVariable();
|
||||
testMissingAnnotationValue();
|
||||
testFinalVariableWithDefaultConstructor();
|
||||
testFinalVariableWithConstructor();
|
||||
}
|
||||
|
||||
static void testUninitializedVariable() throws IOException {
|
||||
compile(JavaSource.createJavaSource("Object o = new A().new B(); class A { }",
|
||||
"B()"));
|
||||
}
|
||||
static void testMissingAnnotationValue() throws IOException {
|
||||
compile(JavaSource.createJavaSource("@Foo(\"vvvv\")",
|
||||
null, "@interface Foo { }", "\"vvvv\""));
|
||||
}
|
||||
|
||||
static void testFinalVariableWithDefaultConstructor() throws IOException {
|
||||
compile(JavaSource.createJavaSource("private static final String Foo; public void bar() { }",
|
||||
"private static final String Foo;"));
|
||||
}
|
||||
|
||||
static void testFinalVariableWithConstructor() throws IOException {
|
||||
compile(JavaSource.createJavaSource("public Bug (){} private static final String Foo; public void bar() { }",
|
||||
"{}"));
|
||||
}
|
||||
|
||||
static void compile(JavaSource src) throws IOException {
|
||||
ByteArrayOutputStream ba = new ByteArrayOutputStream();
|
||||
PrintWriter writer = new PrintWriter(ba);
|
||||
File tempDir = new File(".");
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
DiagnosticCollector dc = new DiagnosticCollector();
|
||||
JavaFileManager javaFileManager = getJavaFileManager(compiler, dc);
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add("-cp");
|
||||
options.add(tempDir.getPath());
|
||||
options.add("-d");
|
||||
options.add(tempDir.getPath());
|
||||
options.add("-XDshouldStopPolicy=GENERATE");
|
||||
|
||||
List<JavaFileObject> sources = new ArrayList<>();
|
||||
sources.add(src);
|
||||
JavaCompiler.CompilationTask task =
|
||||
compiler.getTask(writer, javaFileManager,
|
||||
dc, options, null,
|
||||
sources);
|
||||
task.call();
|
||||
for (Diagnostic diagnostic : (List<Diagnostic>) dc.getDiagnostics()) {
|
||||
long actualStart = diagnostic.getStartPosition();
|
||||
long actualEnd = diagnostic.getEndPosition();
|
||||
System.out.println("Source: " + src.source);
|
||||
System.out.println("Diagnostic: " + diagnostic);
|
||||
System.out.print("Start position: Expected: " + src.startPos);
|
||||
System.out.println(", Actual: " + actualStart);
|
||||
System.out.print("End position: Expected: " + src.endPos);
|
||||
System.out.println(", Actual: " + actualEnd);
|
||||
if (src.startPos != actualStart || src.endPos != actualEnd) {
|
||||
throw new RuntimeException("error: trees don't match");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue