This commit is contained in:
Lana Steuck 2010-09-24 16:43:08 -07:00
commit 98b2aad842
133 changed files with 5470 additions and 754 deletions

View File

@ -275,6 +275,7 @@
failOnError="false"
errorProperty="findbugs.all.errors"
warningsProperty="findbugs.all.warnings"
jvm="${target.java.home}/bin/java"
jvmargs="-Xmx512M">
<class location="${build.classes.dir}"/>
<sourcePath>
@ -621,7 +622,7 @@
<genstubs
srcdir="${import.jdk.src.dir}" destdir="${build.genstubs.dir}"
includes="${import.jdk.stub.files}"
fork="true" classpath="${build.toolclasses.dir}:${build.bootstrap.dir}/classes:${ant.home}/lib/ant.jar"
fork="true" classpath="${build.toolclasses.dir}:${build.bootstrap.dir}/classes:${ant.core.lib}"
/>
</target>
@ -673,6 +674,7 @@
<filterset begintoken="#" endtoken="#">
<filter token="PROGRAM" value="@{name}"/>
<filter token="TARGET_JAVA" value="@{java}"/>
<filter token="PS" value="${path.separator}"/>
</filterset>
</copy>
<chmod file="@{bin.dir}/@{name}" perm="ugo+rx"/>
@ -812,7 +814,8 @@
executable="${boot.java.home}/bin/javac"
srcdir="${make.tools.dir}/CompileProperties"
destdir="${build.toolclasses.dir}/"
classpath="${ant.home}/lib/ant.jar"/>
classpath="${ant.core.lib}"
includeantruntime="false"/>
<taskdef name="pcompile"
classname="CompilePropertiesTask"
classpath="${build.toolclasses.dir}/"/>
@ -826,7 +829,8 @@
executable="${boot.java.home}/bin/javac"
srcdir="${make.tools.dir}/GenStubs"
destdir="${build.toolclasses.dir}/"
classpath="${build.bootstrap.dir}/classes:${ant.home}/lib/ant.jar"/>
classpath="${build.bootstrap.dir}/classes:${ant.core.lib}"
includeantruntime="false"/>
<taskdef name="genstubs"
classname="GenStubs$$Ant"
classpath="${build.toolclasses.dir}/"/>
@ -935,7 +939,8 @@
<taskdef classpathref="cobertura.classpath" resource="tasks.properties"/>
</target>
<target name="-def-findbugs" unless="findbugs.defined" depends="-check-findbugs.home">
<target name="-def-findbugs" unless="findbugs.defined"
depends="-check-findbugs.home,-check-target.java.home">
<taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask">
<classpath>
<pathelement location="${findbugs.home}/lib/findbugs.jar"/>
@ -955,6 +960,7 @@
failOnError="false"
errorProperty="findbugs.@{name}.errors"
warningsProperty="findbugs.@{name}.warnings"
jvm="${target.java.home}/bin/java"
jvmargs="-Xmx512M" >
<class location="${dist.dir}/lib/@{name}.jar"/>
<auxClasspath>

View File

