Merge
This commit is contained in:
commit
98b2aad842
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
}
|
||||
|
@ -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()]));
|
||||
}
|
||||
|
@ -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>
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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))
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -80,6 +80,7 @@ public enum OptionName {
|
||||
XMAXERRS("-Xmaxerrs"),
|
||||
XMAXWARNS("-Xmaxwarns"),
|
||||
XSTDOUT("-Xstdout"),
|
||||
XPKGINFO("-Xpkginfo:"),
|
||||
XPRINT("-Xprint"),
|
||||
XPRINTROUNDS("-XprintRounds"),
|
||||
XPRINTPROCESSORINFO("-XprintProcessorInfo"),
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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) \
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
@ -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());
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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)) {
|
||||
|
@ -99,7 +99,10 @@ public class SourceWriter extends InstructionDetailWriter {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasSource() {
|
||||
return (sourceLines.length > 0);
|
||||
}
|
||||
|
||||
private void setLineMap(Code_attribute attr) {
|
||||
|
@ -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™ 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
//...
|
||||
//...
|
||||
//...
|
||||
//...
|
||||
//...
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
TestCast6979683_BAD34.java:34:49: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Number, boolean
|
||||
1 error
|
@ -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
|
||||
//...
|
||||
//...
|
||||
//...
|
||||
//...
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
TestCast6979683_BAD35.java:35:45: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Number, int
|
||||
1 error
|
@ -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
|
||||
//...
|
||||
//...
|
||||
//...
|
||||
}
|
@ -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
|
@ -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
|
||||
//...
|
||||
//...
|
||||
}
|
@ -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
|
@ -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
|
||||
//...
|
||||
}
|
@ -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
|
@ -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
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
TestCast6979683_BAD39.java:39:53: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), java.lang.Number, char
|
||||
1 error
|
111
langtools/test/tools/javac/6979683/TestCast6979683_GOOD.java
Normal file
111
langtools/test/tools/javac/6979683/TestCast6979683_GOOD.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
||||
/*
|
||||
|
62
langtools/test/tools/javac/T6458749.java
Normal file
62
langtools/test/tools/javac/T6458749.java
Normal 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();
|
||||
}
|
||||
}
|
55
langtools/test/tools/javac/T6458823/MyProcessor.java
Normal file
55
langtools/test/tools/javac/T6458823/MyProcessor.java
Normal 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();
|
||||
}
|
||||
}
|
87
langtools/test/tools/javac/T6458823/T6458823.java
Normal file
87
langtools/test/tools/javac/T6458823/T6458823.java
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
25
langtools/test/tools/javac/T6458823/TestClass.java
Normal file
25
langtools/test/tools/javac/T6458823/TestClass.java
Normal 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> {
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
50
langtools/test/tools/javac/T6900149.java
Normal file
50
langtools/test/tools/javac/T6900149.java
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
126
langtools/test/tools/javac/T6956462/T6956462.java
Normal file
126
langtools/test/tools/javac/T6956462/T6956462.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
30
langtools/test/tools/javac/T6956462/TestClass.java
Normal file
30
langtools/test/tools/javac/T6956462/TestClass.java
Normal 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;
|
||||
}
|
||||
}
|
86
langtools/test/tools/javac/T6985181.java
Normal file
86
langtools/test/tools/javac/T6985181.java
Normal 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;
|
||||
}
|
||||
}
|
174
langtools/test/tools/javac/TestPkgInfo.java
Normal file
174
langtools/test/tools/javac/TestPkgInfo.java
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
216
langtools/test/tools/javac/api/TestContainTypes.java
Normal file
216
langtools/test/tools/javac/api/TestContainTypes.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
235
langtools/test/tools/javac/api/TestGetElement.java
Normal file
235
langtools/test/tools/javac/api/TestGetElement.java
Normal 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
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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); }
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
775
langtools/test/tools/javac/failover/CheckAttributedTree.java
Normal file
775
langtools/test/tools/javac/failover/CheckAttributedTree.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
10
langtools/test/tools/javac/failover/FailOver01.java
Normal file
10
langtools/test/tools/javac/failover/FailOver01.java
Normal 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 = "" } }
|
3
langtools/test/tools/javac/failover/FailOver01.out
Normal file
3
langtools/test/tools/javac/failover/FailOver01.out
Normal 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
|
14
langtools/test/tools/javac/failover/FailOver02.java
Normal file
14
langtools/test/tools/javac/failover/FailOver02.java
Normal 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) {}
|
||||
}
|
||||
}
|
3
langtools/test/tools/javac/failover/FailOver02.out
Normal file
3
langtools/test/tools/javac/failover/FailOver02.out
Normal 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
|
12
langtools/test/tools/javac/failover/FailOver03.java
Normal file
12
langtools/test/tools/javac/failover/FailOver03.java
Normal 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;
|
||||
}
|
2
langtools/test/tools/javac/failover/FailOver03.out
Normal file
2
langtools/test/tools/javac/failover/FailOver03.out
Normal file
@ -0,0 +1,2 @@
|
||||
FailOver03.java:10:1: compiler.err.cyclic.inheritance: Test
|
||||
1 error
|
12
langtools/test/tools/javac/failover/FailOver04.java
Normal file
12
langtools/test/tools/javac/failover/FailOver04.java
Normal 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() {}; }
|
||||
}
|
2
langtools/test/tools/javac/failover/FailOver04.out
Normal file
2
langtools/test/tools/javac/failover/FailOver04.out
Normal file
@ -0,0 +1,2 @@
|
||||
FailOver04.java:11:10: compiler.err.cant.resolve.location: kindname.class, Unknown, , , kindname.class, Test
|
||||
1 error
|
12
langtools/test/tools/javac/failover/FailOver05.java
Normal file
12
langtools/test/tools/javac/failover/FailOver05.java
Normal 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) {} }
|
||||
}
|
2
langtools/test/tools/javac/failover/FailOver05.out
Normal file
2
langtools/test/tools/javac/failover/FailOver05.out
Normal file
@ -0,0 +1,2 @@
|
||||
FailOver05.java:10:1: compiler.err.cyclic.inheritance: Test
|
||||
1 error
|
13
langtools/test/tools/javac/failover/FailOver06.java
Normal file
13
langtools/test/tools/javac/failover/FailOver06.java
Normal 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 { } }
|
||||
}
|
2
langtools/test/tools/javac/failover/FailOver06.out
Normal file
2
langtools/test/tools/javac/failover/FailOver06.out
Normal file
@ -0,0 +1,2 @@
|
||||
FailOver06.java:10:1: compiler.err.cyclic.inheritance: Test
|
||||
1 error
|
13
langtools/test/tools/javac/failover/FailOver07.java
Normal file
13
langtools/test/tools/javac/failover/FailOver07.java
Normal 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); }
|
||||
}
|
2
langtools/test/tools/javac/failover/FailOver07.out
Normal file
2
langtools/test/tools/javac/failover/FailOver07.out
Normal file
@ -0,0 +1,2 @@
|
||||
FailOver07.java:10:1: compiler.err.cyclic.inheritance: Test
|
||||
1 error
|
13
langtools/test/tools/javac/failover/FailOver08.java
Normal file
13
langtools/test/tools/javac/failover/FailOver08.java
Normal 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) {}; }
|
||||
}
|
2
langtools/test/tools/javac/failover/FailOver08.out
Normal file
2
langtools/test/tools/javac/failover/FailOver08.out
Normal file
@ -0,0 +1,2 @@
|
||||
FailOver08.java:10:1: compiler.err.cyclic.inheritance: Test
|
||||
1 error
|
13
langtools/test/tools/javac/failover/FailOver09.java
Normal file
13
langtools/test/tools/javac/failover/FailOver09.java
Normal 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++) {}; }
|
||||
}
|
2
langtools/test/tools/javac/failover/FailOver09.out
Normal file
2
langtools/test/tools/javac/failover/FailOver09.out
Normal file
@ -0,0 +1,2 @@
|
||||
FailOver09.java:10:1: compiler.err.cyclic.inheritance: Test
|
||||
1 error
|
15
langtools/test/tools/javac/failover/FailOver10.java
Normal file
15
langtools/test/tools/javac/failover/FailOver10.java
Normal 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; }
|
||||
}
|
2
langtools/test/tools/javac/failover/FailOver10.out
Normal file
2
langtools/test/tools/javac/failover/FailOver10.out
Normal 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
Loading…
Reference in New Issue
Block a user