@ -40,8 +40,8 @@ mylib="`dirname $mydir`"/lib
if [ "$LANGTOOLS_USE_BOOTCLASSPATH" != "no" ]; then
cp=`unzip -c "$mylib/#PROGRAM#.jar" META-INF/MANIFEST.MF |
grep "Class-Path:" |
sed -e 's|Class-Path: *||' -e 's|\([a-z]*\.jar\) *|'"$mylib"'/\1:|g'`
bcp="$mylib/#PROGRAM#.jar":$cp
sed -e 's|Class-Path: *||' -e 's|\([a-z]*\.jar\) *|'"$mylib"'/\1#PS#|g'`
bcp="$mylib/#PROGRAM#.jar#PS#$cp"
fi
# tools currently assumes that assertions are enabled in the launcher

View File

@ -94,7 +94,7 @@ public interface Tree {
CATCH(CatchTree.class),
/**
* Used for instances of {@link ClassTree}.
* Used for instances of {@link ClassTree} representing classes.
*/
CLASS(ClassTree.class),
@ -557,6 +557,21 @@ public interface Tree {
*/
ERRONEOUS(ErroneousTree.class),
/**
* Used for instances of {@link ClassTree} representing interfaces.
*/
INTERFACE(ClassTree.class),
/**
* Used for instances of {@link ClassTree} representing enums.
*/
ENUM(ClassTree.class),
/**
* Used for instances of {@link ClassTree} representing annotation types.
*/
ANNOTATION_TYPE(ClassTree.class),
/**
* An implementation-reserved node. This is the not the node
* you are looking for.

View File

@ -141,6 +141,7 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
r = scanAndReduce(node.getReceiverAnnotations(), p, r);
r = scanAndReduce(node.getThrows(), p, r);
r = scanAndReduce(node.getBody(), p, r);
r = scanAndReduce(node.getDefaultValue(), p, r);
return r;
}

View File

@ -45,6 +45,7 @@ import com.sun.source.tree.Tree;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Symbol;
@ -189,8 +190,24 @@ public class JavacTrees extends Trees {
}
public Element getElement(TreePath path) {
Tree t = path.getLeaf();
return TreeInfo.symbolFor((JCTree) t);
JCTree tree = (JCTree) path.getLeaf();
Symbol sym = TreeInfo.symbolFor(tree);
if (sym == null && TreeInfo.isDeclaration(tree)) {
for (TreePath p = path; p != null; p = p.getParentPath()) {
JCTree t = (JCTree) p.getLeaf();
if (t.getTag() == JCTree.CLASSDEF) {
JCClassDecl ct = (JCClassDecl) t;
if (ct.sym != null) {
if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
attr.attribClass(ct.pos(), ct.sym);
sym = TreeInfo.symbolFor(tree);
}
break;
}
}
}
}
return sym;
}
public TypeMirror getTypeMirror(TreePath path) {
@ -258,6 +275,8 @@ public class JavacTrees extends Trees {
env = enter.getTopLevelEnv((JCCompilationUnit)tree);
break;
case CLASS:
case INTERFACE:
case ENUM:
// System.err.println("CLASS: " + ((JCClassDecl)tree).sym.getSimpleName());
env = enter.getClassEnv(((JCClassDecl)tree).sym);
break;

View File

@ -295,4 +295,11 @@ public abstract class Attribute implements AnnotationValue {
void visitEnum(Attribute.Enum e);
void visitError(Attribute.Error e);
}
/** A mirror of java.lang.annotation.RetentionPolicy. */
public static enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
}

View File

@ -241,6 +241,12 @@ public class Flags {
*/
public static final long POLYMORPHIC_SIGNATURE = 1L<<40;
/**
* Flag that marks a special kind of bridge methods (the ones that
* come from restricted supertype bounds)
*/
public static final long OVERRIDE_BRIDGE = 1L<<41;
/** Modifier masks.
*/
public static final int

View File

@ -272,6 +272,12 @@ public class Scope {
return false;
}
static final Filter<Symbol> noFilter = new Filter<Symbol>() {
public boolean accepts(Symbol s) {
return true;
}
};
/** Return the entry associated with given name, starting in
* this scope and proceeding outwards. If no entry was found,
* return the sentinel, which is characterized by having a null in
@ -279,13 +285,20 @@ public class Scope {
* for regular entries.
*/
public Entry lookup(Name name) {
return lookup(name, noFilter);
}
public Entry lookup(Name name, Filter<Symbol> sf) {
Entry e = table[name.hashCode() & hashMask];
while (e.scope != null && e.sym.name != name)
while (e.scope != null && (e.sym.name != name || !sf.accepts(e.sym)))
e = e.shadowed;
return e;
}
public Iterable<Symbol> getElements() {
return getElements(noFilter);
}
public Iterable<Symbol> getElements(final Filter<Symbol> sf) {
return new Iterable<Symbol>() {
public Iterator<Symbol> iterator() {
return new Iterator<Symbol>() {
@ -301,7 +314,9 @@ public class Scope {
public Symbol next() {
Symbol sym = (currEntry == null ? null : currEntry.sym);
currEntry = currEntry.sibling;
if (currEntry != null) {
currEntry = currEntry.sibling;
}
update();
return sym;
}
@ -311,9 +326,17 @@ public class Scope {
}
private void update() {
skipToNextMatchingEntry();
while (currEntry == null && currScope.next != null) {
currScope = currScope.next;
currEntry = currScope.elems;
skipToNextMatchingEntry();
}
}
void skipToNextMatchingEntry() {
while (currEntry != null && !sf.accepts(currEntry.sym)) {
currEntry = currEntry.sibling;
}
}
};

View File

@ -171,11 +171,10 @@ public enum Source {
public boolean allowUnderscoresInLiterals() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowStringsInSwitch() {
public boolean allowExoticIdentifiers() {
return compareTo(JDK1_7) >= 0;
}
// JSR 292: recognize @PolymorphicSignature on java/dyn names
public boolean allowPolymorphicSignature() {
public boolean allowStringsInSwitch() {
return compareTo(JDK1_7) >= 0;
}
public static SourceVersion toSourceVersion(Source source) {

View File

@ -214,6 +214,16 @@ public abstract class Symbol implements Element {
return (flags() & INTERFACE) != 0;
}
/** Recognize if this symbol was marked @PolymorphicSignature in the source. */
public boolean isPolymorphicSignatureGeneric() {
return (flags() & (POLYMORPHIC_SIGNATURE | HYPOTHETICAL)) == POLYMORPHIC_SIGNATURE;
}
/** Recognize if this symbol was split from a @PolymorphicSignature symbol in the source. */
public boolean isPolymorphicSignatureInstance() {
return (flags() & (POLYMORPHIC_SIGNATURE | HYPOTHETICAL)) == (POLYMORPHIC_SIGNATURE | HYPOTHETICAL);
}
/** Is this symbol declared (directly or indirectly) local
* to a method or variable initializer?
* Also includes fields of inner classes which are in
@ -579,6 +589,9 @@ public abstract class Symbol implements Element {
public java.util.List<Symbol> getEnclosedElements() {
List<Symbol> list = List.nil();
if (kind == TYP && type.tag == TYPEVAR) {
return list;
}
for (Scope.Entry e = members().elems; e != null; e = e.sibling) {
if (e.sym != null && (e.sym.flags() & SYNTHETIC) == 0 && e.sym.owner == this)
list = list.prepend(e.sym);
@ -1214,7 +1227,18 @@ public abstract class Symbol implements Element {
* as possible implementations.
*/
public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) {
MethodSymbol res = types.implementation(this, origin, types, checkResult);
return implementation(origin, types, checkResult, implementation_filter);
}
// where
private static final Filter<Symbol> implementation_filter = new Filter<Symbol>() {
public boolean accepts(Symbol s) {
return s.kind == Kinds.MTH &&
(s.flags() & SYNTHETIC) == 0;
}
};
public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult, Filter<Symbol> implFilter) {
MethodSymbol res = types.implementation(this, origin, types, checkResult, implFilter);
if (res != null)
return res;
// if origin is derived from a raw type, we might have missed

View File

@ -93,6 +93,10 @@ public class Symtab {
*/
public final ClassSymbol errSymbol;
/** The unknown symbol.
*/
public final ClassSymbol unknownSymbol;
/** A value for the errType, with a originalType of noType */
public final Type errType;
@ -354,6 +358,7 @@ public class Symtab {
// create the error symbols
errSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.any, null, rootPackage);
unknownSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.fromString("<any?>"), null, rootPackage);
errType = new ErrorType(errSymbol, Type.noType);
// initialize builtin types
@ -368,7 +373,7 @@ public class Symtab {
initType(voidType, "void", "Void");
initType(botType, "<nulltype>");
initType(errType, errSymbol);
initType(unknownType, "<any?>");
initType(unknownType, unknownSymbol);
// the builtin class of all arrays
arrayClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Array, noSymbol);

View File

@ -114,6 +114,8 @@ public class TypeAnnotations {
return p;
case CLASS:
case INTERFACE:
case ENUM:
p.pos = frame.pos;
if (((JCClassDecl)frame).extending == tree) {
p.type = TargetType.CLASS_EXTENDS;

View File

@ -32,6 +32,7 @@ import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.jvm.ClassReader;
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.comp.Check;
import static com.sun.tools.javac.code.Type.*;
@ -914,7 +915,7 @@ public class Types {
return true;
if (t.isPrimitive() != s.isPrimitive())
return allowBoxing && isConvertible(t, s, warn);
return allowBoxing && (isConvertible(t, s, warn) || isConvertible(s, t, warn));
if (warn != warnStack.head) {
try {
@ -1973,45 +1974,74 @@ public class Types {
hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s);
}
private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache_check =
new WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>>();
// <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site">
class ImplementationCache {
private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache_nocheck =
new WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>>();
private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>> _map =
new WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>>();
public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult) {
Map<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache = checkResult ?
implCache_check : implCache_nocheck;
SoftReference<Map<TypeSymbol, MethodSymbol>> ref_cache = implCache.get(ms);
Map<TypeSymbol, MethodSymbol> cache = ref_cache != null ? ref_cache.get() : null;
if (cache == null) {
cache = new HashMap<TypeSymbol, MethodSymbol>();
implCache.put(ms, new SoftReference<Map<TypeSymbol, MethodSymbol>>(cache));
class Entry {
final MethodSymbol cachedImpl;
final Filter<Symbol> implFilter;
final boolean checkResult;
public Entry(MethodSymbol cachedImpl,
Filter<Symbol> scopeFilter,
boolean checkResult) {
this.cachedImpl = cachedImpl;
this.implFilter = scopeFilter;
this.checkResult = checkResult;
}
boolean matches(Filter<Symbol> scopeFilter, boolean checkResult) {
return this.implFilter == scopeFilter &&
this.checkResult == checkResult;
}
}
MethodSymbol impl = cache.get(origin);
if (impl == null) {
MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
SoftReference<Map<TypeSymbol, Entry>> ref_cache = _map.get(ms);
Map<TypeSymbol, Entry> cache = ref_cache != null ? ref_cache.get() : null;
if (cache == null) {
cache = new HashMap<TypeSymbol, Entry>();
_map.put(ms, new SoftReference<Map<TypeSymbol, Entry>>(cache));
}
Entry e = cache.get(origin);
if (e == null ||
!e.matches(implFilter, checkResult)) {
MethodSymbol impl = implementationInternal(ms, origin, Types.this, checkResult, implFilter);
cache.put(origin, new Entry(impl, implFilter, checkResult));
return impl;
}
else {
return e.cachedImpl;
}
}
private MethodSymbol implementationInternal(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult, Filter<Symbol> implFilter) {
for (Type t = origin.type; t.tag == CLASS || t.tag == TYPEVAR; t = types.supertype(t)) {
while (t.tag == TYPEVAR)
t = t.getUpperBound();
TypeSymbol c = t.tsym;
for (Scope.Entry e = c.members().lookup(ms.name);
for (Scope.Entry e = c.members().lookup(ms.name, implFilter);
e.scope != null;
e = e.next()) {
if (e.sym.kind == Kinds.MTH) {
MethodSymbol m = (MethodSymbol) e.sym;
if (m.overrides(ms, origin, types, checkResult) &&
(m.flags() & SYNTHETIC) == 0) {
impl = m;
cache.put(origin, m);
return impl;
}
}
if (e.sym != null &&
e.sym.overrides(ms, origin, types, checkResult))
return (MethodSymbol)e.sym;
}
}
return null;
}
return impl;
}
private ImplementationCache implCache = new ImplementationCache();
public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult, Filter<Symbol> implFilter) {
return implCache.get(ms, origin, checkResult, implFilter);
}
// </editor-fold>
/**
* Does t have the same arguments as s? It is assumed that both
* types are (possibly polymorphic) method types. Monomorphic
@ -3554,4 +3584,24 @@ public class Types {
public Type visitType(Type t, S s) { return t; }
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Annotation support">
public RetentionPolicy getRetention(Attribute.Compound a) {
RetentionPolicy vis = RetentionPolicy.CLASS; // the default
Attribute.Compound c = a.type.tsym.attribute(syms.retentionType.tsym);
if (c != null) {
Attribute value = c.member(names.value);
if (value != null && value instanceof Attribute.Enum) {
Name levelName = ((Attribute.Enum)value).value.name;
if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE;
else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS;
else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME;
else ;// /* fail soft */ throw new AssertionError(levelName);
}
}
return vis;
}
// </editor-fold>
}

View File

@ -182,6 +182,7 @@ public class Annotate {
if (!method.type.isErroneous())
buf.append(new Pair<MethodSymbol,Attribute>
((MethodSymbol)method, value));
t.type = result;
}
return new Attribute.Compound(a.type, buf.toList());
}
@ -234,6 +235,7 @@ public class Annotate {
l.head,
env));
}
na.type = expected;
return new Attribute.
Array(expected, buf.toArray(new Attribute[buf.length()]));
}

View File

@ -328,6 +328,12 @@ public class Attr extends JCTree.Visitor {
attribExpr(expr, env);
} catch (BreakAttr b) {
return b.env;
} catch (AssertionError ae) {
if (ae.getCause() instanceof BreakAttr) {
return ((BreakAttr)(ae.getCause())).env;
} else {
throw ae;
}
} finally {
breakTree = null;
log.useSource(prev);
@ -342,6 +348,12 @@ public class Attr extends JCTree.Visitor {
attribStat(stmt, env);
} catch (BreakAttr b) {
return b.env;
} catch (AssertionError ae) {
if (ae.getCause() instanceof BreakAttr) {
return ((BreakAttr)(ae.getCause())).env;
} else {
throw ae;
}
} finally {
breakTree = null;
log.useSource(prev);
@ -578,6 +590,8 @@ public class Attr extends JCTree.Visitor {
boolean classExpected,
boolean interfaceExpected,
boolean checkExtensible) {
if (t.isErroneous())
return t;
if (t.tag == TYPEVAR && !classExpected && !interfaceExpected) {
// check that type variable is already visible
if (t.getUpperBound() == null) {
@ -595,7 +609,7 @@ public class Attr extends JCTree.Visitor {
} else if (checkExtensible &&
classExpected &&
(t.tsym.flags() & INTERFACE) != 0) {
log.error(tree.pos(), "no.intf.expected.here");
log.error(tree.pos(), "no.intf.expected.here");
return types.createErrorType(t);
}
if (checkExtensible &&
@ -1171,7 +1185,10 @@ public class Attr extends JCTree.Visitor {
}
public void visitExec(JCExpressionStatement tree) {
attribExpr(tree.expr, env);
//a fresh environment is required for 292 inference to work properly ---
//see Infer.instantiatePolymorphicSignatureInstance()
Env<AttrContext> localEnv = env.dup(tree);
attribExpr(tree.expr, localEnv);
result = null;
}
@ -1429,23 +1446,19 @@ public class Attr extends JCTree.Visitor {
restype.tsym);
}
// as a special case, MethodHandle.<T>invoke(abc) and InvokeDynamic.<T>foo(abc)
// has type <T>, and T can be a primitive type.
if (tree.meth.getTag() == JCTree.SELECT && !typeargtypes.isEmpty()) {
JCFieldAccess mfield = (JCFieldAccess) tree.meth;
if ((mfield.selected.type.tsym != null &&
(mfield.selected.type.tsym.flags() & POLYMORPHIC_SIGNATURE) != 0)
||
(mfield.sym != null &&
(mfield.sym.flags() & POLYMORPHIC_SIGNATURE) != 0)) {
assert types.isSameType(restype, typeargtypes.head) : mtype;
assert mfield.selected.type == syms.methodHandleType
|| mfield.selected.type == syms.invokeDynamicType;
typeargtypesNonRefOK = true;
}
// Special case logic for JSR 292 types.
if (rs.allowTransitionalJSR292 &&
tree.meth.getTag() == JCTree.SELECT &&
!typeargtypes.isEmpty()) {
JCFieldAccess mfield = (JCFieldAccess) tree.meth;
// MethodHandle.<T>invoke(abc) and InvokeDynamic.<T>foo(abc)
// has type <T>, and T can be a primitive type.
if (mfield.sym != null &&
mfield.sym.isPolymorphicSignatureInstance())
typeargtypesNonRefOK = true;
}
if (!typeargtypesNonRefOK) {
if (!(rs.allowTransitionalJSR292 && typeargtypesNonRefOK)) {
chk.checkRefTypes(tree.typeargs, typeargtypes);
}
@ -2009,7 +2022,10 @@ public class Attr extends JCTree.Visitor {
public void visitTypeCast(JCTypeCast tree) {
Type clazztype = attribType(tree.clazz, env);
chk.validate(tree.clazz, env, false);
Type exprtype = attribExpr(tree.expr, env, Infer.anyPoly);
//a fresh environment is required for 292 inference to work properly ---
//see Infer.instantiatePolymorphicSignatureInstance()
Env<AttrContext> localEnv = env.dup(tree);
Type exprtype = attribExpr(tree.expr, localEnv, Infer.anyPoly);
Type owntype = chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
if (exprtype.constValue() != null)
owntype = cfolder.coerce(exprtype, owntype);
@ -2845,7 +2861,6 @@ public class Attr extends JCTree.Visitor {
if (tree.bounds.tail.nonEmpty()) {
log.error(tree.bounds.tail.head.pos(),
"type.var.may.not.be.followed.by.other.bounds");
log.unrecoverableError = true;
tree.bounds = List.of(tree.bounds.head);
a.bound = bs.head;
}
@ -3186,4 +3201,104 @@ public class Attr extends JCTree.Visitor {
super.visitMethodDef(tree);
}
};
// <editor-fold desc="post-attribution visitor">
/**
* Handle missing types/symbols in an AST. This routine is useful when
* the compiler has encountered some errors (which might have ended up
* terminating attribution abruptly); if the compiler is used in fail-over
* mode (e.g. by an IDE) and the AST contains semantic errors, this routine
* prevents NPE to be progagated during subsequent compilation steps.
*/
public void postAttr(Env<AttrContext> env) {
new PostAttrAnalyzer().scan(env.tree);
}
class PostAttrAnalyzer extends TreeScanner {
private void initTypeIfNeeded(JCTree that) {
if (that.type == null) {
that.type = syms.unknownType;
}
}
@Override
public void scan(JCTree tree) {
if (tree == null) return;
if (tree instanceof JCExpression) {
initTypeIfNeeded(tree);
}
super.scan(tree);
}
@Override
public void visitIdent(JCIdent that) {
if (that.sym == null) {
that.sym = syms.unknownSymbol;
}
}
@Override
public void visitSelect(JCFieldAccess that) {
if (that.sym == null) {
that.sym = syms.unknownSymbol;
}
super.visitSelect(that);
}
@Override
public void visitClassDef(JCClassDecl that) {
initTypeIfNeeded(that);
if (that.sym == null) {
that.sym = new ClassSymbol(0, that.name, that.type, syms.noSymbol);
}
super.visitClassDef(that);
}
@Override
public void visitMethodDef(JCMethodDecl that) {
initTypeIfNeeded(that);
if (that.sym == null) {
that.sym = new MethodSymbol(0, that.name, that.type, syms.noSymbol);
}
super.visitMethodDef(that);
}
@Override
public void visitVarDef(JCVariableDecl that) {
initTypeIfNeeded(that);
if (that.sym == null) {
that.sym = new VarSymbol(0, that.name, that.type, syms.noSymbol);
that.sym.adr = 0;
}
super.visitVarDef(that);
}
@Override
public void visitNewClass(JCNewClass that) {
if (that.constructor == null) {
that.constructor = new MethodSymbol(0, names.init, syms.unknownType, syms.noSymbol);
}
if (that.constructorType == null) {
that.constructorType = syms.unknownType;
}
super.visitNewClass(that);
}
@Override
public void visitBinary(JCBinary that) {
if (that.operator == null)
that.operator = new OperatorSymbol(names.empty, syms.unknownType, -1, syms.noSymbol);
super.visitBinary(that);
}
@Override
public void visitUnary(JCUnary that) {
if (that.operator == null)
that.operator = new OperatorSymbol(names.empty, syms.unknownType, -1, syms.noSymbol);
super.visitUnary(that);
}
}
// </editor-fold>
}

View File

@ -38,6 +38,7 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.main.RecognizedOptions.PkgInfo;
import com.sun.tools.javac.tree.JCTree.*;
import static com.sun.tools.javac.code.Flags.*;
@ -102,6 +103,7 @@ public class Enter extends JCTree.Visitor {
Lint lint;
Names names;
JavaFileManager fileManager;
PkgInfo pkginfoOpt;
private final Todo todo;
@ -132,6 +134,9 @@ public class Enter extends JCTree.Visitor {
predefClassDef.sym = syms.predefClass;
todo = Todo.instance(context);
fileManager = context.get(JavaFileManager.class);
Options options = Options.instance(context);
pkginfoOpt = PkgInfo.get(options);
}
/** A hashtable mapping classes and packages to the environments current
@ -278,7 +283,7 @@ public class Enter extends JCTree.Visitor {
JavaFileObject.Kind.SOURCE);
if (tree.pid != null) {
tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid));
if (tree.packageAnnotations.nonEmpty()) {
if (tree.packageAnnotations.nonEmpty() || pkginfoOpt == PkgInfo.ALWAYS) {
if (isPkgInfo) {
addEnv = true;
} else {

View File

@ -408,7 +408,9 @@ public class Flow extends TreeScanner {
tree = TreeInfo.skipParens(tree);
if (tree.getTag() == JCTree.IDENT || tree.getTag() == JCTree.SELECT) {
Symbol sym = TreeInfo.symbol(tree);
letInit(tree.pos(), (VarSymbol)sym);
if (sym.kind == VAR) {
letInit(tree.pos(), (VarSymbol)sym);
}
}
}
@ -481,12 +483,13 @@ public class Flow extends TreeScanner {
/** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets
*/
void split() {
void split(boolean setToNull) {
initsWhenFalse = inits.dup();
uninitsWhenFalse = uninits.dup();
initsWhenTrue = inits;
uninitsWhenTrue = uninits;
inits = uninits = null;
if (setToNull)
inits = uninits = null;
}
/** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
@ -568,9 +571,11 @@ public class Flow extends TreeScanner {
uninitsWhenTrue = uninits;
} else {
scan(tree);
if (inits != null) split();
if (inits != null)
split(tree.type != syms.unknownType);
}
inits = uninits = null;
if (tree.type != syms.unknownType)
inits = uninits = null;
}
/* ------------ Visitor methods for various sorts of trees -------------*/
@ -1007,7 +1012,7 @@ public class Flow extends TreeScanner {
List.of(resource.type);
for (Type sup : closeableSupertypes) {
if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) {
Symbol closeMethod = rs.resolveInternalMethod(tree,
Symbol closeMethod = rs.resolveQualifiedMethod(tree,
attrEnv,
sup,
names.close,
@ -1050,20 +1055,22 @@ public class Flow extends TreeScanner {
List<Type> rethrownTypes = chk.diff(thrownInTry, caughtInTry);
for (JCExpression ct : subClauses) {
Type exc = ct.type;
ctypes = ctypes.append(exc);
if (types.isSameType(exc, syms.objectType))
continue;
if (chk.subset(exc, caughtInTry)) {
log.error(l.head.pos(),
"except.already.caught", exc);
} else if (!chk.isUnchecked(l.head.pos(), exc) &&
exc.tsym != syms.throwableType.tsym &&
exc.tsym != syms.exceptionType.tsym &&
!chk.intersects(exc, thrownInTry)) {
log.error(l.head.pos(),
"except.never.thrown.in.try", exc);
if (exc != syms.unknownType) {
ctypes = ctypes.append(exc);
if (types.isSameType(exc, syms.objectType))
continue;
if (chk.subset(exc, caughtInTry)) {
log.error(l.head.pos(),
"except.already.caught", exc);
} else if (!chk.isUnchecked(l.head.pos(), exc) &&
exc.tsym != syms.throwableType.tsym &&
exc.tsym != syms.exceptionType.tsym &&
!chk.intersects(exc, thrownInTry)) {
log.error(l.head.pos(),
"except.never.thrown.in.try", exc);
}
caughtInTry = chk.incl(exc, caughtInTry);
}
caughtInTry = chk.incl(exc, caughtInTry);
}
inits = initsTry.dup();
uninits = uninitsTry.dup();

View File

@ -25,6 +25,8 @@
package com.sun.tools.javac.comp;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCTypeCast;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.code.*;
@ -543,4 +545,56 @@ public class Infer {
args.head, bounds);
}
}
/**
* Compute a synthetic method type corresponding to the requested polymorphic
* method signature. If no explicit return type is supplied, a provisional
* return type is computed (just Object in case of non-transitional 292)
*/
Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env, Type site,
Name name,
MethodSymbol spMethod, // sig. poly. method or null if none
List<Type> argtypes,
List<Type> typeargtypes) {
final Type restype;
if (rs.allowTransitionalJSR292 && typeargtypes.nonEmpty()) {
restype = typeargtypes.head;
} else {
//The return type for a polymorphic signature call is computed from
//the enclosing tree E, as follows: if E is a cast, then use the
//target type of the cast expression as a return type; if E is an
//expression statement, the return type is 'void' - otherwise the
//return type is simply 'Object'.
switch (env.outer.tree.getTag()) {
case JCTree.TYPECAST:
restype = ((JCTypeCast)env.outer.tree).clazz.type; break;
case JCTree.EXEC:
restype = syms.voidType; break;
default:
restype = syms.objectType;
}
}
List<Type> paramtypes = Type.map(argtypes, implicitArgType);
List<Type> exType = spMethod != null ?
spMethod.getThrownTypes() :
List.of(syms.throwableType); // make it throw all exceptions
MethodType mtype = new MethodType(paramtypes,
restype,
exType,
syms.methodClass);
return mtype;
}
//where
Mapping implicitArgType = new Mapping ("implicitArgType") {
public Type apply(Type t) {
t = types.erasure(t);
if (t.tag == BOT)
// nulls type as the marker type Null (which has no instances)
// infer as java.lang.Void for now
t = types.boxedClass(syms.voidType).type;
return t;
}
};
}

View File

@ -29,6 +29,7 @@ import java.util.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.main.RecognizedOptions.PkgInfo;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@ -82,6 +83,7 @@ public class Lower extends TreeTranslator {
private final Name classDollar;
private Types types;
private boolean debugLower;
private PkgInfo pkginfoOpt;
protected Lower(Context context) {
context.put(lowerKey, this);
@ -106,6 +108,7 @@ public class Lower extends TreeTranslator {
types = Types.instance(context);
Options options = Options.instance(context);
debugLower = options.get("debuglower") != null;
pkginfoOpt = PkgInfo.get(options);
}
/** The currently enclosing class.
@ -2161,7 +2164,7 @@ public class Lower extends TreeTranslator {
}
public void visitTopLevel(JCCompilationUnit tree) {
if (tree.packageAnnotations.nonEmpty()) {
if (needPackageInfoClass(tree)) {
Name name = names.package_info;
long flags = Flags.ABSTRACT | Flags.INTERFACE;
if (target.isPackageInfoSynthetic())
@ -2183,6 +2186,23 @@ public class Lower extends TreeTranslator {
translated.append(packageAnnotationsClass);
}
}
// where
private boolean needPackageInfoClass(JCCompilationUnit tree) {
switch (pkginfoOpt) {
case ALWAYS:
return true;
case LEGACY:
return tree.packageAnnotations.nonEmpty();
case NONEMPTY:
for (Attribute.Compound a: tree.packge.attributes_field) {
Attribute.RetentionPolicy p = types.getRetention(a);
if (p != Attribute.RetentionPolicy.SOURCE)
return true;
}
return false;
}
throw new AssertionError();
}
public void visitClassDef(JCClassDecl tree) {
ClassSymbol currentClassPrev = currentClass;
@ -2869,8 +2889,17 @@ public class Lower extends TreeTranslator {
/** Unbox an object to a primitive value. */
JCExpression unbox(JCExpression tree, Type primitive) {
Type unboxedType = types.unboxedType(tree.type);
// note: the "primitive" parameter is not used. There muse be
// a conversion from unboxedType to primitive.
if (unboxedType.tag == NONE) {
unboxedType = primitive;
if (!unboxedType.isPrimitive())
throw new AssertionError(unboxedType);
make_at(tree.pos());
tree = make.TypeCast(types.boxedClass(unboxedType).type, tree);
} else {
// There must be a conversion from unboxedType to primitive.
if (!types.isSubtype(unboxedType, primitive))
throw new AssertionError(tree);
}
make_at(tree.pos());
Symbol valueSym = lookupMethod(tree.pos(),
unboxedType.tsym.name.append(names.Value), // x.intValue()

View File

@ -769,9 +769,17 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
&& types.isSameType(c.type, syms.deprecatedType))
s.flags_field |= Flags.DEPRECATED;
// Internally to java.dyn, a @PolymorphicSignature annotation
// translates to a classfile attribute.
if (!c.type.isErroneous()
&& types.isSameType(c.type, syms.polymorphicSignatureType)) {
// acts like a classfile attribute.
if (!c.type.isErroneous() &&
types.isSameType(c.type, syms.polymorphicSignatureType)) {
if (!target.hasMethodHandles()) {
// Somebody is compiling JDK7 source code to a JDK6 target.
// Make it a strict warning, since it is unlikely but important.
log.strictWarning(env.tree.pos(),
"wrong.target.for.polymorphic.signature.definition",
target.name);
}
// Pull the flag through for better diagnostics, even on a bad target.
s.flags_field |= Flags.POLYMORPHIC_SIGNATURE;
}
if (!annotated.add(a.type.tsym))

View File

@ -69,9 +69,13 @@ public class Resolve {
JCDiagnostic.Factory diags;
public final boolean boxingEnabled; // = source.allowBoxing();
public final boolean varargsEnabled; // = source.allowVarargs();
public final boolean allowPolymorphicSignature;
public final boolean allowMethodHandles;
public final boolean allowInvokeDynamic;
public final boolean allowTransitionalJSR292;
private final boolean debugResolve;
Scope polymorphicSignatureScope;
public static Resolve instance(Context context) {
Resolve instance = context.get(resolveKey);
if (instance == null)
@ -107,7 +111,14 @@ public class Resolve {
varargsEnabled = source.allowVarargs();
Options options = Options.instance(context);
debugResolve = options.get("debugresolve") != null;
allowPolymorphicSignature = source.allowPolymorphicSignature() || options.get("invokedynamic") != null;
allowTransitionalJSR292 = options.get("allowTransitionalJSR292") != null;
Target target = Target.instance(context);
allowMethodHandles = allowTransitionalJSR292 ||
target.hasMethodHandles();
allowInvokeDynamic = (allowTransitionalJSR292 ||
target.hasInvokedynamic()) &&
options.get("invokedynamic") != null;
polymorphicSignatureScope = new Scope(syms.noSymbol);
}
/** error symbols, which are returned when resolution fails
@ -246,7 +257,8 @@ public class Resolve {
/* `sym' is accessible only if not overridden by
* another symbol which is a member of `site'
* (because, if it is overridden, `sym' is not strictly
* speaking a member of `site'.)
* speaking a member of `site'). A polymorphic signature method
* cannot be overridden (e.g. MH.invokeExact(Object[])).
*/
private boolean notOverriddenIn(Type site, Symbol sym) {
if (sym.kind != MTH || sym.isConstructor() || sym.isStatic())
@ -254,6 +266,7 @@ public class Resolve {
else {
Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true);
return (s2 == null || s2 == sym ||
s2.isPolymorphicSignatureGeneric() ||
!types.isSubSignature(types.memberType(site, s2), types.memberType(site, sym)));
}
}
@ -303,7 +316,8 @@ public class Resolve {
boolean useVarargs,
Warner warn)
throws Infer.InferenceException {
assert ((m.flags() & (POLYMORPHIC_SIGNATURE|HYPOTHETICAL)) != POLYMORPHIC_SIGNATURE);
boolean polymorphicSignature = (m.isPolymorphicSignatureGeneric() && allowMethodHandles) ||
isTransitionalDynamicCallSite(site, m);
if (useVarargs && (m.flags() & VARARGS) == 0) return null;
Type mt = types.memberType(site, m);
@ -311,7 +325,10 @@ public class Resolve {
// need to inferred.
List<Type> tvars = env.info.tvars;
if (typeargtypes == null) typeargtypes = List.nil();
if (mt.tag != FORALL && typeargtypes.nonEmpty()) {
if (allowTransitionalJSR292 && polymorphicSignature && typeargtypes.nonEmpty()) {
//transitional 292 call sites might have wrong number of targs
}
else if (mt.tag != FORALL && typeargtypes.nonEmpty()) {
// This is not a polymorphic method, but typeargs are supplied
// which is fine, see JLS3 15.12.2.1
} else if (mt.tag == FORALL && typeargtypes.nonEmpty()) {
@ -339,7 +356,8 @@ public class Resolve {
}
// find out whether we need to go the slow route via infer
boolean instNeeded = tvars.tail != null/*inlined: tvars.nonEmpty()*/;
boolean instNeeded = tvars.tail != null || /*inlined: tvars.nonEmpty()*/
polymorphicSignature;
for (List<Type> l = argtypes;
l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded;
l = l.tail) {
@ -347,8 +365,9 @@ public class Resolve {
}
if (instNeeded)
return
infer.instantiateMethod(env,
return polymorphicSignature ?
infer.instantiatePolymorphicSignatureInstance(env, site, m.name, (MethodSymbol)m, argtypes, typeargtypes) :
infer.instantiateMethod(env,
tvars,
(MethodType)mt,
m,
@ -363,6 +382,14 @@ public class Resolve {
: null;
}
boolean isTransitionalDynamicCallSite(Type site, Symbol sym) {
return allowTransitionalJSR292 && // old logic that doesn't use annotations
!sym.isPolymorphicSignatureInstance() &&
((allowMethodHandles && site == syms.methodHandleType && // invokeExact, invokeGeneric, invoke
(sym.name == names.invoke && sym.isPolymorphicSignatureGeneric())) ||
(site == syms.invokeDynamicType && allowInvokeDynamic)); // InvokeDynamic.XYZ
}
/** Same but returns null instead throwing a NoInstanceException
*/
Type instantiate(Env<AttrContext> env,
@ -580,14 +607,6 @@ public class Resolve {
if (sym.kind == ERR) return bestSoFar;
if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar;
assert sym.kind < AMBIGUOUS;
if ((sym.flags() & POLYMORPHIC_SIGNATURE) != 0 && allowPolymorphicSignature) {
assert(site.tag == CLASS);
// Never match a MethodHandle.invoke directly.
if (useVarargs | allowBoxing | operator)
return bestSoFar;
// Supply an exactly-typed implicit method instead.
sym = findPolymorphicSignatureInstance(env, sym.owner.type, sym.name, (MethodSymbol) sym, argtypes, typeargtypes);
}
try {
if (rawInstantiate(env, site, sym, argtypes, typeargtypes,
allowBoxing, useVarargs, Warner.noWarnings) == null) {
@ -759,13 +778,6 @@ public class Resolve {
boolean useVarargs,
boolean operator) {
Symbol bestSoFar = methodNotFound;
if ((site.tsym.flags() & POLYMORPHIC_SIGNATURE) != 0 &&
allowPolymorphicSignature &&
site.tag == CLASS &&
!(useVarargs | allowBoxing | operator)) {
// supply an exactly-typed implicit method in java.dyn.InvokeDynamic
bestSoFar = findPolymorphicSignatureInstance(env, site, name, null, argtypes, typeargtypes);
}
return findMethod(env,
site,
name,
@ -907,90 +919,6 @@ public class Resolve {
return bestSoFar;
}
/** Find or create an implicit method of exactly the given type (after erasure).
* Searches in a side table, not the main scope of the site.
* This emulates the lookup process required by JSR 292 in JVM.
* @param env The current environment.
* @param site The original type from where the selection
* takes place.
* @param name The method's name.
* @param argtypes The method's value arguments.
* @param typeargtypes The method's type arguments
*/
Symbol findPolymorphicSignatureInstance(Env<AttrContext> env,
Type site,
Name name,
MethodSymbol spMethod, // sig. poly. method or null if none
List<Type> argtypes,
List<Type> typeargtypes) {
assert allowPolymorphicSignature;
//assert site == syms.invokeDynamicType || site == syms.methodHandleType : site;
ClassSymbol c = (ClassSymbol) site.tsym;
Scope implicit = c.members().next;
if (implicit == null) {
c.members().next = implicit = new Scope(c);
}
Type restype;
if (typeargtypes.isEmpty()) {
restype = syms.objectType;
} else {
restype = typeargtypes.head;
if (!typeargtypes.tail.isEmpty())
return methodNotFound;
}
List<Type> paramtypes = Type.map(argtypes, implicitArgType);
long flags;
List<Type> exType;
if (spMethod != null) {
exType = spMethod.getThrownTypes();
flags = spMethod.flags() & AccessFlags;
} else {
// make it throw all exceptions
//assert(site == syms.invokeDynamicType);
exType = List.of(syms.throwableType);
flags = PUBLIC | STATIC;
}
MethodType mtype = new MethodType(paramtypes,
restype,
exType,
syms.methodClass);
flags |= ABSTRACT | HYPOTHETICAL | POLYMORPHIC_SIGNATURE;
Symbol m = null;
for (Scope.Entry e = implicit.lookup(name);
e.scope != null;
e = e.next()) {
Symbol sym = e.sym;
assert sym.kind == MTH;
if (types.isSameType(mtype, sym.type)
&& (sym.flags() & STATIC) == (flags & STATIC)) {
m = sym;
break;
}
}
if (m == null) {
// create the desired method
m = new MethodSymbol(flags, name, mtype, c);
implicit.enter(m);
}
assert argumentsAcceptable(argtypes, types.memberType(site, m).getParameterTypes(),
false, false, Warner.noWarnings);
assert null != instantiate(env, site, m, argtypes, typeargtypes, false, false, Warner.noWarnings);
return m;
}
//where
Mapping implicitArgType = new Mapping ("implicitArgType") {
public Type apply(Type t) { return implicitArgType(t); }
};
Type implicitArgType(Type argType) {
argType = types.erasure(argType);
if (argType.tag == BOT)
// nulls type as the marker type Null (which has no instances)
// TO DO: figure out how to access java.lang.Null safely, else throw nice error
//argType = types.boxedClass(syms.botType).type;
argType = types.boxedClass(syms.voidType).type; // REMOVE
return argType;
}
/** Load toplevel or member class with given fully qualified name and
* verify that it is accessible.
* @param env The current environment.
@ -1369,16 +1297,77 @@ public class Resolve {
methodResolutionCache.put(steps.head, sym);
steps = steps.tail;
}
if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
MethodResolutionPhase errPhase =
firstErroneousResolutionPhase();
sym = access(methodResolutionCache.get(errPhase),
pos, site, name, true, argtypes, typeargtypes);
env.info.varArgs = errPhase.isVarargsRequired;
if (sym.kind >= AMBIGUOUS) {
if (site.tsym.isPolymorphicSignatureGeneric() ||
isTransitionalDynamicCallSite(site, sym)) {
//polymorphic receiver - synthesize new method symbol
env.info.varArgs = false;
sym = findPolymorphicSignatureInstance(env,
site, name, null, argtypes, typeargtypes);
}
else {
//if nothing is found return the 'first' error
MethodResolutionPhase errPhase =
firstErroneousResolutionPhase();
sym = access(methodResolutionCache.get(errPhase),
pos, site, name, true, argtypes, typeargtypes);
env.info.varArgs = errPhase.isVarargsRequired;
}
} else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) {
//non-instantiated polymorphic signature - synthesize new method symbol
env.info.varArgs = false;
sym = findPolymorphicSignatureInstance(env,
site, name, (MethodSymbol)sym, argtypes, typeargtypes);
}
return sym;
}
/** Find or create an implicit method of exactly the given type (after erasure).
* Searches in a side table, not the main scope of the site.
* This emulates the lookup process required by JSR 292 in JVM.
* @param env Attribution environment
* @param site The original type from where the selection takes place.
* @param name The method's name.
* @param spMethod A template for the implicit method, or null.
* @param argtypes The required argument types.
* @param typeargtypes The required type arguments.
*/
Symbol findPolymorphicSignatureInstance(Env<AttrContext> env, Type site,
Name name,
MethodSymbol spMethod, // sig. poly. method or null if none
List<Type> argtypes,
List<Type> typeargtypes) {
if (typeargtypes.nonEmpty() && (site.tsym.isPolymorphicSignatureGeneric() ||
(spMethod != null && spMethod.isPolymorphicSignatureGeneric()))) {
log.warning(env.tree.pos(), "type.parameter.on.polymorphic.signature");
}
Type mtype = infer.instantiatePolymorphicSignatureInstance(env,
site, name, spMethod, argtypes, typeargtypes);
long flags = ABSTRACT | HYPOTHETICAL | POLYMORPHIC_SIGNATURE |
(spMethod != null ?
spMethod.flags() & Flags.AccessFlags :
Flags.PUBLIC | Flags.STATIC);
Symbol m = null;
for (Scope.Entry e = polymorphicSignatureScope.lookup(name);
e.scope != null;
e = e.next()) {
Symbol sym = e.sym;
if (types.isSameType(mtype, sym.type) &&
(sym.flags() & Flags.STATIC) == (flags & Flags.STATIC) &&
types.isSameType(sym.owner.type, site)) {
m = sym;
break;
}
}
if (m == null) {
// create the desired method
m = new MethodSymbol(flags, name, mtype, site.tsym);
polymorphicSignatureScope.enter(m);
}
return m;
}
/** Resolve a qualified method identifier, throw a fatal error if not
* found.
* @param pos The position to use for error reporting.

View File

@ -283,12 +283,13 @@ public class TransTypes extends TreeTranslator {
ListBuffer<JCTree> bridges) {
if (sym.kind == MTH &&
sym.name != names.init &&
(sym.flags() & (PRIVATE | SYNTHETIC | STATIC)) == 0 &&
(sym.flags() & (PRIVATE | STATIC)) == 0 &&
(sym.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC &&
sym.isMemberOf(origin, types))
{
MethodSymbol meth = (MethodSymbol)sym;
MethodSymbol bridge = meth.binaryImplementation(origin, types);
MethodSymbol impl = meth.implementation(origin, types, true);
MethodSymbol impl = meth.implementation(origin, types, true, overrideBridgeFilter);
if (bridge == null ||
bridge == meth ||
(impl != null && !bridge.owner.isSubClass(impl.owner, types))) {
@ -304,7 +305,7 @@ public class TransTypes extends TreeTranslator {
// reflection design error.
addBridge(pos, meth, impl, origin, false, bridges);
}
} else if ((bridge.flags() & SYNTHETIC) != 0) {
} else if ((bridge.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) == SYNTHETIC) {
MethodSymbol other = overridden.get(bridge);
if (other != null && other != meth) {
if (impl == null || !impl.overrides(other, origin, types, true)) {
@ -327,6 +328,11 @@ public class TransTypes extends TreeTranslator {
}
}
// where
Filter<Symbol> overrideBridgeFilter = new Filter<Symbol>() {
public boolean accepts(Symbol s) {
return (s.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC;
}
};
/**
* @param method The symbol for which a bridge might have to be added
* @param impl The implementation of method
@ -754,6 +760,90 @@ public class TransTypes extends TreeTranslator {
return types.erasure(t);
}
private boolean boundsRestricted(ClassSymbol c) {
Type st = types.supertype(c.type);
if (st.isParameterized()) {
List<Type> actuals = st.allparams();
List<Type> formals = st.tsym.type.allparams();
while (!actuals.isEmpty() && !formals.isEmpty()) {
Type actual = actuals.head;
Type formal = formals.head;
if (!types.isSameType(types.erasure(actual),
types.erasure(formal)))
return true;
actuals = actuals.tail;
formals = formals.tail;
}
}
return false;
}
private List<JCTree> addOverrideBridgesIfNeeded(DiagnosticPosition pos,
final ClassSymbol c) {
ListBuffer<JCTree> buf = ListBuffer.lb();
if (c.isInterface() || !boundsRestricted(c))
return buf.toList();
Type t = types.supertype(c.type);
Scope s = t.tsym.members();
if (s.elems != null) {
for (Symbol sym : s.getElements(new NeedsOverridBridgeFilter(c))) {
MethodSymbol m = (MethodSymbol)sym;
MethodSymbol member = (MethodSymbol)m.asMemberOf(c.type, types);
MethodSymbol impl = m.implementation(c, types, false);
if ((impl == null || impl.owner != c) &&
!types.isSameType(member.erasure(types), m.erasure(types))) {
addOverrideBridges(pos, m, member, c, buf);
}
}
}
return buf.toList();
}
// where
class NeedsOverridBridgeFilter implements Filter<Symbol> {
ClassSymbol c;
NeedsOverridBridgeFilter(ClassSymbol c) {
this.c = c;
}
public boolean accepts(Symbol s) {
return s.kind == MTH &&
!s.isConstructor() &&
s.isInheritedIn(c, types) &&
(s.flags() & FINAL) == 0 &&
(s.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC;
}
}
private void addOverrideBridges(DiagnosticPosition pos,
MethodSymbol impl,
MethodSymbol member,
ClassSymbol c,
ListBuffer<JCTree> bridges) {
Type implErasure = impl.erasure(types);
long flags = (impl.flags() & AccessFlags) | SYNTHETIC | BRIDGE | OVERRIDE_BRIDGE;
member = new MethodSymbol(flags, member.name, member.type, c);
JCMethodDecl md = make.MethodDef(member, null);
JCExpression receiver = make.Super(types.supertype(c.type).tsym.erasure(types), c);
Type calltype = erasure(impl.type.getReturnType());
JCExpression call =
make.Apply(null,
make.Select(receiver, impl).setType(calltype),
translateArgs(make.Idents(md.params),
implErasure.getParameterTypes(), null))
.setType(calltype);
JCStatement stat = (member.getReturnType().tag == VOID)
? make.Exec(call)
: make.Return(coerce(call, member.erasure(types).getReturnType()));
md.body = make.Block(0, List.of(stat));
c.members().enter(member);
bridges.append(md);
}
/**************************************************************************
* main method
*************************************************************************/
@ -786,6 +876,7 @@ public class TransTypes extends TreeTranslator {
make.at(tree.pos);
if (addBridges) {
ListBuffer<JCTree> bridges = new ListBuffer<JCTree>();
bridges.appendList(addOverrideBridgesIfNeeded(tree, c));
if ((tree.sym.flags() & INTERFACE) == 0)
addBridges(tree.pos(), tree.sym, bridges);
tree.defs = bridges.toList().prependList(tree.defs);

View File

@ -1098,12 +1098,6 @@ public class ClassReader implements Completer {
}
},
new AttributeReader(names.PolymorphicSignature, V45_3/*S.B.V51*/, CLASS_OR_MEMBER_ATTRIBUTE) {
void read(Symbol sym, int attrLen) {
sym.flags_field |= POLYMORPHIC_SIGNATURE;
}
},
// The following attributes for a Code attribute are not currently handled
// StackMapTable
@ -1289,6 +1283,9 @@ public class ClassReader implements Completer {
sym.flags_field |= PROPRIETARY;
else
proxies.append(proxy);
if (majorVersion >= V51.major && proxy.type.tsym == syms.polymorphicSignatureType.tsym) {
sym.flags_field |= POLYMORPHIC_SIGNATURE;
}
}
annotate.later(new AnnotationCompleter(sym, proxies.toList()));
}

View File

@ -34,6 +34,7 @@ import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.file.BaseFileObject;
@ -651,13 +652,6 @@ public class ClassWriter extends ClassFile {
endAttr(alenIdx);
acount++;
}
if ((flags & POLYMORPHIC_SIGNATURE) != 0) {
if (target.majorVersion < 51)
throw new AssertionError("PolymorphicSignature attributes in java/dyn must be written with -target 7 (required major version is 51, current is"+target.majorVersion+")");
int alenIdx = writeAttr(names.PolymorphicSignature);
endAttr(alenIdx);
acount++;
}
return acount;
}
@ -692,7 +686,7 @@ public class ClassWriter extends ClassFile {
boolean hasInvisible = false;
if (m.params != null) for (VarSymbol s : m.params) {
for (Attribute.Compound a : s.getAnnotationMirrors()) {
switch (getRetention(a.type.tsym)) {
switch (types.getRetention(a)) {
case SOURCE: break;
case CLASS: hasInvisible = true; break;
case RUNTIME: hasVisible = true; break;
@ -708,7 +702,7 @@ public class ClassWriter extends ClassFile {
for (VarSymbol s : m.params) {
ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
for (Attribute.Compound a : s.getAnnotationMirrors())
if (getRetention(a.type.tsym) == RetentionPolicy.RUNTIME)
if (types.getRetention(a) == RetentionPolicy.RUNTIME)
buf.append(a);
databuf.appendChar(buf.length());
for (Attribute.Compound a : buf)
@ -723,7 +717,7 @@ public class ClassWriter extends ClassFile {
for (VarSymbol s : m.params) {
ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
for (Attribute.Compound a : s.getAnnotationMirrors())
if (getRetention(a.type.tsym) == RetentionPolicy.CLASS)
if (types.getRetention(a) == RetentionPolicy.CLASS)
buf.append(a);
databuf.appendChar(buf.length());
for (Attribute.Compound a : buf)
@ -747,7 +741,7 @@ public class ClassWriter extends ClassFile {
ListBuffer<Attribute.Compound> visibles = new ListBuffer<Attribute.Compound>();
ListBuffer<Attribute.Compound> invisibles = new ListBuffer<Attribute.Compound>();
for (Attribute.Compound a : attrs) {
switch (getRetention(a.type.tsym)) {
switch (types.getRetention(a)) {
case SOURCE: break;
case CLASS: invisibles.append(a); break;
case RUNTIME: visibles.append(a); break;
@ -785,7 +779,7 @@ public class ClassWriter extends ClassFile {
if (tc.position.type == TargetType.UNKNOWN
|| !tc.position.emitToClassfile())
continue;
switch (getRetention(tc.type.tsym)) {
switch (types.getRetention(tc)) {
case SOURCE: break;
case CLASS: invisibles.append(tc); break;
case RUNTIME: visibles.append(tc); break;
@ -815,29 +809,6 @@ public class ClassWriter extends ClassFile {
return attrCount;
}
/** A mirror of java.lang.annotation.RetentionPolicy. */
enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
RetentionPolicy getRetention(TypeSymbol annotationType) {
RetentionPolicy vis = RetentionPolicy.CLASS; // the default
Attribute.Compound c = annotationType.attribute(syms.retentionType.tsym);
if (c != null) {
Attribute value = c.member(names.value);
if (value != null && value instanceof Attribute.Enum) {
Name levelName = ((Attribute.Enum)value).value.name;
if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE;
else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS;
else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME;
else ;// /* fail soft */ throw new AssertionError(levelName);
}
}
return vis;
}
/** A visitor to write an attribute including its leading
* single-character marker.
*/

View File

@ -259,6 +259,14 @@ public enum Target {
return compareTo(JDK1_7) >= 0;
}
/** Does the VM support polymorphic method handle invocation?
* Affects the linkage information output to the classfile.
* An alias for {@code hasInvokedynamic}, since all the JSR 292 features appear together.
*/
public boolean hasMethodHandles() {
return hasInvokedynamic();
}
/** Although we may not have support for class literals, should we
* avoid initializing the class that the literal refers to?
* See 4468823

View File

@ -59,6 +59,7 @@ import com.sun.tools.javac.processing.*;
import javax.annotation.processing.Processor;
import static javax.tools.StandardLocation.CLASS_OUTPUT;
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
import static com.sun.tools.javac.util.ListBuffer.lb;
// TEMP, until we have a more efficient way to save doc comment info
@ -579,10 +580,8 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename);
taskListener.started(e);
}
int initialErrorCount = log.nerrors;
Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo);
tree = parser.parseCompilationUnit();
log.unrecoverableError |= (log.nerrors > initialErrorCount);
if (verbose) {
printVerbose("parsing.done", Long.toString(elapsed(msec)));
}
@ -608,7 +607,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
* @param filename The name of the file to be parsed.
*/
@Deprecated
public JCTree.JCCompilationUnit parse(String filename) throws IOException {
public JCTree.JCCompilationUnit parse(String filename) {
JavacFileManager fm = (JavacFileManager)fileManager;
return parse(fm.getJavaFileObjectsFromStrings(List.of(filename)).iterator().next());
}
@ -778,7 +777,6 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
public void compile(List<JavaFileObject> sourceFileObjects,
List<String> classnames,
Iterable<? extends Processor> processors)
throws IOException // TODO: temp, from JavacProcessingEnvironment
{
if (processors != null && processors.iterator().hasNext())
explicitAnnotationProcessingRequested = true;
@ -868,14 +866,19 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
/**
* Parses a list of files.
*/
public List<JCCompilationUnit> parseFiles(Iterable<JavaFileObject> fileObjects) throws IOException {
public List<JCCompilationUnit> parseFiles(Iterable<JavaFileObject> fileObjects) {
if (shouldStop(CompileState.PARSE))
return List.nil();
//parse all files
ListBuffer<JCCompilationUnit> trees = lb();
for (JavaFileObject fileObject : fileObjects)
trees.append(parse(fileObject));
Set<JavaFileObject> filesSoFar = new HashSet<JavaFileObject>();
for (JavaFileObject fileObject : fileObjects) {
if (!filesSoFar.contains(fileObject)) {
filesSoFar.add(fileObject);
trees.append(parse(fileObject));
}
}
return trees.toList();
}
@ -916,6 +919,15 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
}
rootClasses = cdefs.toList();
}
// Ensure the input files have been recorded. Although this is normally
// done by readSource, it may not have been done if the trees were read
// in a prior round of annotation processing, and the trees have been
// cleaned and are being reused.
for (JCCompilationUnit unit : roots) {
inputFiles.add(unit.sourcefile);
}
return roots;
}
@ -941,8 +953,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
* @param processors user provided annotation processors to bypass
* discovery, {@code null} means that no processors were provided
*/
public void initProcessAnnotations(Iterable<? extends Processor> processors)
throws IOException {
public void initProcessAnnotations(Iterable<? extends Processor> processors) {
// Process annotations if processing is not disabled and there
// is at least one Processor available.
Options options = Options.instance(context);
@ -960,8 +971,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
keepComments = true;
if (taskListener != null)
taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
log.deferDiagnostics = true;
} else { // free resources
procEnvImpl.close();
}
@ -969,8 +979,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
}
// TODO: called by JavacTaskImpl
public JavaCompiler processAnnotations(List<JCCompilationUnit> roots)
throws IOException {
public JavaCompiler processAnnotations(List<JCCompilationUnit> roots) {
return processAnnotations(roots, List.<String>nil());
}
@ -979,16 +988,23 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
* @param roots a list of compilation units
* @return an instance of the compiler in which to complete the compilation
*/
// Implementation note: when this method is called, log.deferredDiagnostics
// will have been set true by initProcessAnnotations, meaning that any diagnostics
// that are reported will go into the log.deferredDiagnostics queue.
// By the time this method exits, log.deferDiagnostics must be set back to false,
// and all deferredDiagnostics must have been handled: i.e. either reported
// or determined to be transient, and therefore suppressed.
public JavaCompiler processAnnotations(List<JCCompilationUnit> roots,
List<String> classnames)
throws IOException { // TODO: see TEMP note in JavacProcessingEnvironment
List<String> classnames) {
if (shouldStop(CompileState.PROCESS)) {
// Errors were encountered.
// If log.unrecoverableError is set, the errors were parse errors
// Unless all the errors are resolve errors, the errors were parse errors
// or other errors during enter which cannot be fixed by running
// any annotation processors.
if (log.unrecoverableError)
if (unrecoverableError()) {
log.reportDeferredDiagnostics();
return this;
}
}
// ASSERT: processAnnotations and procEnvImpl should have been set up by
@ -1010,6 +1026,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
log.error("proc.no.explicit.annotation.processing.requested",
classnames);
}
log.reportDeferredDiagnostics();
return this; // continue regular compilation
}
@ -1022,6 +1039,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
if (!explicitAnnotationProcessingRequested()) {
log.error("proc.no.explicit.annotation.processing.requested",
classnames);
log.reportDeferredDiagnostics();
return this; // TODO: Will this halt compilation?
} else {
boolean errors = false;
@ -1036,7 +1054,6 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
if (sym.kind == Kinds.PCK)
sym.complete();
if (sym.exists()) {
Name name = names.fromString(nameStr);
if (sym.kind == Kinds.PCK)
pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
else
@ -1052,25 +1069,38 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
continue;
}
}
if (errors)
if (errors) {
log.reportDeferredDiagnostics();
return this;
}
}
}
try {
JavaCompiler c = procEnvImpl.doProcessing(context, roots, classSymbols, pckSymbols);
if (c != this)
annotationProcessingOccurred = c.annotationProcessingOccurred = true;
// doProcessing will have handled deferred diagnostics
assert c.log.deferDiagnostics == false;
assert c.log.deferredDiagnostics.size() == 0;
return c;
} finally {
procEnvImpl.close();
}
} catch (CompletionFailure ex) {
log.error("cant.access", ex.sym, ex.getDetailValue());
log.reportDeferredDiagnostics();
return this;
}
}
private boolean unrecoverableError() {
for (JCDiagnostic d: log.deferredDiagnostics) {
if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RESOLVE_ERROR))
return true;
}
return false;
}
boolean explicitAnnotationProcessingRequested() {
Options options = Options.instance(context);
return
@ -1119,6 +1149,11 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
env.toplevel.sourcefile);
try {
attr.attribClass(env.tree.pos(), env.enclClass.sym);
if (errorCount() > 0 && !shouldStop(CompileState.ATTR)) {
//if in fail-over mode, ensure that AST expression nodes
//are correctly initialized (e.g. they have a type/symbol)
attr.postAttr(env);
}
compileStates.put(env, CompileState.ATTR);
}
finally {

View File

@ -282,6 +282,13 @@ public class Main {
}
}
// phase this out with JSR 292 PFD
if ("no".equals(options.get("allowTransitionalJSR292"))) {
options.put("allowTransitionalJSR292", null);
} else if (target.hasInvokedynamic() && options.get("allowTransitionalJSR292") == null) {
options.put("allowTransitionalJSR292", "allowTransitionalJSR292");
}
// handle this here so it works even if no other options given
String showClass = options.get("showClass");
if (showClass != null) {
@ -467,10 +474,13 @@ public class Main {
ex.printStackTrace(out);
}
/** Print a message reporting an fatal error.
/** Print a message reporting a fatal error.
*/
void feMessage(Throwable ex) {
Log.printLines(out, ex.getMessage());
if (ex.getCause() != null && options.get("dev") != null) {
ex.getCause().printStackTrace(out);
}
}
/** Print a message reporting an input/output error.

View File

@ -80,6 +80,7 @@ public enum OptionName {
XMAXERRS("-Xmaxerrs"),
XMAXWARNS("-Xmaxwarns"),
XSTDOUT("-Xstdout"),
XPKGINFO("-Xpkginfo:"),
XPRINT("-Xprint"),
XPRINTROUNDS("-XprintRounds"),
XPRINTPROCESSORINFO("-XprintProcessorInfo"),

View File

@ -160,6 +160,7 @@ public class RecognizedOptions {
XMAXERRS,
XMAXWARNS,
XSTDOUT,
XPKGINFO,
XPRINT,
XPRINTROUNDS,
XPRINTPROCESSORINFO,
@ -217,6 +218,7 @@ public class RecognizedOptions {
XMAXERRS,
XMAXWARNS,
// XSTDOUT,
XPKGINFO,
XPRINT,
XPRINTROUNDS,
XPRINTPROCESSORINFO,
@ -532,6 +534,9 @@ public class RecognizedOptions {
new XOption(XPREFER, "opt.prefer",
Option.ChoiceKind.ONEOF, "source", "newer"),
new XOption(XPKGINFO, "opt.pkginfo",
Option.ChoiceKind.ONEOF, "always", "legacy", "nonempty"),
/* -O is a no-op, accepted for backward compatibility. */
new HiddenOption(O),
@ -598,6 +603,16 @@ public class RecognizedOptions {
};
}
public enum PkgInfo {
ALWAYS, LEGACY, NONEMPTY;
public static PkgInfo get(Options options) {
String v = options.get(XPKGINFO);
return (v == null
? PkgInfo.LEGACY
: PkgInfo.valueOf(v.toUpperCase()));
}
}
private static Map<String,Boolean> getXLintChoices() {
Map<String,Boolean> choices = new LinkedHashMap<String,Boolean>();
choices.put("all", false);

View File

@ -103,7 +103,7 @@ public class JavacTypes implements javax.lang.model.util.Types {
public boolean contains(TypeMirror t1, TypeMirror t2) {
validateTypeNotIn(t1, EXEC_OR_PKG);
validateTypeNotIn(t2, EXEC_OR_PKG);
return ((Type) t1).contains((Type) t2);
return types.containsType((Type) t1, (Type) t2);
}
public boolean isSubsignature(ExecutableType m1, ExecutableType m2) {

View File

@ -2781,7 +2781,7 @@ public class JavacParser implements Parser {
List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
if (S.token() == SEMI) {
S.nextToken();
return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
return List.<JCTree>nil();
} else {
String dc = S.docComment();
int pos = S.pos();

View File

@ -108,6 +108,10 @@ public class Scanner implements Lexer {
*/
private boolean allowUnderscoresInLiterals;
/** Allow exotic identifiers.
*/
private boolean allowExoticIdentifiers;
/** The source language setting.
*/
private Source source;
@ -181,6 +185,7 @@ public class Scanner implements Lexer {
allowBinaryLiterals = source.allowBinaryLiterals();
allowHexFloats = source.allowHexFloats();
allowUnderscoresInLiterals = source.allowBinaryLiterals();
allowExoticIdentifiers = source.allowExoticIdentifiers(); // for invokedynamic
}
private static final boolean hexFloatsWork = hexFloatsWork();
@ -1010,6 +1015,10 @@ public class Scanner implements Lexer {
case '#':
scanChar();
if (ch == '\"') {
if (!allowExoticIdentifiers) {
lexError("unsupported.exotic.id", source.name);
allowExoticIdentifiers = true;
}
scanChar();
if (ch == '\"')
lexError(pos, "empty.bytecode.ident");

View File

@ -34,6 +34,7 @@ import javax.lang.model.element.Element;
import java.util.*;
import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FilterOutputStream;
@ -450,10 +451,15 @@ public class JavacFiler implements Filer, Closeable {
// TODO: Only support reading resources in selected output
// locations? Only allow reading of non-source, non-class
// files from the supported input locations?
FileObject fileObject = fileManager.getFileForOutput(location,
pkg.toString(),
relativeName.toString(),
null);
FileObject fileObject = fileManager.getFileForInput(location,
pkg.toString(),
relativeName.toString());
if (fileObject == null) {
String name = (pkg.length() == 0)
? relativeName.toString() : (pkg + "/" + relativeName);
throw new FileNotFoundException(name);
}
// If the path was already opened for writing, throw an exception.
checkFileReopening(fileObject, false);
return new FilerInputFileObject(fileObject);

View File

@ -67,6 +67,8 @@ import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.Abort;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Convert;
import com.sun.tools.javac.util.FatalError;
import com.sun.tools.javac.util.JCDiagnostic;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.JavacMessages;
@ -75,6 +77,7 @@ import com.sun.tools.javac.util.Names;
import com.sun.tools.javac.util.Options;
import static javax.tools.StandardLocation.*;
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
/**
* Objects of this class hold and manage the state needed to support
@ -95,6 +98,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
private final boolean procOnly;
private final boolean fatalErrors;
private final boolean werror;
private final boolean showResolveErrors;
private boolean foundTypeProcessors;
private final JavacFiler filer;
@ -131,6 +135,10 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
*/
Log log;
/** Diagnostic factory.
*/
JCDiagnostic.Factory diags;
/**
* Source level of the compile.
*/
@ -146,10 +154,11 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
private Context context;
public JavacProcessingEnvironment(Context context, Iterable<? extends Processor> processors) {
options = Options.instance(context);
this.context = context;
log = Log.instance(context);
source = Source.instance(context);
diags = JCDiagnostic.Factory.instance(context);
options = Options.instance(context);
printProcessorInfo = options.get("-XprintProcessorInfo") != null;
printRounds = options.get("-XprintRounds") != null;
verbose = options.get("-verbose") != null;
@ -157,6 +166,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
procOnly = options.get("-proc:only") != null ||
options.get("-Xprint") != null;
fatalErrors = options.get("fatalEnterError") != null;
showResolveErrors = options.get("showResolveErrors") != null;
werror = options.get("-Werror") != null;
platformAnnotations = initPlatformAnnotations();
foundTypeProcessors = false;
@ -818,6 +828,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
compiler = JavaCompiler.instance(context);
log = Log.instance(context);
log.deferDiagnostics = true;
// the following is for the benefit of JavacProcessingEnvironment.getContext()
JavacProcessingEnvironment.this.context = context;
@ -848,8 +859,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
/** Create a new round. */
private Round(Round prev,
Set<JavaFileObject> newSourceFiles, Map<String,JavaFileObject> newClassFiles)
throws IOException {
Set<JavaFileObject> newSourceFiles, Map<String,JavaFileObject> newClassFiles) {
this(prev.nextContext(), prev.number+1, prev.compiler.log.nwarnings);
this.genClassFiles = prev.genClassFiles;
@ -882,8 +892,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
/** Create the next round to be used. */
Round next(Set<JavaFileObject> newSourceFiles, Map<String, JavaFileObject> newClassFiles)
throws IOException {
Round next(Set<JavaFileObject> newSourceFiles, Map<String, JavaFileObject> newClassFiles) {
try {
return new Round(this, newSourceFiles, newClassFiles);
} finally {
@ -919,10 +928,24 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
/** Return whether or not an unrecoverable error has occurred. */
boolean unrecoverableError() {
return log.unrecoverableError
|| messager.errorRaised()
|| (werror && log.nwarnings > 0)
|| (fatalErrors && log.nerrors > 0);
if (messager.errorRaised())
return true;
for (JCDiagnostic d: log.deferredDiagnostics) {
switch (d.getKind()) {
case WARNING:
if (werror)
return true;
break;
case ERROR:
if (fatalErrors || !d.isFlagSet(RESOLVE_ERROR))
return true;
break;
}
}
return false;
}
/** Find the set of annotations present in the set of top level
@ -938,7 +961,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
/** Enter a set of generated class files. */
List<ClassSymbol> enterClassFiles(Map<String, JavaFileObject> classFiles) {
private List<ClassSymbol> enterClassFiles(Map<String, JavaFileObject> classFiles) {
ClassReader reader = ClassReader.instance(context);
Names names = Names.instance(context);
List<ClassSymbol> list = List.nil();
@ -965,7 +988,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
/** Enter a set of syntax trees. */
void enterTrees(List<JCCompilationUnit> roots) {
private void enterTrees(List<JCCompilationUnit> roots) {
compiler.enterTrees(roots);
}
@ -995,6 +1018,15 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
}
void showDiagnostics(boolean showAll) {
Set<JCDiagnostic.Kind> kinds = EnumSet.allOf(JCDiagnostic.Kind.class);
if (!showAll) {
// suppress errors, which are all presumed to be transient resolve errors
kinds.remove(JCDiagnostic.Kind.ERROR);
}
log.reportDeferredDiagnostics(kinds);
}
/** Update the processing state for the current context. */
private void updateProcessingState() {
filer.newRound(context);
@ -1083,8 +1115,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
public JavaCompiler doProcessing(Context context,
List<JCCompilationUnit> roots,
List<ClassSymbol> classSymbols,
Iterable<? extends PackageSymbol> pckSymbols)
throws IOException {
Iterable<? extends PackageSymbol> pckSymbols) {
TaskListener taskListener = context.get(TaskListener.class);
log = Log.instance(context);
@ -1107,6 +1138,8 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
errorStatus = round.unrecoverableError();
moreToDo = moreToDo();
round.showDiagnostics(errorStatus || showResolveErrors);
// Set up next round.
// Copy mutable collections returned from filer.
round = round.next(
@ -1121,6 +1154,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
// run last round
round.run(true, errorStatus);
round.showDiagnostics(true);
filer.warnIfUnclosedFiles();
warnIfUnmatchedOptions();
@ -1184,13 +1218,19 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
/**
* Free resources related to annotation processing.
*/
public void close() throws IOException {
public void close() {
filer.close();
if (discoveredProcs != null) // Make calling close idempotent
discoveredProcs.close();
discoveredProcs = null;
if (processorClassLoader != null && processorClassLoader instanceof Closeable)
((Closeable) processorClassLoader).close();
if (processorClassLoader != null && processorClassLoader instanceof Closeable) {
try {
((Closeable) processorClassLoader).close();
} catch (IOException e) {
JCDiagnostic msg = diags.fragment("fatal.err.cant.close.loader");
throw new FatalError(msg, e);
}
}
}
private List<ClassSymbol> getTopLevelClasses(List<? extends JCCompilationUnit> units) {

View File

@ -128,6 +128,11 @@ compiler.err.call.to.super.not.allowed.in.enum.ctor=\
compiler.err.no.superclass=\
{0} has no superclass
compiler.warn.type.parameter.on.polymorphic.signature=\
change obsolete notation for MethodHandle invocations from x.<T>invoke(y) to (T)x.invoke(y)
compiler.warn.wrong.target.for.polymorphic.signature.definition=\
MethodHandle API building requires -target 7 runtimes or better; current is -target {0}
compiler.err.concrete.inheritance.conflict=\
methods {0} from {1} and {2} from {3} are inherited with the same signature
@ -550,6 +555,8 @@ compiler.misc.fatal.err.cant.locate.field=\
Fatal Error: Unable to find field {0}
compiler.misc.fatal.err.cant.locate.ctor=\
Fatal Error: Unable to find constructor for {0}
compiler.misc.fatal.err.cant.close.loader=\
Fatal Error: Cannot close class loader for annotation processors
#####
@ -1240,6 +1247,10 @@ compiler.err.unsupported.underscore.lit=\
underscores in literals are not supported in -source {0}\n\
(use -source 7 or higher to enable underscores in literals)
compiler.err.unsupported.exotic.id=\
exotic identifiers #"___" are not supported in -source {0}\n\
(use -source 7 or higher to enable exotic identifiers)
compiler.err.automatic.resource.management.not.supported.in.source=\
automatic resource management is not supported in -source {0}\n\
(use -source 7 or higher to enable automatic resource management)

View File

@ -74,7 +74,9 @@ javac.opt.Werror=\
javac.opt.A=\
Options to pass to annotation processors
javac.opt.implicit=\
Specify whether or not to generate class files for implicitly referenced files
Specify whether or not to generate class files for implicitly referenced files
javac.opt.pkginfo=\
Specify handling of package-info files
javac.opt.arg.class=\
<class>
javac.opt.arg.class.list=\
@ -189,7 +191,7 @@ javac.msg.usage=\
javac.msg.usage.nonstandard.footer=\
These options are non-standard and subject to change without notice.
javac.msg.bug=\
An exception has occurred in the compiler ({0}). \
Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) \

View File

@ -565,6 +565,7 @@ sun.tools.jar = tiger legacy
sun.tools.jar.resources = tiger legacy
sun.util = tiger legacy
sun.util.calendar = tiger legacy
sun.util.locale = tiger legacy
sun.util.logging.resources = tiger legacy
sunw.io = tiger legacy
sunw.util = tiger legacy

View File

@ -340,6 +340,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public abstract int getTag();
/** Convert a tree to a pretty-printed string. */
@Override
public String toString() {
StringWriter s = new StringWriter();
try {
@ -375,6 +376,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/** Return a shallow copy of this tree.
*/
@Override
public Object clone() {
try {
return super.clone();
@ -587,7 +589,17 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
@Override
public void accept(Visitor v) { v.visitClassDef(this); }
public Kind getKind() { return Kind.CLASS; }
public Kind getKind() {
if ((mods.flags & Flags.ANNOTATION) != 0)
return Kind.ANNOTATION_TYPE;
else if ((mods.flags & Flags.INTERFACE) != 0)
return Kind.INTERFACE;
else if ((mods.flags & Flags.ENUM) != 0)
return Kind.ENUM;
else
return Kind.CLASS;
}
public JCModifiers getModifiers() { return mods; }
public Name getSimpleName() { return name; }
public List<JCTypeParameter> getTypeParameters() {

View File

@ -501,6 +501,10 @@ public class TreeInfo {
if (that.sym == sym) result = that;
else super.visitVarDef(that);
}
public void visitTypeParameter(JCTypeParameter that) {
if (that.type.tsym == sym) result = that;
else super.visitTypeParameter(that);
}
}
DeclScanner s = new DeclScanner();
tree.accept(s);
@ -633,6 +637,18 @@ public class TreeInfo {
}
}
public static boolean isDeclaration(JCTree node) {
node = skipParens(node);
switch (node.getTag()) {
case JCTree.CLASSDEF:
case JCTree.METHODDEF:
case JCTree.VARDEF:
return true;
default:
return false;
}
}
/** If this tree is an identifier or a field, return its symbol,
* otherwise return null.
*/

View File

@ -37,12 +37,6 @@ package com.sun.tools.javac.util;
public class FatalError extends Error {
private static final long serialVersionUID = 0;
/** Construct a <code>FatalError</code> with no detail message.
*/
public FatalError() {
super();
}
/** Construct a <code>FatalError</code> with the specified detail message.
* @param d A diagnostic containing the reason for failure.
*/
@ -50,6 +44,15 @@ public class FatalError extends Error {
super(d.toString());
}
/** Construct a <code>FatalError</code> with the specified detail message
* and cause.
* @param d A diagnostic containing the reason for failure.
* @param t An exception causing the error
*/
public FatalError(JCDiagnostic d, Throwable t) {
super(d.toString(), t);
}
/** Construct a <code>FatalError</code> with the specified detail message.
* @param s An English(!) string describing the failure, typically because
* the diagnostic resources are missing.

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2010, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.tools.javac.util;
/**
* Simple filter acting as a boolean predicate. Method accepts return true if
* the supplied element matches against the filter.
*/
public interface Filter<T> {
/**
* Does this element match against the filter?
* @param t element to be checked
* @return true if the element satisfy constraints imposed by filter
*/
boolean accepts(T t);
}

View File

@ -27,8 +27,10 @@ package com.sun.tools.javac.util;
import java.io.*;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
@ -110,6 +112,12 @@ public class Log extends AbstractLog {
*/
private JavacMessages messages;
/**
* Deferred diagnostics
*/
public boolean deferDiagnostics;
public Queue<JCDiagnostic> deferredDiagnostics = new ListBuffer<JCDiagnostic>();
/** Construct a log with given I/O redirections.
*/
@Deprecated
@ -204,12 +212,6 @@ public class Log extends AbstractLog {
*/
public int nwarnings = 0;
/**
* Whether or not an unrecoverable error has been seen.
* Unrecoverable errors prevent subsequent annotation processing.
*/
public boolean unrecoverableError;
/** A set of all errors generated so far. This is used to avoid printing an
* error message more than once. For each error, a pair consisting of the
* source file name and source code position of the error is added to the set.
@ -347,12 +349,32 @@ public class Log extends AbstractLog {
nwarnings++;
}
/** Report all deferred diagnostics, and clear the deferDiagnostics flag. */
public void reportDeferredDiagnostics() {
reportDeferredDiagnostics(EnumSet.allOf(JCDiagnostic.Kind.class));
}
/** Report selected deferred diagnostics, and clear the deferDiagnostics flag. */
public void reportDeferredDiagnostics(Set<JCDiagnostic.Kind> kinds) {
deferDiagnostics = false;
JCDiagnostic d;
while ((d = deferredDiagnostics.poll()) != null) {
if (kinds.contains(d.getKind()))
report(d);
}
}
/**
* Common diagnostic handling.
* The diagnostic is counted, and depending on the options and how many diagnostics have been
* reported so far, the diagnostic may be handed off to writeDiagnostic.
*/
public void report(JCDiagnostic diagnostic) {
if (deferDiagnostics) {
deferredDiagnostics.add(diagnostic);
return;
}
if (expectDiagKeys != null)
expectDiagKeys.remove(diagnostic.getCode());

View File

@ -103,7 +103,6 @@ public class Names {
public final Name RuntimeInvisibleTypeAnnotations;
public final Name RuntimeVisibleParameterAnnotations;
public final Name RuntimeInvisibleParameterAnnotations;
public final Name PolymorphicSignature;
public final Name Value;
public final Name EnclosingMethod;
public final Name desiredAssertionStatus;
@ -116,6 +115,7 @@ public class Names {
public final Name value;
public final Name getMessage;
public final Name getClass;
public final Name invoke; //allowTransitionalJSR292 only
public final Name TYPE;
public final Name TYPE_USE;
public final Name TYPE_PARAMETER;
@ -215,7 +215,6 @@ public class Names {
RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
RuntimeVisibleParameterAnnotations = fromString("RuntimeVisibleParameterAnnotations");
RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
PolymorphicSignature = fromString("PolymorphicSignature");
Value = fromString("Value");
EnclosingMethod = fromString("EnclosingMethod");
@ -230,6 +229,7 @@ public class Names {
value = fromString("value");
getMessage = fromString("getMessage");
getClass = fromString("getClass");
invoke = fromString("invoke"); //allowTransitionalJSR292 only
TYPE = fromString("TYPE");
TYPE_USE = fromString("TYPE_USE");

View File

@ -239,7 +239,10 @@ class CodeWriter extends BasicWriter {
new ArrayList<InstructionDetailWriter>();
if (options.details.contains(InstructionDetailWriter.Kind.SOURCE)) {
sourceWriter.reset(classWriter.getClassFile(), attr);
detailWriters.add(sourceWriter);
if (sourceWriter.hasSource())
detailWriters.add(sourceWriter);
else
println("(Source code not available)");
}
if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VARS)) {

View File

@ -99,7 +99,10 @@ public class SourceWriter extends InstructionDetailWriter {
}
}
}
}
public boolean hasSource() {
return (sourceLines.length > 0);
}
private void setLineMap(Code_attribute attr) {

View File

@ -26,10 +26,14 @@
package javax.tools;
import java.io.File;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Logger;
import java.util.logging.Level;
import static java.util.logging.Level.*;
@ -44,8 +48,6 @@ import static java.util.logging.Level.*;
*/
public class ToolProvider {
private ToolProvider() {}
private static final String propertyName = "sun.tools.ToolProvider";
private static final String loggerName = "javax.tools";
@ -87,6 +89,9 @@ public class ToolProvider {
return null;
}
private static final String defaultJavaCompilerName
= "com.sun.tools.javac.api.JavacTool";
/**
* Gets the Java&trade; programming language compiler provided
* with this platform.
@ -94,13 +99,7 @@ public class ToolProvider {
* {@code null} if no compiler is provided
*/
public static JavaCompiler getSystemJavaCompiler() {
if (Lazy.compilerClass == null)
return trace(WARNING, "Lazy.compilerClass == null");
try {
return Lazy.compilerClass.newInstance();
} catch (Throwable e) {
return trace(WARNING, e);
}
return instance().getSystemTool(JavaCompiler.class, defaultJavaCompilerName);
}
/**
@ -113,63 +112,109 @@ public class ToolProvider {
* or {@code null} if no tools are provided
*/
public static ClassLoader getSystemToolClassLoader() {
if (Lazy.compilerClass == null)
return trace(WARNING, "Lazy.compilerClass == null");
return Lazy.compilerClass.getClassLoader();
}
/**
* This class will not be initialized until one of the above
* methods are called. This ensures that searching for the
* compiler does not affect platform start up.
*/
static class Lazy {
private static final String defaultJavaCompilerName
= "com.sun.tools.javac.api.JavacTool";
private static final String[] defaultToolsLocation
= { "lib", "tools.jar" };
static final Class<? extends JavaCompiler> compilerClass;
static {
Class<? extends JavaCompiler> c = null;
try {
c = findClass().asSubclass(JavaCompiler.class);
} catch (Throwable t) {
trace(WARNING, t);
}
compilerClass = c;
}
private static Class<?> findClass()
throws MalformedURLException, ClassNotFoundException
{
try {
return enableAsserts(Class.forName(defaultJavaCompilerName, false, null));
} catch (ClassNotFoundException e) {
trace(FINE, e);
}
File file = new File(System.getProperty("java.home"));
if (file.getName().equalsIgnoreCase("jre"))
file = file.getParentFile();
for (String name : defaultToolsLocation)
file = new File(file, name);
URL[] urls = {file.toURI().toURL()};
trace(FINE, urls[0].toString());
ClassLoader cl = URLClassLoader.newInstance(urls);
cl.setPackageAssertionStatus("com.sun.tools.javac", true);
return Class.forName(defaultJavaCompilerName, false, cl);
}
private static Class<?> enableAsserts(Class<?> cls) {
try {
ClassLoader loader = cls.getClassLoader();
if (loader != null)
loader.setPackageAssertionStatus("com.sun.tools.javac", true);
else
trace(FINE, "loader == null");
} catch (SecurityException ex) {
trace(FINE, ex);
}
return cls;
try {
Class<? extends JavaCompiler> c =
instance().getSystemToolClass(JavaCompiler.class, defaultJavaCompilerName);
return c.getClassLoader();
} catch (Throwable e) {
return trace(WARNING, e);
}
}
private static ToolProvider instance;
private static synchronized ToolProvider instance() {
if (instance == null)
instance = new ToolProvider();
return instance;
}
// Cache for tool classes.
// Use weak references to avoid keeping classes around unnecessarily
private Map<String, Reference<Class<?>>> toolClasses = new HashMap<String, Reference<Class<?>>>();
// Cache for tool classloader.
// Use a weak reference to avoid keeping it around unnecessarily
private Reference<ClassLoader> refToolClassLoader = null;
private ToolProvider() { }
private <T> T getSystemTool(Class<T> clazz, String name) {
Class<? extends T> c = getSystemToolClass(clazz, name);
try {
return c.asSubclass(clazz).newInstance();
} catch (Throwable e) {
trace(WARNING, e);
return null;
}
}
private <T> Class<? extends T> getSystemToolClass(Class<T> clazz, String name) {
Reference<Class<?>> refClass = toolClasses.get(name);
Class<?> c = (refClass == null ? null : refClass.get());
if (c == null) {
try {
c = findSystemToolClass(name);
} catch (Throwable e) {
return trace(WARNING, e);
}
toolClasses.put(name, new WeakReference<Class<?>>(c));
}
return c.asSubclass(clazz);
}
private static final String[] defaultToolsLocation = { "lib", "tools.jar" };
private Class<?> findSystemToolClass(String toolClassName)
throws MalformedURLException, ClassNotFoundException
{
// try loading class directly, in case tool is on the bootclasspath
try {
return enableAsserts(Class.forName(toolClassName, false, null));
} catch (ClassNotFoundException e) {
trace(FINE, e);
// if tool not on bootclasspath, look in default tools location (tools.jar)
ClassLoader cl = (refToolClassLoader == null ? null : refToolClassLoader.get());
if (cl == null) {
File file = new File(System.getProperty("java.home"));
if (file.getName().equalsIgnoreCase("jre"))
file = file.getParentFile();
for (String name : defaultToolsLocation)
file = new File(file, name);
// if tools not found, no point in trying a URLClassLoader
// so rethrow the original exception.
if (!file.exists())
throw e;
URL[] urls = { file.toURI().toURL() };
trace(FINE, urls[0].toString());
cl = URLClassLoader.newInstance(urls);
cl.setPackageAssertionStatus("com.sun.tools.javac", true);
refToolClassLoader = new WeakReference<ClassLoader>(cl);
}
return Class.forName(toolClassName, false, cl);
}
}
private static Class<?> enableAsserts(Class<?> cls) {
try {
ClassLoader loader = cls.getClassLoader();
if (loader != null)
loader.setPackageAssertionStatus("com.sun.tools.javac", true);
else
trace(FINE, "loader == null");
} catch (SecurityException ex) {
trace(FINE, ex);
}
return cls;
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2010, 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 6979683
* @summary Verify that casts can narrow and unbox at the same time
* @author jrose
*
* @compile/fail/ref=TestCast6979683_BAD34.java.errlog -XDrawDiagnostics TestCast6979683_BAD34.java
*/
public class TestCast6979683_BAD34 {
static boolean zconvBAD1(Number o) { return o; } //BAD
//...
//...
//...
//...
//...
}

View File

@ -0,0 +1,2 @@
TestCast6979683_BAD34.java:34:49: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Number, boolean
1 error

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2010, 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 6979683
* @summary Verify that casts can narrow and unbox at the same time
* @author jrose
*
* @compile/fail/ref=TestCast6979683_BAD35.java.errlog -XDrawDiagnostics TestCast6979683_BAD35.java
*/
public class TestCast6979683_BAD35 {
//...
static int iconvBAD1(Number o) { return o; } //BAD: cast needed
//...
//...
//...
//...
}

View File

@ -0,0 +1,2 @@
TestCast6979683_BAD35.java:35:45: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Number, int
1 error

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2010, 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 6979683
* @summary Verify that casts can narrow and unbox at the same time
* @author jrose
*
* @compile/fail/ref=TestCast6979683_BAD36.java.errlog -XDrawDiagnostics TestCast6979683_BAD36.java
*/
public class TestCast6979683_BAD36 {
//...
//...
static int iconvBAD2(Comparable<Integer> o) { return o; } //BAD: cast needed
//...
//...
//...
}

View File

@ -0,0 +1,2 @@
TestCast6979683_BAD36.java:36:58: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Comparable<java.lang.Integer>, int
1 error

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2010, 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 6979683
* @summary Verify that casts can narrow and unbox at the same time
* @author jrose
*
* @compile/fail/ref=TestCast6979683_BAD37.java.errlog -XDrawDiagnostics TestCast6979683_BAD37.java
*/
public class TestCast6979683_BAD37 {
//...
//...
//...
static int iconvBAD3(Comparable<Short> o) { return (int)o; } //BAD: wrong instance
//...
//...
}

View File

@ -0,0 +1,2 @@
TestCast6979683_BAD37.java:37:61: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), java.lang.Comparable<java.lang.Short>, int
1 error

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2010, 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 6979683
* @summary Verify that casts can narrow and unbox at the same time
* @author jrose
*
* @compile/fail/ref=TestCast6979683_BAD38.java.errlog -XDrawDiagnostics TestCast6979683_BAD38.java
*/
public class TestCast6979683_BAD38 {
//...
//...
//...
//...
static float cconvBAD1(Comparable<Character> o) { return o; } //BAD
//...
}

View File

@ -0,0 +1,2 @@
TestCast6979683_BAD38.java:38:62: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Comparable<java.lang.Character>, float
1 error

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2010, 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 6979683
* @summary Verify that casts can narrow and unbox at the same time
* @author jrose
*
* @compile/fail/ref=TestCast6979683_BAD39.java.errlog -XDrawDiagnostics TestCast6979683_BAD39.java
*/
public class TestCast6979683_BAD39 {
//...
//...
//...
//...
//...
static float cconvBAD2(Number o) { return (char)o; } //BAD
}

View File

@ -0,0 +1,2 @@
TestCast6979683_BAD39.java:39:53: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), java.lang.Number, char
1 error

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2010, 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 6979683
* @summary Verify that casts can narrow and unbox at the same time
* @author jrose
*
* @compile TestCast6979683_GOOD.java
* @run main TestCast6979683_GOOD
*/
public class TestCast6979683_GOOD {
public static void main(String... av) {
bugReportExample();
for (int x = -1; x <= 2; x++) {
zconvTests(x != 0);
iconvTests(x);
bconvTests((byte)x);
cconvTests((char)x);
}
System.out.println("Successfully ran "+tests+" tests.");
}
static int tests;
static void assertEquals(Object x, Object y) {
if (!x.equals(y)) {
throw new RuntimeException("assertEquals: "+x+" != "+y);
}
++tests;
}
static void bugReportExample() {
{} // example in bug report:
Object x = (Object)1;
int y = (int)x;
{} // end example
}
static boolean zconv1(Boolean o) { return o; }
static boolean zconv2(Object o) { return (boolean)o; }
static boolean zconv3(Comparable<Boolean> o) { return (boolean)o; }
static void zconvTests(boolean x) {
assertEquals(x, zconv1(x));
assertEquals(x, zconv2(x));
assertEquals(x, zconv3(x));
}
static int iconv1(Integer o) { return o; }
static int iconv2(Object o) { return (int)o; }
static int iconv3(java.io.Serializable o) { return (int)o; }
static int iconv4(Number o) { return (int)o; }
static int iconv5(Comparable<Integer> o) { return (int)o; }
static void iconvTests(int x) {
assertEquals(x, iconv1(x));
assertEquals(x, iconv2(x));
assertEquals(x, iconv3(x));
assertEquals(x, iconv4(x));
assertEquals(x, iconv5(x));
}
static float bconv1(Byte o) { return o; } // note type "float"
static float bconv2(Object o) { return (byte)o; }
static float bconv3(java.io.Serializable o) { return (byte)o; }
static float bconv4(Number o) { return (byte)o; }
static void bconvTests(byte x) {
float xf = x;
assertEquals(xf, bconv1(x));
assertEquals(xf, bconv2(x));
assertEquals(xf, bconv3(x));
assertEquals(xf, bconv4(x));
}
static float cconv1(Character o) { return o; } // note type "float"
static float cconv2(Object o) { return (char)o; }
static float cconv3(java.io.Serializable o) { return (char)o; }
static float cconv4(Comparable<Character> o) { return (char)o; }
static void cconvTests(char x) {
float xf = x;
assertEquals(xf, cconv1(x));
assertEquals(xf, cconv2(x));
assertEquals(xf, cconv3(x));
assertEquals(xf, cconv4(x));
}
}

View File

@ -23,9 +23,11 @@
/*
* @test
* @bug 4399129
* @bug 4399129 6980724
* @summary Check that assertions compile properly when nested in an interface
* @author gafter
* @compile InterfaceAssert.java
* @run main InterfaceAssert
*/
/*

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2010, 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 6458749
* @summary TypeParameterElement.getEnclosedElements() throws NPE within javac
* @build T6458749
* @compile -processor T6458749 -proc:only T6458749.java
*/
import java.util.Set;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.SourceVersion;
@SupportedAnnotationTypes("*")
public class T6458749<T> extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> tes, RoundEnvironment renv) {
if (!renv.processingOver()) {
for(TypeElement e : ElementFilter.typesIn(renv.getRootElements())) {
System.out.printf("Element %s:%n", e.toString());
try {
for (TypeParameterElement tp : e.getTypeParameters()) {
System.out.printf("Type param %s", tp.toString());
if (! tp.getEnclosedElements().isEmpty()) {
throw new AssertionError("TypeParameterElement.getEnclosedElements() should return empty list");
}
}
} catch (NullPointerException npe) {
throw new AssertionError("NPE from TypeParameterElement.getEnclosedElements()", npe);
}
}
}
return true;
}
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2010, 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.
*/
import java.util.Set;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.SourceVersion;
import static javax.tools.Diagnostic.Kind.*;
@SupportedAnnotationTypes("*")
public class MyProcessor extends AbstractProcessor {
private Messager messager;
public void init(ProcessingEnvironment processingEnv) {
this.messager = processingEnv.getMessager();
}
public boolean process(Set<? extends TypeElement> tes, RoundEnvironment renv) {
if (!renv.processingOver()) {
for(TypeElement e : ElementFilter.typesIn(renv.getRootElements())) {
for (TypeParameterElement tp : e.getTypeParameters()) {
if (tp.getSimpleName().toString().length() > 1) {
messager.printMessage(WARNING,
"Type param names should be of length 1", tp);
}
}
}
}
return true;
}
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2010, 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 6458823
* @summary Messager messages on TypeParamterElements to not include position information.
*
* @compile MyProcessor.java T6458823.java
* @run main T6458823
*/
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class T6458823 {
public static void main(String[] args) throws Exception {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null) {
throw new RuntimeException("can't get javax.tools.JavaCompiler!");
}
DiagnosticCollector<JavaFileObject> diagColl =
new DiagnosticCollector<JavaFileObject>();
StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null);
List<String> options = new ArrayList<String>();
options.add("-processor");
options.add("MyProcessor");
options.add("-proc:only");
List<File> files = new ArrayList<File>();
files.add(new File(T6458823.class.getResource("TestClass.java").toURI()));
final CompilationTask task = compiler.getTask(null, fm, diagColl,
options, null, fm.getJavaFileObjectsFromFiles(files));
task.call();
int diagCount = 0;
for (Diagnostic<? extends JavaFileObject> diag : diagColl.getDiagnostics()) {
if (diag.getKind() != Diagnostic.Kind.WARNING) {
throw new AssertionError("Only warnings expected");
}
System.out.println(diag);
if (diag.getPosition() == Diagnostic.NOPOS) {
throw new AssertionError("No position info in message");
}
if (diag.getSource() == null) {
throw new AssertionError("No source info in message");
}
diagCount++;
}
if (diagCount != 2) {
throw new AssertionError("unexpected number of warnings: " +
diagCount + ", expected: 2");
}
}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2010, 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.
*/
class TestClass<XYZ, ABC> {
}

View File

@ -71,12 +71,10 @@ public class T6855236 extends AbstractProcessor {
@Override
public Object visitMethodInvocation(MethodInvocationTree node, Trees p) {
System.out.print("current path: ");
System.out.println("current path: ");
for (Tree t : getCurrentPath()) {
System.out.print('/');
System.out.print(t);
}
System.out.println();
System.out.println(" " + t.getKind() + ": " + trim(t, 64));
}
System.out.println("parent path: " + getCurrentPath().getParentPath());
System.out.println("method select: " + node.getMethodSelect().toString());
for (ExpressionTree arg : node.getArguments()) {
@ -88,12 +86,20 @@ public class T6855236 extends AbstractProcessor {
@Override
public Object visitExpressionStatement(ExpressionStatementTree node, Trees p) {
ExpressionTree t = node.getExpression();
System.out.println("expression statement: " + t.toString());
System.out.println();
System.out.println("expression statement: " + trim(t, 64));
return super.visitExpressionStatement(node, p);
}
}
private String trim(Tree t, int len) {
String s = t.toString().trim().replaceAll("\\s+", " ");
if (s.length() > len)
s = s.substring(0, len) + "...";
return s;
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2010, 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 6900149
* @summary IllegalStateException when compiling same files and DiagnosticListener is set
*/
import java.io.*;
import java.util.*;
import javax.tools.*;
import javax.tools.JavaCompiler.CompilationTask;
public class T6900149 {
public static void main(String[] args) throws IOException {
DiagnosticCollector<JavaFileObject> diag =
new DiagnosticCollector<JavaFileObject>();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm =
compiler.getStandardFileManager(null, null, null);
File emptyFile = File.createTempFile("Empty", ".java");
File[] files = new File[] { emptyFile, emptyFile };
CompilationTask task = compiler.getTask(null, fm, diag,
null, null, fm.getJavaFileObjects(files));
if (! task.call()) {
throw new AssertionError("compilation failed");
}
}
}

View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2010, 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 6956462
* @summary AssertionError exception throws in the Compiler Tree API in JDK 7.
*
* @build TestClass T6956462
* @run main T6956462
*/
import java.io.*;
import java.net.URISyntaxException;
import java.util.*;
import javax.tools.*;
import javax.tools.JavaCompiler.CompilationTask;
import com.sun.source.tree.*;
import com.sun.source.util.*;
public class T6956462 {
public static void main(String[] args) throws Exception {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null) {
throw new RuntimeException("can't get javax.tools.JavaCompiler!");
}
StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null);
List<File> files = new ArrayList<File>();
files.add(new File(T6956462.class.getResource("TestClass.java").toURI()));
final CompilationTask task = compiler.getTask(null, fm, null,
null, null, fm.getJavaFileObjectsFromFiles(files));
JavacTask javacTask = (JavacTask) task;
for (CompilationUnitTree cu : javacTask.parse()) {
cu.accept(new MyVisitor(javacTask), null);
}
}
private static class MyVisitor extends SimpleTreeVisitor<Tree, Void> {
private final Trees trees;
private CompilationUnitTree file;
private MyVisitor(JavacTask javac) {
this.trees = Trees.instance(javac);
}
@Override
public Tree visitCompilationUnit(CompilationUnitTree file, Void v) {
this.file = file;
for (Tree typeDecl : file.getTypeDecls()) {
typeDecl.accept(this, v);
}
return null;
}
@Override
public Tree visitImport(ImportTree imp, Void v) {
return null;
}
@Override
public Tree visitMethodInvocation(MethodInvocationTree invoke, Void v) {
invoke.getMethodSelect().accept(this, v);
return null;
}
@Override
public Tree visitBlock(BlockTree block, Void v) {
for (StatementTree stat : block.getStatements()) {
stat.accept(this, v);
}
return null;
}
@Override
public Tree visitClass(ClassTree clazz, Void v) {
for (Tree member : clazz.getMembers()) {
member.accept(this, v);
}
return null;
}
@Override
public Tree visitIdentifier(IdentifierTree ident, Void v) {
trees.getScope(trees.getPath(file, ident));
return null;
}
@Override
public Tree visitMethod(MethodTree method, Void v) {
method.getBody().accept(this, v);
return null;
}
@Override
public Tree visitMemberSelect(MemberSelectTree select, Void v) {
select.getExpression().accept(this, v);
return null;
}
@Override
public Tree visitVariable(VariableTree var, Void v) {
var.getInitializer().accept(this, v);
return null;
}
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2010, 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.
*/
import java.io.PrintStream;
abstract class TestClass {
private void test() {
final PrintStream out = System.out;
}
}

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2010, 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 6985181
* @summary Annotations lost from classfile
*/
import java.io.*;
import java.util.*;
public class T6985181 {
public static void main(String... args) throws Exception{
new T6985181().run();
}
public void run() throws Exception {
String code = "@interface Simple { }\ninterface Test<@Simple T> { }";
File srcFile = writeFile("Test.java", code);
File classesDir = new File("classes");
classesDir.mkdirs();
compile("-d", classesDir.getPath(), srcFile.getPath());
String out = javap(new File(classesDir, srcFile.getName().replace(".java", ".class")));
if (!out.contains("RuntimeInvisibleTypeAnnotations"))
throw new Exception("RuntimeInvisibleTypeAnnotations not found");
}
void compile(String... args) throws Exception {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
int rc = com.sun.tools.javac.Main.compile(args, pw);
pw.close();
String out = sw.toString();
if (out.length() > 0)
System.err.println(out);
if (rc != 0)
throw new Exception("Compilation failed: rc=" + rc);
}
String javap(File classFile) throws Exception {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
String[] args = { "-v", classFile.getPath() };
int rc = com.sun.tools.javap.Main.run(args, pw);
pw.close();
String out = sw.toString();
if (out.length() > 0)
System.err.println(out);
if (rc != 0)
throw new Exception("javap failed: rc=" + rc);
return out;
}
File writeFile(String path, String body) throws IOException {
File f = new File(path);
FileWriter out = new FileWriter(f);
try {
out.write(body);
} finally {
out.close();
}
return f;
}
}

View File

@ -0,0 +1,174 @@
/*
* Copyright (c) 2010, 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 6960424
* @summary new option -Xpkginfo for better control of when package-info.class is generated
*/
import java.io.*;
import java.util.*;
public class TestPkgInfo {
enum OptKind {
NONE(null),
ALWAYS("-Xpkginfo:always"),
NONEMPTY("-Xpkginfo:nonempty"),
LEGACY("-Xpkginfo:legacy");
OptKind(String opt) { this.opt = opt; }
final String opt;
};
public static void main(String... args) throws Exception {
new TestPkgInfo().run(args);
}
public void run(String... args) throws Exception {
boolean[] booleanValues = { false, true };
for (OptKind ok: OptKind.values()) {
for (boolean sr: booleanValues) {
for (boolean cr: booleanValues) {
for (boolean rr: booleanValues) {
try {
test(ok, sr, cr, rr);
} catch (Exception e) {
error("Exception: " + e);
}
if (errors > 0) throw new AssertionError();
}
}
}
}
if (errors > 0)
throw new Exception(errors + " errors occurred");
}
void test(OptKind ok, boolean sr, boolean cr, boolean rr) throws Exception {
count++;
System.err.println("Test " + count + ": ok:" + ok + " sr:" + sr + " cr:" + cr + " rr:" + rr);
StringBuilder sb = new StringBuilder();
// create annotated package statement with all combinations of retention policy
if (sr) sb.append("@SR\n");
if (cr) sb.append("@CR\n");
if (rr) sb.append("@RR\n");
sb.append("package p;\n");
sb.append("\n");
sb.append("import java.lang.annotation.*;\n");
sb.append("@Retention(RetentionPolicy.SOURCE) @interface SR { }\n");
sb.append("@Retention(RetentionPolicy.CLASS) @interface CR { }\n");
sb.append("@Retention(RetentionPolicy.RUNTIME) @interface RR { }\n");
// test specific tmp directory
File tmpDir = new File("tmp.test" + count);
File classesDir = new File(tmpDir, "classes");
classesDir.mkdirs();
File pkginfo_java = new File(new File(tmpDir, "src"), "package-info.java");
writeFile(pkginfo_java, sb.toString());
// build up list of options and files to be compiled
List<String> opts = new ArrayList<String>();
List<File> files = new ArrayList<File>();
opts.add("-d");
opts.add(classesDir.getPath());
if (ok.opt != null)
opts.add(ok.opt);
//opts.add("-verbose");
files.add(pkginfo_java);
compile(opts, files);
File pkginfo_class = new File(new File(classesDir, "p"), "package-info.class");
boolean exists = pkginfo_class.exists();
boolean expected;
switch (ok) {
case ALWAYS:
expected = true;
break;
case LEGACY:
case NONE:
expected = (sr || cr || rr ); // any annotation
break;
case NONEMPTY:
expected = (cr || rr ); // any annotation in class file
break;
default:
throw new IllegalStateException();
}
if (exists && !expected)
error("package-info.class found but not expected");
if (!exists && expected)
error("package-info.class expected but not found");
}
/** Compile files with options provided. */
void compile(List<String> opts, List<File> files) throws Exception {
System.err.println("javac: " + opts + " " + files);
List<String> args = new ArrayList<String>();
args.addAll(opts);
for (File f: files)
args.add(f.getPath());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw);
pw.flush();
if (sw.getBuffer().length() > 0)
System.err.println(sw.toString());
if (rc != 0)
throw new Exception("compilation failed: rc=" + rc);
}
/** Write a file with a given body. */
void writeFile(File f, String body) throws Exception {
if (f.getParentFile() != null)
f.getParentFile().mkdirs();
Writer out = new FileWriter(f);
try {
out.write(body);
} finally {
out.close();
}
}
/** Report an error. */
void error(String msg) {
System.err.println("Error: " + msg);
errors++;
}
/** Test case counter. */
int count;
/** Number of errors found. */
int errors;
}

View File

@ -47,12 +47,12 @@ public class T6392782 {
check(scanner, 6, scanner.scan(trees, null));
CountNodes nodeCounter = new CountNodes();
// 383 nodes with the regular parser; 384 nodes with EndPosParser
// We automatically swith to EndPosParser when calling JavacTask.parse()
check(nodeCounter, 384, nodeCounter.scan(trees, null));
// 359 nodes with the regular parser; 360 nodes with EndPosParser
// We automatically switch to EndPosParser when calling JavacTask.parse()
check(nodeCounter, 360, nodeCounter.scan(trees, null));
CountIdentifiers idCounter = new CountIdentifiers();
check(idCounter, 106, idCounter.scan(trees, null));
check(idCounter, 107, idCounter.scan(trees, null));
}
private static void check(TreeScanner<?,?> scanner, int expect, int found) {
@ -73,10 +73,11 @@ public class T6392782 {
}
}
// example from TreeScanner javadoc
static class CountNodes extends TreeScanner<Integer,Void> {
@Override
public Integer scan(Tree node, Void p) {
if (node == null)
return 0;
Integer n = super.scan(node, p);
return (n == null ? 0 : n) + 1;
}

View File

@ -0,0 +1,216 @@
/*
* Copyright (c) 2010, 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 6981185
* @summary com.sun.tools.model.JavacTypes.contains() calls Type.contains instead of Types.containsType
* @run main TestContainTypes
*/
import java.net.URI;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.DeclaredType;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import com.sun.source.util.JavacTask;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
public class TestContainTypes {
enum ClassType {
OBJECT("Object"),
NUMBER("Number"),
INTEGER("Integer"),
STRING("String");
String classStub;
ClassType(String classStub) {
this.classStub = classStub;
}
boolean subtypeOf(ClassType that) {
switch (that) {
case OBJECT: return true;
case NUMBER: return this == NUMBER || this == INTEGER;
case INTEGER: return this == INTEGER;
case STRING: return this == STRING;
default: throw new AssertionError("Bad type kind in subtyping test");
}
}
}
enum ParameterType {
INVARIANT("List<#1>"),
COVARIANT("List<? extends #1>"),
CONTRAVARIANT("List<? super #1>"),
BIVARIANT("List<?>");
String paramTypeStub;
ParameterType(String paramTypeStub) {
this.paramTypeStub = paramTypeStub;
}
String instantiate(ClassType ct) {
return paramTypeStub.replace("#1", ct.classStub);
}
static boolean contains(ParameterType pt1, ClassType ct1,
ParameterType pt2, ClassType ct2) {
switch (pt1) {
case INVARIANT: return (pt2 == INVARIANT && ct1 == ct2) ||
(pt2 == CONTRAVARIANT && ct1 == ct2 && ct1 == ClassType.OBJECT);
case COVARIANT: return ((pt2 == INVARIANT || pt2 == COVARIANT) &&
ct2.subtypeOf(ct1)) ||
(ct1 == ClassType.OBJECT);
case CONTRAVARIANT: return (pt2 == INVARIANT || pt2 == CONTRAVARIANT) &&
ct1.subtypeOf(ct2);
case BIVARIANT: return true;
default: throw new AssertionError("Bad type kind in containment test");
}
}
}
static class JavaSource extends SimpleJavaFileObject {
final static String sourceStub =
"import java.util.List;\n" +
"@interface ToCheck {}\n" +
"class Test {\n" +
" @ToCheck void test(#A a, #B b) {}\n" +
"}\n";
String source;
public JavaSource(String typeA, String typeB) {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
source = sourceStub.replace("#A", typeA).replace("#B", typeB);
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return source;
}
}
public static void main(String... args) throws Exception {
for (ClassType ctA : ClassType.values()) {
for (ParameterType ptA : ParameterType.values()) {
for (ClassType ctB : ClassType.values()) {
for (ParameterType ptB : ParameterType.values()) {
compileAndCheck(ptA, ctA, ptB, ctB);
}
}
}
}
}
static void compileAndCheck(ParameterType ptA, ClassType ctA, ParameterType ptB, ClassType ctB) throws Exception {
JavaSource source = new JavaSource(ptA.instantiate(ctA), ptB.instantiate(ctB));
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
JavacTask ct = (JavacTask)tool.getTask(null, null, null,
null, null, Arrays.asList(source));
ct.setProcessors(Arrays.asList(new ContainTypesTester(ParameterType.contains(ptA, ctA, ptB, ctB), source)));
System.err.println("A = " + ptA +" / " + ptA.instantiate(ctA));
System.err.println("B = " + ptB +" / " + ptB.instantiate(ctB));
System.err.println("Source = " + source.source);
ct.analyze();
}
@SupportedSourceVersion(SourceVersion.RELEASE_7)
static class ContainTypesTester extends AbstractProcessor {
boolean expected;
JavaSource source;
ContainTypesTester(boolean expected, JavaSource source) {
this.expected = expected;
this.source = source;
}
@Override
public Set<String> getSupportedAnnotationTypes() {
Set<String> supportedAnnos = new HashSet();
supportedAnnos.add("*");
return supportedAnnos;
}
private void error(String msg) {
System.err.println(source.source);
throw new AssertionError(msg);
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.getRootElements().size() == 0) {
return true;
}
if (annotations.isEmpty() || annotations.size() > 1) {
error("no anno found/wrong number of annotations found: " + annotations.size());
}
TypeElement anno = (TypeElement)annotations.toArray()[0];
Set<? extends Element> annoElems = roundEnv.getElementsAnnotatedWith(anno);
if (annoElems.isEmpty() || annoElems.size() > 1) {
error("no annotated element found/wrong number of annotated elements found: " + annoElems.size());
}
Element annoElement = (Element)annoElems.toArray()[0];
if (!(annoElement instanceof ExecutableElement)) {
error("annotated element must be a method");
}
ExecutableElement method = (ExecutableElement)annoElement;
if (method.getParameters().size() != 2) {
error("annotated method must have 2 arguments");
}
DeclaredType d1 = (DeclaredType)method.getParameters().get(0).asType();
DeclaredType d2 = (DeclaredType)method.getParameters().get(1).asType();
if (d1.getTypeArguments().size() != 1 ||
d1.getTypeArguments().size() != 1) {
error("parameter type must be generic in one type-variable");
}
TypeMirror t1 = d1.getTypeArguments().get(0);
TypeMirror t2 = d2.getTypeArguments().get(0);
if (processingEnv.getTypeUtils().contains(t1, t2) != expected) {
error("bad type containment result\n" +
"t1 : " + t1 +"\n" +
"t2 : " + t2 +"\n" +
"expected answer : " + expected +"\n");
}
return true;
}
}
}

View File

@ -0,0 +1,235 @@
/*
* Copyright (c) 2010, 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 6930507
* @summary Symbols for anonymous and local classes made too late for use by java tree API
*/
import java.io.*;
import java.util.*;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.tools.Diagnostic;
import static javax.lang.model.util.ElementFilter.*;
import com.sun.source.tree.*;
import com.sun.source.util.*;
@SupportedOptions({"test", "last"})
@SupportedAnnotationTypes("*")
public class TestGetElement extends AbstractProcessor {
public static void main(String... args) throws Exception {
new TestGetElement().run();
}
public TestGetElement() { }
public void run() throws Exception {
final String testSrc = System.getProperty("test.src");
final String testClasses = System.getProperty("test.classes");
final String myClassName = getClass().getName();
final String mySrc = new File(testSrc, myClassName + ".java").getPath();
final int NUM_TESTS = 90; // #decls in this source file
for (int i = 1; i <= NUM_TESTS; i++) {
System.err.println("test " + i);
File testDir = new File("test" + i);
File classesDir = new File(testDir, "classes");
classesDir.mkdirs();
String[] args = {
"-d", classesDir.getPath(),
"-processorpath", testClasses,
"-processor", myClassName,
"-proc:only",
"-Atest=" + i,
"-Alast=" + (i == NUM_TESTS),
mySrc
};
// System.err.println("compile: " + Arrays.asList(args));
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
int rc = com.sun.tools.javac.Main.compile(args, pw);
pw.close();
String out = sw.toString();
if (out != null)
System.err.println(out);
if (rc != 0) {
System.err.println("compilation failed: rc=" + rc);
errors++;
}
}
if (errors > 0)
throw new Exception(errors + " errors occurred");
}
int errors;
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnvironment)
{
if (roundEnvironment.processingOver())
return true;
Map<String,String> options = processingEnv.getOptions();
int test = Integer.parseInt(options.get("test"));
boolean _last = Boolean.parseBoolean(options.get("last"));
Trees trees = Trees.instance(processingEnv);
Scanner scanner = new Scanner(trees, _last);
int nelems = 0;
for (TypeElement e : typesIn(roundEnvironment.getRootElements())) {
nelems += scanner.scan(trees.getPath(e), test);
}
Messager m = processingEnv.getMessager();
int EXPECT = 1;
if (nelems != EXPECT) {
m.printMessage(Diagnostic.Kind.ERROR,
"Unexpected number of elements found: " + nelems + " expected: " + EXPECT);
}
return true;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
class Scanner extends TreePathScanner<Integer,Integer> {
final Trees trees;
final boolean last;
int count;
Scanner(Trees trees, boolean last) {
this.trees = trees;
this.last = last;
}
@Override
public Integer visitClass(ClassTree tree, Integer test) {
return reduce(check(test), super.visitClass(tree, test));
}
@Override
public Integer visitMethod(MethodTree tree, Integer test) {
return reduce(check(test), super.visitMethod(tree, test));
}
@Override
public Integer visitVariable(VariableTree tree, Integer test) {
return reduce(check(test), super.visitVariable(tree, test));
}
@Override
public Integer reduce(Integer i1, Integer i2) {
if (i1 == null || i1.intValue() == 0)
return i2;
if (i2 == null || i2.intValue() == 0)
return i1;
return (i1 + i2);
}
int check(int test) {
count++;
if (count != test)
return 0;
TreePath p = getCurrentPath();
Element e = trees.getElement(p);
String text = p.getLeaf().toString().replaceAll("\\s+", " ").trim();
int MAXLEN = 40;
if (text.length() > MAXLEN)
text = text.substring(0, MAXLEN - 3) + "...";
System.err.println(String.format("%3d: %-" + MAXLEN + "s -- %s",
count, text,
(e == null ? "null" : e.getKind() + " " + e)));
Messager m = processingEnv.getMessager();
if (e == null) {
m.printMessage(Diagnostic.Kind.ERROR, "Null element found for " + text);
return 0;
}
if (last && !e.getSimpleName().contentEquals("last")) {
m.printMessage(Diagnostic.Kind.ERROR, "Unexpected name in last test: "
+ e.getSimpleName() + ", expected: last");
}
return 1;
}
}
// following are all fodder for the test
class MemberClass {
class NestedMemberClass { }
}
{
class InnerClassInInit { }
Object o = new Object() { };
}
TestGetElement(TestGetElement unused) {
class InnerClassInConstr { }
Object o = new Object() { };
}
void m() {
class InnerClassInMethod { }
Object o = new Object() { };
class C {
class MemberClass {
class NestedMemberClass { }
}
{
class InnerClassInInit { }
Object o = new Object() { };
}
C(Object unused) {
class InnerClassInConstr { }
Object o = new Object() { };
}
void m() {
class InnerClassInMethod { }
Object o = new Object() { };
}
}
}
int last; // this name is verified by the test to make sure that all decls are checked
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2010, 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 6604599
* @summary ToolProvider should be less compiler-specific
*/
import java.io.*;
import java.util.*;
// verify that running a simple program, such as this one, does not trigger
// the loading of ToolProvider or any com.sun.tools.javac class
public class HelloWorldTest {
public static void main(String... args) throws Exception {
if (args.length > 0) {
System.err.println(Arrays.asList(args));
return;
}
new HelloWorldTest().run();
}
void run() throws Exception {
File javaHome = new File(System.getProperty("java.home"));
if (javaHome.getName().equals("jre"))
javaHome = javaHome.getParentFile();
File javaExe = new File(new File(javaHome, "bin"), "java");
String classpath = System.getProperty("java.class.path");
String[] cmd = {
javaExe.getPath(),
"-verbose:class",
"-classpath", classpath,
HelloWorldTest.class.getName(),
"Hello", "World"
};
ProcessBuilder pb = new ProcessBuilder(cmd).redirectErrorStream(true);
Process p = pb.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = r.readLine()) != null) {
System.err.println(line);
if (line.contains("javax.tools.ToolProvider") || line.contains("com.sun.tools.javac."))
error(">>> " + line);
}
int rc = p.waitFor();
if (rc != 0)
error("Unexpected exit code: " + rc);
if (errors > 0)
throw new Exception(errors + " errors occurred");
}
void error(String msg) {
System.err.println(msg);
errors++;
}
int errors;
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2010, 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 6604599
* @summary ToolProvider should be less compiler-specific
*/
import java.io.*;
// verify that running accessing ToolProvider by itself does not
// trigger loading com.sun.tools.javac.*
public class ToolProviderTest1 {
public static void main(String... args) throws Exception {
if (args.length > 0) {
System.err.println(Class.forName(args[0], true, null));
return;
}
new ToolProviderTest1().run();
}
void run() throws Exception {
File javaHome = new File(System.getProperty("java.home"));
if (javaHome.getName().equals("jre"))
javaHome = javaHome.getParentFile();
File javaExe = new File(new File(javaHome, "bin"), "java");
String classpath = System.getProperty("java.class.path");
String[] cmd = {
javaExe.getPath(),
"-verbose:class",
"-classpath", classpath,
ToolProviderTest1.class.getName(),
"javax.tools.ToolProvider"
};
ProcessBuilder pb = new ProcessBuilder(cmd).redirectErrorStream(true);
Process p = pb.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = r.readLine()) != null) {
System.err.println(line);
if (line.contains("com.sun.tools.javac."))
error(">>> " + line);
}
int rc = p.waitFor();
if (rc != 0)
error("Unexpected exit code: " + rc);
if (errors > 0)
throw new Exception(errors + " errors occurred");
}
void error(String msg) {
System.err.println(msg);
errors++;
}
int errors;
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2010, 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 6604599
* @summary ToolProvider should be less compiler-specific
*/
import java.io.*;
import javax.tools.*;
// control for ToolProviderTest1 -- verify that using ToolProvider to
// access the compiler does trigger loading com.sun.tools.javac.*
public class ToolProviderTest2 {
public static void main(String... args) throws Exception {
if (args.length > 0) {
System.err.println(ToolProvider.getSystemJavaCompiler());
return;
}
new ToolProviderTest2().run();
}
void run() throws Exception {
File javaHome = new File(System.getProperty("java.home"));
if (javaHome.getName().equals("jre"))
javaHome = javaHome.getParentFile();
File javaExe = new File(new File(javaHome, "bin"), "java");
String classpath = System.getProperty("java.class.path");
String[] cmd = {
javaExe.getPath(),
"-verbose:class",
"-classpath", classpath,
ToolProviderTest2.class.getName(),
"javax.tools.ToolProvider"
};
ProcessBuilder pb = new ProcessBuilder(cmd).redirectErrorStream(true);
Process p = pb.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
boolean found = false;
while ((line = r.readLine()) != null) {
System.err.println(line);
if (line.contains("com.sun.tools.javac."))
found = true;
}
int rc = p.waitFor();
if (rc != 0)
error("Unexpected exit code: " + rc);
if (!found)
System.err.println("expected class name not found");
if (errors > 0)
throw new Exception(errors + " errors occurred");
}
void error(String msg) {
System.err.println(msg);
errors++;
}
int errors;
}

View File

@ -62,6 +62,7 @@ compiler.misc.class.file.wrong.class
compiler.misc.fatal.err.cant.locate.ctor # Resolve, from Lower
compiler.misc.fatal.err.cant.locate.field # Resolve, from Lower
compiler.misc.fatal.err.cant.locate.meth # Resolve, from Lower
compiler.misc.fatal.err.cant.close.loader # JavacProcessingEnvironment
compiler.misc.file.does.not.contain.package
compiler.misc.illegal.start.of.class.file
compiler.misc.inferred.do.not.conform.to.params # UNUSED (hard to see if very complex inference scenario might require this though, so leaving it in, as per JLS3)
@ -113,3 +114,4 @@ compiler.warn.proc.type.already.exists # JavacFiler: just menti
compiler.warn.unchecked.assign # DEAD, replaced by compiler.misc.unchecked.assign
compiler.warn.unchecked.cast.to.type # DEAD, replaced by compiler.misc.unchecked.cast.to.type
compiler.warn.unexpected.archive.file # Paths: zip file with unknown extn
compiler.warn.wrong.target.for.polymorphic.signature.definition # Transitional 292

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2010, 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.warn.type.parameter.on.polymorphic.signature
// key: compiler.err.unreported.exception.need.to.catch.or.throw
import java.dyn.InvokeDynamic;
class TypeParameterOnPolymorphicSignature {
{ InvokeDynamic.<void>call("",123); }
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2010, 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.unsupported.exotic.id
// options: -source 6
class UnsupportedExoticID {
void m() {
Object #"Hello!" = null;
}
}

View File

@ -0,0 +1,775 @@
/*
* Copyright (c) 2010, 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.
*/
import com.sun.source.util.TaskEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCImport;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Pair;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.lang.model.element.Element;
/**
* Utility and test program to check validity of tree positions for tree nodes.
* The program can be run standalone, or as a jtreg test. In standalone mode,
* errors can be displayed in a gui viewer. For info on command line args,
* run program with no args.
*
* <p>
* jtreg: Note that by using the -r switch in the test description below, this test
* will process all java files in the langtools/test directory, thus implicitly
* covering any new language features that may be tested in this test suite.
*/
/*
* @test
* @bug 6970584
* @summary assorted position errors in compiler syntax trees
* @run main CheckAttributedTree -q -r -et ERRONEOUS .
*/
public class CheckAttributedTree {
/**
* Main entry point.
* If test.src is set, program runs in jtreg mode, and will throw an Error
* if any errors arise, otherwise System.exit will be used, unless the gui
* viewer is being used. In jtreg mode, the default base directory for file
* args is the value of ${test.src}. In jtreg mode, the -r option can be
* given to change the default base directory to the root test directory.
*/
public static void main(String... args) {
String testSrc = System.getProperty("test.src");
File baseDir = (testSrc == null) ? null : new File(testSrc);
boolean ok = new CheckAttributedTree().run(baseDir, args);
if (!ok) {
if (testSrc != null) // jtreg mode
throw new Error("failed");
else
System.exit(1);
}
}
/**
* Run the program. A base directory can be provided for file arguments.
* In jtreg mode, the -r option can be given to change the default base
* directory to the test root directory. For other options, see usage().
* @param baseDir base directory for any file arguments.
* @param args command line args
* @return true if successful or in gui mode
*/
boolean run(File baseDir, String... args) {
if (args.length == 0) {
usage(System.out);
return true;
}
List<File> files = new ArrayList<File>();
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.equals("-encoding") && i + 1 < args.length)
encoding = args[++i];
else if (arg.equals("-gui"))
gui = true;
else if (arg.equals("-q"))
quiet = true;
else if (arg.equals("-v"))
verbose = true;
else if (arg.equals("-t") && i + 1 < args.length)
tags.add(args[++i]);
else if (arg.equals("-ef") && i + 1 < args.length)
excludeFiles.add(new File(baseDir, args[++i]));
else if (arg.equals("-et") && i + 1 < args.length)
excludeTags.add(args[++i]);
else if (arg.equals("-r")) {
if (excludeFiles.size() > 0)
throw new Error("-r must be used before -ef");
File d = baseDir;
while (!new File(d, "TEST.ROOT").exists()) {
if (d == null)
throw new Error("cannot find TEST.ROOT");
d = d.getParentFile();
}
baseDir = d;
}
else if (arg.startsWith("-"))
throw new Error("unknown option: " + arg);
else {
while (i < args.length)
files.add(new File(baseDir, args[i++]));
}
}
for (File file: files) {
if (file.exists())
test(file);
else
error("File not found: " + file);
}
if (fileCount != 1)
System.err.println(fileCount + " files read");
if (errors > 0)
System.err.println(errors + " errors");
return (gui || errors == 0);
}
/**
* Print command line help.
* @param out output stream
*/
void usage(PrintStream out) {
out.println("Usage:");
out.println(" java CheckAttributedTree options... files...");
out.println("");
out.println("where options include:");
out.println("-q Quiet: don't report on inapplicable files");
out.println("-gui Display returns in a GUI viewer");
out.println("-v Verbose: report on files as they are being read");
out.println("-t tag Limit checks to tree nodes with this tag");
out.println(" Can be repeated if desired");
out.println("-ef file Exclude file or directory");
out.println("-et tag Exclude tree nodes with given tag name");
out.println("");
out.println("files may be directories or files");
out.println("directories will be scanned recursively");
out.println("non java files, or java files which cannot be parsed, will be ignored");
out.println("");
}
/**
* Test a file. If the file is a directory, it will be recursively scanned
* for java files.
* @param file the file or directory to test
*/
void test(File file) {
if (excludeFiles.contains(file)) {
if (!quiet)
error("File " + file + " excluded");
return;
}
if (file.isDirectory()) {
for (File f: file.listFiles()) {
test(f);
}
return;
}
if (file.isFile() && file.getName().endsWith(".java")) {
try {
if (verbose)
System.err.println(file);
fileCount++;
NPETester p = new NPETester();
p.test(read(file));
} catch (AttributionException e) {
if (!quiet) {
error("Error attributing " + file + "\n" + e.getMessage());
}
} catch (IOException e) {
error("Error reading " + file + ": " + e);
}
return;
}
if (!quiet)
error("File " + file + " ignored");
}
/**
* Read a file.
* @param file the file to be read
* @return the tree for the content of the file
* @throws IOException if any IO errors occur
* @throws TreePosTest.ParseException if any errors occur while parsing the file
*/
List<Pair<JCCompilationUnit, JCTree>> read(File file) throws IOException, AttributionException {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
Reporter r = new Reporter(pw);
JavacTool tool = JavacTool.create();
Charset cs = (encoding == null ? null : Charset.forName(encoding));
StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null);
Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file);
String[] opts = { "-XDshouldStopPolicy=ATTR", "-XDverboseCompilePolicy" };
JavacTask task = tool.getTask(pw, fm, r, Arrays.asList(opts), null, files);
final List<Element> analyzedElems = new ArrayList<>();
task.setTaskListener(new TaskListener() {
public void started(TaskEvent e) {
if (e.getKind() == TaskEvent.Kind.ANALYZE)
analyzedElems.add(e.getTypeElement());
}
public void finished(TaskEvent e) { }
});
try {
Iterable<? extends CompilationUnitTree> trees = task.parse();
task.analyze();
List<Pair<JCCompilationUnit, JCTree>> res = new ArrayList<>();
//System.out.println("Try to add pairs. Elems are " + analyzedElems);
for (CompilationUnitTree t : trees) {
JCCompilationUnit cu = (JCCompilationUnit)t;
for (JCTree def : cu.defs) {
if (def.getTag() == JCTree.CLASSDEF &&
analyzedElems.contains(((JCTree.JCClassDecl)def).sym)) {
//System.out.println("Adding pair...");
res.add(new Pair<>(cu, def));
}
}
}
return res;
}
catch (Throwable t) {
throw new AttributionException("Exception while attributing file: " + file);
}
}
/**
* Report an error. When the program is complete, the program will either
* exit or throw an Error if any errors have been reported.
* @param msg the error message
*/
void error(String msg) {
System.err.println(msg);
errors++;
}
/** Number of files that have been analyzed. */
int fileCount;
/** Number of errors reported. */
int errors;
/** Flag: don't report irrelevant files. */
boolean quiet;
/** Flag: show errors in GUI viewer. */
boolean gui;
/** The GUI viewer for errors. */
Viewer viewer;
/** Flag: report files as they are processed. */
boolean verbose;
/** Option: encoding for test files. */
String encoding;
/** The set of tags for tree nodes to be analyzed; if empty, all tree nodes
* are analyzed. */
Set<String> tags = new HashSet<String>();
/** Set of files and directories to be excluded from analysis. */
Set<File> excludeFiles = new HashSet<File>();
/** Set of tag names to be excluded from analysis. */
Set<String> excludeTags = new HashSet<String>();
/** Utility class for trees */
TreeUtil treeUtil = new TreeUtil();
/**
* Main class for testing assertions concerning types/symbol
* left uninitialized after attribution
*/
private class NPETester extends TreeScanner {
void test(List<Pair<JCCompilationUnit, JCTree>> trees) {
for (Pair<JCCompilationUnit, JCTree> p : trees) {
sourcefile = p.fst.sourcefile;
endPosTable = p.fst.endPositions;
encl = new Info(p.snd, endPosTable);
p.snd.accept(this);
}
}
@Override
public void scan(JCTree tree) {
if (tree == null ||
excludeTags.contains(treeUtil.nameFromTag(tree.getTag()))) {
return;
}
Info self = new Info(tree, endPosTable);
check(!mandatoryType(tree) ||
(tree.type != null &&
checkFields(tree)),
"'null' found in tree ",
self);
Info prevEncl = encl;
encl = self;
tree.accept(this);
encl = prevEncl;
}
private boolean mandatoryType(JCTree that) {
return that instanceof JCTree.JCExpression ||
that.getTag() == JCTree.VARDEF ||
that.getTag() == JCTree.METHODDEF ||
that.getTag() == JCTree.CLASSDEF;
}
private final List<String> excludedFields = Arrays.asList("varargsElement");
void check(boolean ok, String label, Info self) {
if (!ok) {
if (gui) {
if (viewer == null)
viewer = new Viewer();
viewer.addEntry(sourcefile, label, encl, self);
}
error(label + self.toString() + " encl: " + encl.toString() + " in file: " + sourcefile + " " + self.tree);
}
}
boolean checkFields(JCTree t) {
List<Field> fieldsToCheck = treeUtil.getFieldsOfType(t,
excludedFields,
Symbol.class,
Type.class);
for (Field f : fieldsToCheck) {
try {
if (f.get(t) == null) {
return false;
}
}
catch (IllegalAccessException e) {
System.err.println("Cannot read field: " + f);
//swallow it
}
}
return true;
}
@Override
public void visitImport(JCImport tree) { }
@Override
public void visitTopLevel(JCCompilationUnit tree) {
scan(tree.defs);
}
JavaFileObject sourcefile;
Map<JCTree, Integer> endPosTable;
Info encl;
}
/**
* Utility class providing easy access to position and other info for a tree node.
*/
private class Info {
Info() {
tree = null;
tag = JCTree.ERRONEOUS;
start = 0;
pos = 0;
end = Integer.MAX_VALUE;
}
Info(JCTree tree, Map<JCTree, Integer> endPosTable) {
this.tree = tree;
tag = tree.getTag();
start = TreeInfo.getStartPos(tree);
pos = tree.pos;
end = TreeInfo.getEndPos(tree, endPosTable);
}
@Override
public String toString() {
return treeUtil.nameFromTag(tree.getTag()) + "[start:" + start + ",pos:" + pos + ",end:" + end + "]";
}
final JCTree tree;
final int tag;
final int start;
final int pos;
final int end;
}
/**
* Names for tree tags.
* javac does not provide an API to convert tag values to strings, so this class uses
* reflection to determine names of public static final int values in JCTree.
*/
private static class TreeUtil {
String nameFromTag(int tag) {
if (names == null) {
names = new HashMap<Integer, String>();
Class c = JCTree.class;
for (Field f : c.getDeclaredFields()) {
if (f.getType().equals(int.class)) {
int mods = f.getModifiers();
if (Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) {
try {
names.put(f.getInt(null), f.getName());
} catch (IllegalAccessException e) {
}
}
}
}
}
String name = names.get(tag);
return (name == null) ? "??" : name;
}
List<Field> getFieldsOfType(JCTree t, List<String> excludeNames, Class<?>... types) {
List<Field> buf = new ArrayList<Field>();
for (Field f : t.getClass().getDeclaredFields()) {
if (!excludeNames.contains(f.getName())) {
for (Class<?> type : types) {
if (type.isAssignableFrom(f.getType())) {
f.setAccessible(true);
buf.add(f);
break;
}
}
}
}
return buf;
}
private Map<Integer, String> names;
}
/**
* Thrown when errors are found parsing a java file.
*/
private static class ParseException extends Exception {
ParseException(String msg) {
super(msg);
}
}
private static class AttributionException extends Exception {
AttributionException(String msg) {
super(msg);
}
}
/**
* DiagnosticListener to report diagnostics and count any errors that occur.
*/
private static class Reporter implements DiagnosticListener<JavaFileObject> {
Reporter(PrintWriter out) {
this.out = out;
}
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
out.println(diagnostic);
switch (diagnostic.getKind()) {
case ERROR:
errors++;
}
}
int errors;
PrintWriter out;
}
/**
* GUI viewer for issues found by TreePosTester. The viewer provides a drop
* down list for selecting error conditions, a header area providing details
* about an error, and a text area with the ranges of text highlighted as
* appropriate.
*/
private class Viewer extends JFrame {
/**
* Create a viewer.
*/
Viewer() {
initGUI();
}
/**
* Add another entry to the list of errors.
* @param file The file containing the error
* @param check The condition that was being tested, and which failed
* @param encl the enclosing tree node
* @param self the tree node containing the error
*/
void addEntry(JavaFileObject file, String check, Info encl, Info self) {
Entry e = new Entry(file, check, encl, self);
DefaultComboBoxModel m = (DefaultComboBoxModel) entries.getModel();
m.addElement(e);
if (m.getSize() == 1)
entries.setSelectedItem(e);
}
/**
* Initialize the GUI window.
*/
private void initGUI() {
JPanel head = new JPanel(new GridBagLayout());
GridBagConstraints lc = new GridBagConstraints();
GridBagConstraints fc = new GridBagConstraints();
fc.anchor = GridBagConstraints.WEST;
fc.fill = GridBagConstraints.HORIZONTAL;
fc.gridwidth = GridBagConstraints.REMAINDER;
entries = new JComboBox();
entries.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showEntry((Entry) entries.getSelectedItem());
}
});
fc.insets.bottom = 10;
head.add(entries, fc);
fc.insets.bottom = 0;
head.add(new JLabel("check:"), lc);
head.add(checkField = createTextField(80), fc);
fc.fill = GridBagConstraints.NONE;
head.add(setBackground(new JLabel("encl:"), enclColor), lc);
head.add(enclPanel = new InfoPanel(), fc);
head.add(setBackground(new JLabel("self:"), selfColor), lc);
head.add(selfPanel = new InfoPanel(), fc);
add(head, BorderLayout.NORTH);
body = new JTextArea();
body.setFont(Font.decode(Font.MONOSPACED));
body.addCaretListener(new CaretListener() {
public void caretUpdate(CaretEvent e) {
int dot = e.getDot();
int mark = e.getMark();
if (dot == mark)
statusText.setText("dot: " + dot);
else
statusText.setText("dot: " + dot + ", mark:" + mark);
}
});
JScrollPane p = new JScrollPane(body,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
p.setPreferredSize(new Dimension(640, 480));
add(p, BorderLayout.CENTER);
statusText = createTextField(80);
add(statusText, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null); // centered on screen
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
/** Show an entry that has been selected. */
private void showEntry(Entry e) {
try {
// update simple fields
setTitle(e.file.getName());
checkField.setText(e.check);
enclPanel.setInfo(e.encl);
selfPanel.setInfo(e.self);
// show file text with highlights
body.setText(e.file.getCharContent(true).toString());
Highlighter highlighter = body.getHighlighter();
highlighter.removeAllHighlights();
addHighlight(highlighter, e.encl, enclColor);
addHighlight(highlighter, e.self, selfColor);
scroll(body, getMinPos(enclPanel.info, selfPanel.info));
} catch (IOException ex) {
body.setText("Cannot read " + e.file.getName() + ": " + e);
}
}
/** Create a test field. */
private JTextField createTextField(int width) {
JTextField f = new JTextField(width);
f.setEditable(false);
f.setBorder(null);
return f;
}
/** Add a highlighted region based on the positions in an Info object. */
private void addHighlight(Highlighter h, Info info, Color c) {
int start = info.start;
int end = info.end;
if (start == -1 && end == -1)
return;
if (start == -1)
start = end;
if (end == -1)
end = start;
try {
h.addHighlight(info.start, info.end,
new DefaultHighlighter.DefaultHighlightPainter(c));
if (info.pos != -1) {
Color c2 = new Color(c.getRed(), c.getGreen(), c.getBlue(), (int)(.4f * 255)); // 40%
h.addHighlight(info.pos, info.pos + 1,
new DefaultHighlighter.DefaultHighlightPainter(c2));
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
/** Get the minimum valid position in a set of info objects. */
private int getMinPos(Info... values) {
int i = Integer.MAX_VALUE;
for (Info info: values) {
if (info.start >= 0) i = Math.min(i, info.start);
if (info.pos >= 0) i = Math.min(i, info.pos);
if (info.end >= 0) i = Math.min(i, info.end);
}
return (i == Integer.MAX_VALUE) ? 0 : i;
}
/** Set the background on a component. */
private JComponent setBackground(JComponent comp, Color c) {
comp.setOpaque(true);
comp.setBackground(c);
return comp;
}
/** Scroll a text area to display a given position near the middle of the visible area. */
private void scroll(final JTextArea t, final int pos) {
// Using invokeLater appears to give text a chance to sort itself out
// before the scroll happens; otherwise scrollRectToVisible doesn't work.
// Maybe there's a better way to sync with the text...
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Rectangle r = t.modelToView(pos);
JScrollPane p = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, t);
r.y = Math.max(0, r.y - p.getHeight() * 2 / 5);
r.height += p.getHeight() * 4 / 5;
t.scrollRectToVisible(r);
} catch (BadLocationException ignore) {
}
}
});
}
private JComboBox entries;
private JTextField checkField;
private InfoPanel enclPanel;
private InfoPanel selfPanel;
private JTextArea body;
private JTextField statusText;
private Color selfColor = new Color(0.f, 1.f, 0.f, 0.2f); // 20% green
private Color enclColor = new Color(1.f, 0.f, 0.f, 0.2f); // 20% red
/** Panel to display an Info object. */
private class InfoPanel extends JPanel {
InfoPanel() {
add(tagName = createTextField(20));
add(new JLabel("start:"));
add(addListener(start = createTextField(6)));
add(new JLabel("pos:"));
add(addListener(pos = createTextField(6)));
add(new JLabel("end:"));
add(addListener(end = createTextField(6)));
}
void setInfo(Info info) {
this.info = info;
tagName.setText(treeUtil.nameFromTag(info.tag));
start.setText(String.valueOf(info.start));
pos.setText(String.valueOf(info.pos));
end.setText(String.valueOf(info.end));
}
JTextField addListener(final JTextField f) {
f.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
body.setCaretPosition(Integer.valueOf(f.getText()));
body.getCaret().setVisible(true);
}
});
return f;
}
Info info;
JTextField tagName;
JTextField start;
JTextField pos;
JTextField end;
}
/** Object to record information about an error to be displayed. */
private class Entry {
Entry(JavaFileObject file, String check, Info encl, Info self) {
this.file = file;
this.check = check;
this.encl = encl;
this.self= self;
}
@Override
public String toString() {
return file.getName() + " " + check + " " + getMinPos(encl, self);
}
final JavaFileObject file;
final String check;
final Info encl;
final Info self;
}
}
}

View File

@ -0,0 +1,10 @@
/*
* @test /nodynamiccopyright/
* @bug 6970584
* @summary Flow.java should be more error-friendly
* @author mcimadamore
*
* @compile/fail/ref=FailOver01.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver01.java
*/
class Test { { x = "" } }

View File

@ -0,0 +1,3 @@
FailOver01.java:10:22: compiler.err.expected: ';'
FailOver01.java:10:16: compiler.err.cant.resolve.location: kindname.variable, x, , , kindname.class, Test
2 errors

View File

@ -0,0 +1,14 @@
/*
* @test /nodynamiccopyright/
* @bug 6970584
* @summary Flow.java should be more error-friendly
* @author mcimadamore
*
* @compile/fail/ref=FailOver02.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver02.java
*/
class Test implements AutoCloseable {
void test() {
try(Test t = null) {}
}
}

View File

@ -0,0 +1,3 @@
FailOver02.java:10:1: compiler.err.does.not.override.abstract: Test, close(), java.lang.AutoCloseable
FailOver02.java:12:9: compiler.err.cant.resolve.location.args: kindname.method, close, , , kindname.class, Test
2 errors

View File

@ -0,0 +1,12 @@
/*
* @test /nodynamiccopyright/
* @bug 6970584
* @summary Flow.java should be more error-friendly
* @author mcimadamore
*
* @compile/fail/ref=FailOver03.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver03.java
*/
class Test extends Test {
Test i;
}

View File

@ -0,0 +1,2 @@
FailOver03.java:10:1: compiler.err.cyclic.inheritance: Test
1 error

View File

@ -0,0 +1,12 @@
/*
* @test /nodynamiccopyright/
* @bug 6970584
* @summary Flow.java should be more error-friendly
* @author mcimadamore
*
* @compile/fail/ref=FailOver04.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver04.java
*/
class Test {
{ new Unknown() {}; }
}

View File

@ -0,0 +1,2 @@
FailOver04.java:11:10: compiler.err.cant.resolve.location: kindname.class, Unknown, , , kindname.class, Test
1 error

View File

@ -0,0 +1,12 @@
/*
* @test /nodynamiccopyright/
* @bug 6970584
* @summary Flow.java should be more error-friendly
* @author mcimadamore
*
* @compile/fail/ref=FailOver05.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver05.java
*/
class Test extends Test {
{ for ( Integer x : null) {} }
}

View File

@ -0,0 +1,2 @@
FailOver05.java:10:1: compiler.err.cyclic.inheritance: Test
1 error

View File

@ -0,0 +1,13 @@
/*
* @test /nodynamiccopyright/
* @bug 6970584
* @summary Flow.java should be more error-friendly
* @author mcimadamore
*
* @compile/fail/ref=FailOver06.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver06.java
*/
class Test extends Test {
Inference x = 1;
{ if (x == 1) { } else { } }
}

View File

@ -0,0 +1,2 @@
FailOver06.java:10:1: compiler.err.cyclic.inheritance: Test
1 error

View File

@ -0,0 +1,13 @@
/*
* @test /nodynamiccopyright/
* @bug 6970584
* @summary Flow.java should be more error-friendly
* @author mcimadamore
*
* @compile/fail/ref=FailOver07.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver07.java
*/
class Test extends Test {
Integer x = 1;
{ do {} while (x); }
}

View File

@ -0,0 +1,2 @@
FailOver07.java:10:1: compiler.err.cyclic.inheritance: Test
1 error

View File

@ -0,0 +1,13 @@
/*
* @test /nodynamiccopyright/
* @bug 6970584
* @summary Flow.java should be more error-friendly
* @author mcimadamore
*
* @compile/fail/ref=FailOver08.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver08.java
*/
class Test extends Test {
Integer x = 1;
{ while (x) {}; }
}

View File

@ -0,0 +1,2 @@
FailOver08.java:10:1: compiler.err.cyclic.inheritance: Test
1 error

View File

@ -0,0 +1,13 @@
/*
* @test /nodynamiccopyright/
* @bug 6970584
* @summary Flow.java should be more error-friendly
* @author mcimadamore
*
* @compile/fail/ref=FailOver09.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver09.java
*/
class Test extends Test {
Integer x = 1;
{ for (x = 0 ; x ; x++) {}; }
}

View File

@ -0,0 +1,2 @@
FailOver09.java:10:1: compiler.err.cyclic.inheritance: Test
1 error

View File

@ -0,0 +1,15 @@
/*
* @test /nodynamiccopyright/
* @bug 6970584
* @summary Flow.java should be more error-friendly
* @author mcimadamore
*
* @compile/fail/ref=FailOver10.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver10.java
*/
class Test extends Test {
boolean cond;
{ Object o = null; }
}

View File

@ -0,0 +1,2 @@
FailOver10.java:10:1: compiler.err.cyclic.inheritance: Test
1 error

Some files were not shown because too many files have changed in this diff Show More