feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,249 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.code;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.lang.model.AnnotatedConstruct;
import com.sun.tools.javac.model.AnnotationProxyMaker;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
/**
* Common super type for annotated constructs such as Types and Symbols.
*
* This class should *not* contain any fields since it would have a significant
* impact on the javac memory footprint.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
public abstract class AnnoConstruct implements AnnotatedConstruct {
// Override to enforce a narrower return type.
@Override
public abstract List<? extends Attribute.Compound> getAnnotationMirrors();
// This method is part of the javax.lang.model API, do not use this in javac code.
protected <A extends Annotation> Attribute.Compound getAttribute(Class<A> annoType) {
String name = annoType.getName();
for (Attribute.Compound anno : getAnnotationMirrors()) {
if (name.equals(anno.type.tsym.flatName().toString()))
return anno;
}
return null;
}
@SuppressWarnings("unchecked")
protected <A extends Annotation> A[] getInheritedAnnotations(Class<A> annoType) {
return (A[]) java.lang.reflect.Array.newInstance(annoType, 0); // annoType is the Class for A
}
// This method is part of the javax.lang.model API, do not use this in javac code.
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annoType) {
if (!annoType.isAnnotation())
throw new IllegalArgumentException("Not an annotation type: "
+ annoType);
// If annoType does not declare a container this is equivalent to wrapping
// getAnnotation(...) in an array.
Class <? extends Annotation> containerType = getContainer(annoType);
if (containerType == null) {
A res = getAnnotation(annoType);
int size = res == null ? 0 : 1;
@SuppressWarnings("unchecked") // annoType is the Class for A
A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size);
if (res != null)
arr[0] = res;
return arr;
}
// So we have a containing type
String annoTypeName = annoType.getName();
String containerTypeName = containerType.getName();
int directIndex = -1, containerIndex = -1;
Attribute.Compound direct = null, container = null;
// Find directly (explicit or implicit) present annotations
int index = -1;
for (Attribute.Compound attribute : getAnnotationMirrors()) {
index++;
if (attribute.type.tsym.flatName().contentEquals(annoTypeName)) {
directIndex = index;
direct = attribute;
} else if(containerTypeName != null &&
attribute.type.tsym.flatName().contentEquals(containerTypeName)) {
containerIndex = index;
container = attribute;
}
}
// Deal with inherited annotations
if (direct == null && container == null &&
annoType.isAnnotationPresent(Inherited.class))
return getInheritedAnnotations(annoType);
Attribute.Compound[] contained = unpackContained(container);
// In case of an empty legacy container we might need to look for
// inherited annos as well
if (direct == null && contained.length == 0 &&
annoType.isAnnotationPresent(Inherited.class))
return getInheritedAnnotations(annoType);
int size = (direct == null ? 0 : 1) + contained.length;
@SuppressWarnings("unchecked") // annoType is the Class for A
A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size);
// if direct && container, which is first?
int insert = -1;
int length = arr.length;
if (directIndex >= 0 && containerIndex >= 0) {
if (directIndex < containerIndex) {
arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
insert = 1;
} else {
arr[arr.length - 1] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
insert = 0;
length--;
}
} else if (directIndex >= 0) {
arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
return arr;
} else {
// Only container
insert = 0;
}
for (int i = 0; i + insert < length; i++)
arr[insert + i] = AnnotationProxyMaker.generateAnnotation(contained[i], annoType);
return arr;
}
private Attribute.Compound[] unpackContained(Attribute.Compound container) {
// Pack them in an array
Attribute[] contained0 = null;
if (container != null)
contained0 = unpackAttributes(container);
ListBuffer<Attribute.Compound> compounds = new ListBuffer<>();
if (contained0 != null) {
for (Attribute a : contained0)
if (a instanceof Attribute.Compound)
compounds = compounds.append((Attribute.Compound)a);
}
return compounds.toArray(new Attribute.Compound[compounds.size()]);
}
// This method is part of the javax.lang.model API, do not use this in javac code.
public <A extends Annotation> A getAnnotation(Class<A> annoType) {
if (!annoType.isAnnotation())
throw new IllegalArgumentException("Not an annotation type: " + annoType);
Attribute.Compound c = getAttribute(annoType);
return c == null ? null : AnnotationProxyMaker.generateAnnotation(c, annoType);
}
// Needed to unpack the runtime view of containing annotations
private static final Class<? extends Annotation> REPEATABLE_CLASS = initRepeatable();
private static final Method VALUE_ELEMENT_METHOD = initValueElementMethod();
private static Class<? extends Annotation> initRepeatable() {
try {
// Repeatable will not be available when bootstrapping on
// JDK 7 so use a reflective lookup instead of a class
// literal for Repeatable.class.
return Class.forName("java.lang.annotation.Repeatable").asSubclass(Annotation.class);
} catch (ClassNotFoundException | SecurityException e) {
return null;
}
}
private static Method initValueElementMethod() {
if (REPEATABLE_CLASS == null)
return null;
Method m = null;
try {
m = REPEATABLE_CLASS.getMethod("value");
if (m != null)
m.setAccessible(true);
return m;
} catch (NoSuchMethodException e) {
return null;
}
}
// Helper to getAnnotationsByType
private static Class<? extends Annotation> getContainer(Class<? extends Annotation> annoType) {
// Since we can not refer to java.lang.annotation.Repeatable until we are
// bootstrapping with java 8 we need to get the Repeatable annotation using
// reflective invocations instead of just using its type and element method.
if (REPEATABLE_CLASS != null &&
VALUE_ELEMENT_METHOD != null) {
// Get the Repeatable instance on the annotations declaration
Annotation repeatable = (Annotation)annoType.getAnnotation(REPEATABLE_CLASS);
if (repeatable != null) {
try {
// Get the value element, it should be a class
// indicating the containing annotation type
@SuppressWarnings("unchecked")
Class<? extends Annotation> containerType = (Class)VALUE_ELEMENT_METHOD.invoke(repeatable);
if (containerType == null)
return null;
return containerType;
} catch (ClassCastException | IllegalAccessException | InvocationTargetException e) {
return null;
}
}
}
return null;
}
// Helper to getAnnotationsByType
private static Attribute[] unpackAttributes(Attribute.Compound container) {
// We now have an instance of the container,
// unpack it returning an instance of the
// contained type or null
return ((Attribute.Array)container.member(container.type.tsym.name.table.names.value)).values;
}
}

View File

@@ -0,0 +1,401 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.code;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.AnnotationValueVisitor;
import javax.lang.model.type.DeclaredType;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.util.*;
/** An annotation value.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public abstract class Attribute implements AnnotationValue {
/** The type of the annotation element. */
public Type type;
public Attribute(Type type) {
this.type = type;
}
public abstract void accept(Visitor v);
public Object getValue() {
throw new UnsupportedOperationException();
}
public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
throw new UnsupportedOperationException();
}
public boolean isSynthesized() {
return false;
}
public TypeAnnotationPosition getPosition() { return null; };
/** The value for an annotation element of primitive type or String. */
public static class Constant extends Attribute {
public final Object value;
public void accept(Visitor v) { v.visitConstant(this); }
public Constant(Type type, Object value) {
super(type);
this.value = value;
}
public String toString() {
return Constants.format(value, type);
}
public Object getValue() {
return Constants.decode(value, type);
}
public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
if (value instanceof String)
return v.visitString((String) value, p);
if (value instanceof Integer) {
int i = (Integer) value;
switch (type.getTag()) {
case BOOLEAN: return v.visitBoolean(i != 0, p);
case CHAR: return v.visitChar((char) i, p);
case BYTE: return v.visitByte((byte) i, p);
case SHORT: return v.visitShort((short) i, p);
case INT: return v.visitInt(i, p);
}
}
switch (type.getTag()) {
case LONG: return v.visitLong((Long) value, p);
case FLOAT: return v.visitFloat((Float) value, p);
case DOUBLE: return v.visitDouble((Double) value, p);
}
throw new AssertionError("Bad annotation element value: " + value);
}
}
/** The value for an annotation element of type java.lang.Class,
* represented as a ClassSymbol.
*/
public static class Class extends Attribute {
public final Type classType;
public void accept(Visitor v) { v.visitClass(this); }
public Class(Types types, Type type) {
super(makeClassType(types, type));
this.classType = type;
}
static Type makeClassType(Types types, Type type) {
Type arg = type.isPrimitive()
? types.boxedClass(type).type
: types.erasure(type);
return new Type.ClassType(types.syms.classType.getEnclosingType(),
List.of(arg),
types.syms.classType.tsym);
}
public String toString() {
return classType + ".class";
}
public Type getValue() {
return classType;
}
public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
return v.visitType(classType, p);
}
}
/** A compound annotation element value, the type of which is an
* attribute interface.
*/
public static class Compound extends Attribute implements AnnotationMirror {
/** The attributes values, as pairs. Each pair contains a
* reference to the accessing method in the attribute interface
* and the value to be returned when that method is called to
* access this attribute.
*/
public final List<Pair<MethodSymbol,Attribute>> values;
private boolean synthesized = false;
@Override
public boolean isSynthesized() {
return synthesized;
}
public void setSynthesized(boolean synthesized) {
this.synthesized = synthesized;
}
public Compound(Type type,
List<Pair<MethodSymbol,Attribute>> values) {
super(type);
this.values = values;
}
public void accept(Visitor v) { v.visitCompound(this); }
/**
* Returns a string representation of this annotation.
* String is of one of the forms:
* @com.example.foo(name1=val1, name2=val2)
* @com.example.foo(val)
* @com.example.foo
* Omit parens for marker annotations, and omit "value=" when allowed.
*/
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("@");
buf.append(type);
int len = values.length();
if (len > 0) {
buf.append('(');
boolean first = true;
for (Pair<MethodSymbol, Attribute> value : values) {
if (!first) buf.append(", ");
first = false;
Name name = value.fst.name;
if (len > 1 || name != name.table.names.value) {
buf.append(name);
buf.append('=');
}
buf.append(value.snd);
}
buf.append(')');
}
return buf.toString();
}
public Attribute member(Name member) {
Pair<MethodSymbol,Attribute> res = getElemPair(member);
return res == null ? null : res.snd;
}
private Pair<MethodSymbol, Attribute> getElemPair(Name member) {
for (Pair<MethodSymbol,Attribute> pair : values)
if (pair.fst.name == member) return pair;
return null;
}
public Attribute.Compound getValue() {
return this;
}
public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
return v.visitAnnotation(this, p);
}
public DeclaredType getAnnotationType() {
return (DeclaredType) type;
}
@Override
public TypeAnnotationPosition getPosition() {
if (values.size() != 0) {
Name valueName = values.head.fst.name.table.names.value;
Pair<MethodSymbol, Attribute> res = getElemPair(valueName);
return res == null ? null : res.snd.getPosition();
}
return null;
}
public Map<MethodSymbol, Attribute> getElementValues() {
Map<MethodSymbol, Attribute> valmap =
new LinkedHashMap<MethodSymbol, Attribute>();
for (Pair<MethodSymbol, Attribute> value : values)
valmap.put(value.fst, value.snd);
return valmap;
}
}
public static class TypeCompound extends Compound {
public TypeAnnotationPosition position;
public TypeCompound(Compound compound,
TypeAnnotationPosition position) {
this(compound.type, compound.values, position);
}
public TypeCompound(Type type,
List<Pair<MethodSymbol, Attribute>> values,
TypeAnnotationPosition position) {
super(type, values);
this.position = position;
}
@Override
public TypeAnnotationPosition getPosition() {
if (hasUnknownPosition()) {
position = super.getPosition();
}
return position;
}
public boolean hasUnknownPosition() {
return position.type == TargetType.UNKNOWN;
}
public boolean isContainerTypeCompound() {
if (isSynthesized() && values.size() == 1)
return getFirstEmbeddedTC() != null;
return false;
}
private TypeCompound getFirstEmbeddedTC() {
if (values.size() == 1) {
Pair<MethodSymbol, Attribute> val = values.get(0);
if (val.fst.getSimpleName().contentEquals("value")
&& val.snd instanceof Array) {
Array arr = (Array) val.snd;
if (arr.values.length != 0
&& arr.values[0] instanceof Attribute.TypeCompound)
return (Attribute.TypeCompound) arr.values[0];
}
}
return null;
}
public boolean tryFixPosition() {
if (!isContainerTypeCompound())
return false;
TypeCompound from = getFirstEmbeddedTC();
if (from != null && from.position != null &&
from.position.type != TargetType.UNKNOWN) {
position = from.position;
return true;
}
return false;
}
}
/** The value for an annotation element of an array type.
*/
public static class Array extends Attribute {
public final Attribute[] values;
public Array(Type type, Attribute[] values) {
super(type);
this.values = values;
}
public Array(Type type, List<Attribute> values) {
super(type);
this.values = values.toArray(new Attribute[values.size()]);
}
public void accept(Visitor v) { v.visitArray(this); }
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append('{');
boolean first = true;
for (Attribute value : values) {
if (!first)
buf.append(", ");
first = false;
buf.append(value);
}
buf.append('}');
return buf.toString();
}
public List<Attribute> getValue() {
return List.from(values);
}
public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
return v.visitArray(getValue(), p);
}
@Override
public TypeAnnotationPosition getPosition() {
if (values.length != 0)
return values[0].getPosition();
else
return null;
}
}
/** The value for an annotation element of an enum type.
*/
public static class Enum extends Attribute {
public VarSymbol value;
public Enum(Type type, VarSymbol value) {
super(type);
this.value = Assert.checkNonNull(value);
}
public void accept(Visitor v) { v.visitEnum(this); }
public String toString() {
return value.enclClass() + "." + value; // qualified name
}
public VarSymbol getValue() {
return value;
}
public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
return v.visitEnumConstant(value, p);
}
}
public static class Error extends Attribute {
public Error(Type type) {
super(type);
}
public void accept(Visitor v) { v.visitError(this); }
public String toString() {
return "<error>";
}
public String getValue() {
return toString();
}
public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
return v.visitString(toString(), p);
}
}
public static class UnresolvedClass extends Error {
public Type classType;
public UnresolvedClass(Type type, Type classType) {
super(type);
this.classType = classType;
}
}
/** A visitor type for dynamic dispatch on the kind of attribute value. */
public static interface Visitor {
void visitConstant(Attribute.Constant value);
void visitClass(Attribute.Class clazz);
void visitCompound(Attribute.Compound compound);
void visitArray(Attribute.Array array);
void visitEnum(Attribute.Enum e);
void visitError(Attribute.Error e);
}
/** A mirror of java.lang.annotation.RetentionPolicy. */
public static enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2003, 2005, 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.code;
/**
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public enum BoundKind {
EXTENDS("? extends "),
SUPER("? super "),
UNBOUND("?");
private final String name;
BoundKind(String name) {
this.name = name;
}
public String toString() { return name; }
}

View File

@@ -0,0 +1,144 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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.code;
import java.util.HashMap;
import java.util.Map;
import com.sun.tools.javac.tree.EndPosTable;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.ListBuffer;
/**
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class DeferredLintHandler {
protected static final Context.Key<DeferredLintHandler> deferredLintHandlerKey =
new Context.Key<DeferredLintHandler>();
public static DeferredLintHandler instance(Context context) {
DeferredLintHandler instance = context.get(deferredLintHandlerKey);
if (instance == null)
instance = new DeferredLintHandler(context);
return instance;
}
protected DeferredLintHandler(Context context) {
context.put(deferredLintHandlerKey, this);
this.currentPos = IMMEDIATE_POSITION;
}
/**An interface for deferred lint reporting - loggers passed to
* {@link #report(LintLogger) } will be called when
* {@link #flush(DiagnosticPosition) } is invoked.
*/
public interface LintLogger {
void report();
}
private DiagnosticPosition currentPos;
private Map<DiagnosticPosition, ListBuffer<LintLogger>> loggersQueue = new HashMap<DiagnosticPosition, ListBuffer<LintLogger>>();
/**Associate the given logger with the current position as set by {@link #setPos(DiagnosticPosition) }.
* Will be invoked when {@link #flush(DiagnosticPosition) } will be invoked with the same position.
* <br>
* Will invoke the logger synchronously if {@link #immediate() } was called
* instead of {@link #setPos(DiagnosticPosition) }.
*/
public void report(LintLogger logger) {
if (currentPos == IMMEDIATE_POSITION) {
logger.report();
} else {
ListBuffer<LintLogger> loggers = loggersQueue.get(currentPos);
if (loggers == null) {
loggersQueue.put(currentPos, loggers = new ListBuffer<>());
}
loggers.append(logger);
}
}
/**Invoke all {@link LintLogger}s that were associated with the provided {@code pos}.
*/
public void flush(DiagnosticPosition pos) {
ListBuffer<LintLogger> loggers = loggersQueue.get(pos);
if (loggers != null) {
for (LintLogger lintLogger : loggers) {
lintLogger.report();
}
loggersQueue.remove(pos);
}
}
/**Sets the current position to the provided {@code currentPos}. {@link LintLogger}s
* passed to subsequent invocations of {@link #report(LintLogger) } will be associated
* with the given position.
*/
public DiagnosticPosition setPos(DiagnosticPosition currentPos) {
DiagnosticPosition prevPosition = this.currentPos;
this.currentPos = currentPos;
return prevPosition;
}
/**{@link LintLogger}s passed to subsequent invocations of
* {@link #report(LintLogger) } will be invoked immediately.
*/
public DiagnosticPosition immediate() {
return setPos(IMMEDIATE_POSITION);
}
private static final DiagnosticPosition IMMEDIATE_POSITION = new DiagnosticPosition() {
@Override
public JCTree getTree() {
Assert.error();
return null;
}
@Override
public int getStartPosition() {
Assert.error();
return -1;
}
@Override
public int getPreferredPosition() {
Assert.error();
return -1;
}
@Override
public int getEndPosition(EndPosTable endPosTable) {
Assert.error();
return -1;
}
};
}

View File

@@ -0,0 +1,411 @@
/*
* Copyright (c) 1999, 2014, 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.code;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.Modifier;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.StringUtils;
/** Access flags and other modifiers for Java classes and members.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class Flags {
private Flags() {} // uninstantiable
public static String toString(long flags) {
StringBuilder buf = new StringBuilder();
String sep = "";
for (Flag flag : asFlagSet(flags)) {
buf.append(sep);
buf.append(flag);
sep = " ";
}
return buf.toString();
}
public static EnumSet<Flag> asFlagSet(long flags) {
EnumSet<Flag> flagSet = EnumSet.noneOf(Flag.class);
for (Flag flag : Flag.values()) {
if ((flags & flag.value) != 0) {
flagSet.add(flag);
flags &= ~flag.value;
}
}
Assert.check(flags == 0, "Flags parameter contains unknown flags " + flags);
return flagSet;
}
/* Standard Java flags.
*/
public static final int PUBLIC = 1;
public static final int PRIVATE = 1<<1;
public static final int PROTECTED = 1<<2;
public static final int STATIC = 1<<3;
public static final int FINAL = 1<<4;
public static final int SYNCHRONIZED = 1<<5;
public static final int VOLATILE = 1<<6;
public static final int TRANSIENT = 1<<7;
public static final int NATIVE = 1<<8;
public static final int INTERFACE = 1<<9;
public static final int ABSTRACT = 1<<10;
public static final int STRICTFP = 1<<11;
/* Flag that marks a symbol synthetic, added in classfile v49.0. */
public static final int SYNTHETIC = 1<<12;
/** Flag that marks attribute interfaces, added in classfile v49.0. */
public static final int ANNOTATION = 1<<13;
/** An enumeration type or an enumeration constant, added in
* classfile v49.0. */
public static final int ENUM = 1<<14;
/** Added in SE8, represents constructs implicitly declared in source. */
public static final int MANDATED = 1<<15;
public static final int StandardFlags = 0x0fff;
// Because the following access flags are overloaded with other
// bit positions, we translate them when reading and writing class
// files into unique bits positions: ACC_SYNTHETIC <-> SYNTHETIC,
// for example.
public static final int ACC_SUPER = 0x0020;
public static final int ACC_BRIDGE = 0x0040;
public static final int ACC_VARARGS = 0x0080;
/*****************************************
* Internal compiler flags (no bits in the lower 16).
*****************************************/
/** Flag is set if symbol is deprecated.
*/
public static final int DEPRECATED = 1<<17;
/** Flag is set for a variable symbol if the variable's definition
* has an initializer part.
*/
public static final int HASINIT = 1<<18;
/** Flag is set for compiler-generated anonymous method symbols
* that `own' an initializer block.
*/
public static final int BLOCK = 1<<20;
/** Flag is set for compiler-generated abstract methods that implement
* an interface method (Miranda methods).
*/
public static final int IPROXY = 1<<21;
/** Flag is set for nested classes that do not access instance members
* or `this' of an outer class and therefore don't need to be passed
* a this$n reference. This value is currently set only for anonymous
* classes in superclass constructor calls and only for pre 1.4 targets.
* todo: use this value for optimizing away this$n parameters in
* other cases.
*/
public static final int NOOUTERTHIS = 1<<22;
/** Flag is set for package symbols if a package has a member or
* directory and therefore exists.
*/
public static final int EXISTS = 1<<23;
/** Flag is set for compiler-generated compound classes
* representing multiple variable bounds
*/
public static final int COMPOUND = 1<<24;
/** Flag is set for class symbols if a class file was found for this class.
*/
public static final int CLASS_SEEN = 1<<25;
/** Flag is set for class symbols if a source file was found for this
* class.
*/
public static final int SOURCE_SEEN = 1<<26;
/* State flags (are reset during compilation).
*/
/** Flag for class symbols is set and later re-set as a lock in
* Enter to detect cycles in the superclass/superinterface
* relations. Similarly for constructor call cycle detection in
* Attr.
*/
public static final int LOCKED = 1<<27;
/** Flag for class symbols is set and later re-set to indicate that a class
* has been entered but has not yet been attributed.
*/
public static final int UNATTRIBUTED = 1<<28;
/** Flag for synthesized default constructors of anonymous classes.
*/
public static final int ANONCONSTR = 1<<29;
/** Flag for class symbols to indicate it has been checked and found
* acyclic.
*/
public static final int ACYCLIC = 1<<30;
/** Flag that marks bridge methods.
*/
public static final long BRIDGE = 1L<<31;
/** Flag that marks formal parameters.
*/
public static final long PARAMETER = 1L<<33;
/** Flag that marks varargs methods.
*/
public static final long VARARGS = 1L<<34;
/** Flag for annotation type symbols to indicate it has been
* checked and found acyclic.
*/
public static final long ACYCLIC_ANN = 1L<<35;
/** Flag that marks a generated default constructor.
*/
public static final long GENERATEDCONSTR = 1L<<36;
/** Flag that marks a hypothetical method that need not really be
* generated in the binary, but is present in the symbol table to
* simplify checking for erasure clashes - also used for 292 poly sig methods.
*/
public static final long HYPOTHETICAL = 1L<<37;
/**
* Flag that marks an internal proprietary class.
*/
public static final long PROPRIETARY = 1L<<38;
/**
* Flag that marks a multi-catch parameter.
*/
public static final long UNION = 1L<<39;
/**
* Flag that marks a special kind of bridge method (the ones that
* come from restricted supertype bounds).
*/
public static final long OVERRIDE_BRIDGE = 1L<<40;
/**
* Flag that marks an 'effectively final' local variable.
*/
public static final long EFFECTIVELY_FINAL = 1L<<41;
/**
* Flag that marks non-override equivalent methods with the same signature.
*/
public static final long CLASH = 1L<<42;
/**
* Flag that marks either a default method or an interface containing default methods.
*/
public static final long DEFAULT = 1L<<43;
/**
* Flag that marks class as auxiliary, ie a non-public class following
* the public class in a source file, that could block implicit compilation.
*/
public static final long AUXILIARY = 1L<<44;
/**
* Flag that marks that a symbol is not available in the current profile
*/
public static final long NOT_IN_PROFILE = 1L<<45;
/**
* Flag that indicates that an override error has been detected by Check.
*/
public static final long BAD_OVERRIDE = 1L<<45;
/**
* Flag that indicates a signature polymorphic method (292).
*/
public static final long SIGNATURE_POLYMORPHIC = 1L<<46;
/**
* Flag that indicates that an inference variable is used in a 'throws' clause.
*/
public static final long THROWS = 1L<<47;
/**
* Flag that marks potentially ambiguous overloads
*/
public static final long POTENTIALLY_AMBIGUOUS = 1L<<48;
/**
* Flag that marks a synthetic method body for a lambda expression
*/
public static final long LAMBDA_METHOD = 1L<<49;
/**
* Flag to control recursion in TransTypes
*/
public static final long TYPE_TRANSLATED = 1L<<50;
/** Modifier masks.
*/
public static final int
AccessFlags = PUBLIC | PROTECTED | PRIVATE,
LocalClassFlags = FINAL | ABSTRACT | STRICTFP | ENUM | SYNTHETIC,
MemberClassFlags = LocalClassFlags | INTERFACE | AccessFlags,
ClassFlags = LocalClassFlags | INTERFACE | PUBLIC | ANNOTATION,
InterfaceVarFlags = FINAL | STATIC | PUBLIC,
VarFlags = AccessFlags | FINAL | STATIC |
VOLATILE | TRANSIENT | ENUM,
ConstructorFlags = AccessFlags,
InterfaceMethodFlags = ABSTRACT | PUBLIC,
MethodFlags = AccessFlags | ABSTRACT | STATIC | NATIVE |
SYNCHRONIZED | FINAL | STRICTFP;
public static final long
ExtendedStandardFlags = (long)StandardFlags | DEFAULT,
ModifierFlags = ((long)StandardFlags & ~INTERFACE) | DEFAULT,
InterfaceMethodMask = ABSTRACT | STATIC | PUBLIC | STRICTFP | DEFAULT,
AnnotationTypeElementMask = ABSTRACT | PUBLIC,
LocalVarFlags = FINAL | PARAMETER,
ReceiverParamFlags = PARAMETER;
public static Set<Modifier> asModifierSet(long flags) {
Set<Modifier> modifiers = modifierSets.get(flags);
if (modifiers == null) {
modifiers = java.util.EnumSet.noneOf(Modifier.class);
if (0 != (flags & PUBLIC)) modifiers.add(Modifier.PUBLIC);
if (0 != (flags & PROTECTED)) modifiers.add(Modifier.PROTECTED);
if (0 != (flags & PRIVATE)) modifiers.add(Modifier.PRIVATE);
if (0 != (flags & ABSTRACT)) modifiers.add(Modifier.ABSTRACT);
if (0 != (flags & STATIC)) modifiers.add(Modifier.STATIC);
if (0 != (flags & FINAL)) modifiers.add(Modifier.FINAL);
if (0 != (flags & TRANSIENT)) modifiers.add(Modifier.TRANSIENT);
if (0 != (flags & VOLATILE)) modifiers.add(Modifier.VOLATILE);
if (0 != (flags & SYNCHRONIZED))
modifiers.add(Modifier.SYNCHRONIZED);
if (0 != (flags & NATIVE)) modifiers.add(Modifier.NATIVE);
if (0 != (flags & STRICTFP)) modifiers.add(Modifier.STRICTFP);
if (0 != (flags & DEFAULT)) modifiers.add(Modifier.DEFAULT);
modifiers = Collections.unmodifiableSet(modifiers);
modifierSets.put(flags, modifiers);
}
return modifiers;
}
// Cache of modifier sets.
private static final Map<Long, Set<Modifier>> modifierSets =
new java.util.concurrent.ConcurrentHashMap<Long, Set<Modifier>>(64);
public static boolean isStatic(Symbol symbol) {
return (symbol.flags() & STATIC) != 0;
}
public static boolean isEnum(Symbol symbol) {
return (symbol.flags() & ENUM) != 0;
}
public static boolean isConstant(Symbol.VarSymbol symbol) {
return symbol.getConstValue() != null;
}
public enum Flag {
PUBLIC(Flags.PUBLIC),
PRIVATE(Flags.PRIVATE),
PROTECTED(Flags.PROTECTED),
STATIC(Flags.STATIC),
FINAL(Flags.FINAL),
SYNCHRONIZED(Flags.SYNCHRONIZED),
VOLATILE(Flags.VOLATILE),
TRANSIENT(Flags.TRANSIENT),
NATIVE(Flags.NATIVE),
INTERFACE(Flags.INTERFACE),
ABSTRACT(Flags.ABSTRACT),
DEFAULT(Flags.DEFAULT),
STRICTFP(Flags.STRICTFP),
BRIDGE(Flags.BRIDGE),
SYNTHETIC(Flags.SYNTHETIC),
ANNOTATION(Flags.ANNOTATION),
DEPRECATED(Flags.DEPRECATED),
HASINIT(Flags.HASINIT),
BLOCK(Flags.BLOCK),
ENUM(Flags.ENUM),
MANDATED(Flags.MANDATED),
IPROXY(Flags.IPROXY),
NOOUTERTHIS(Flags.NOOUTERTHIS),
EXISTS(Flags.EXISTS),
COMPOUND(Flags.COMPOUND),
CLASS_SEEN(Flags.CLASS_SEEN),
SOURCE_SEEN(Flags.SOURCE_SEEN),
LOCKED(Flags.LOCKED),
UNATTRIBUTED(Flags.UNATTRIBUTED),
ANONCONSTR(Flags.ANONCONSTR),
ACYCLIC(Flags.ACYCLIC),
PARAMETER(Flags.PARAMETER),
VARARGS(Flags.VARARGS),
ACYCLIC_ANN(Flags.ACYCLIC_ANN),
GENERATEDCONSTR(Flags.GENERATEDCONSTR),
HYPOTHETICAL(Flags.HYPOTHETICAL),
PROPRIETARY(Flags.PROPRIETARY),
UNION(Flags.UNION),
OVERRIDE_BRIDGE(Flags.OVERRIDE_BRIDGE),
EFFECTIVELY_FINAL(Flags.EFFECTIVELY_FINAL),
CLASH(Flags.CLASH),
AUXILIARY(Flags.AUXILIARY),
NOT_IN_PROFILE(Flags.NOT_IN_PROFILE),
BAD_OVERRIDE(Flags.BAD_OVERRIDE),
SIGNATURE_POLYMORPHIC(Flags.SIGNATURE_POLYMORPHIC),
THROWS(Flags.THROWS),
LAMBDA_METHOD(Flags.LAMBDA_METHOD),
TYPE_TRANSLATED(Flags.TYPE_TRANSLATED);
Flag(long flag) {
this.value = flag;
this.lowercaseName = StringUtils.toLowerCase(name());
}
@Override
public String toString() {
return lowercaseName;
}
final long value;
final String lowercaseName;
}
}

View File

@@ -0,0 +1,250 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.code;
import java.util.EnumSet;
import java.util.Locale;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.tools.javac.api.Formattable;
import com.sun.tools.javac.api.Messages;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.TypeTag.CLASS;
import static com.sun.tools.javac.code.TypeTag.PACKAGE;
import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
/** Internal symbol kinds, which distinguish between elements of
* different subclasses of Symbol. Symbol kinds are organized so they can be
* or'ed to sets.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class Kinds {
private Kinds() {} // uninstantiable
/** The empty set of kinds.
*/
public final static int NIL = 0;
/** The kind of package symbols.
*/
public final static int PCK = 1 << 0;
/** The kind of type symbols (classes, interfaces and type variables).
*/
public final static int TYP = 1 << 1;
/** The kind of variable symbols.
*/
public final static int VAR = 1 << 2;
/** The kind of values (variables or non-variable expressions), includes VAR.
*/
public final static int VAL = (1 << 3) | VAR;
/** The kind of methods.
*/
public final static int MTH = 1 << 4;
/** Poly kind, for deferred types.
*/
public final static int POLY = 1 << 5;
/** The error kind, which includes all other kinds.
*/
public final static int ERR = (1 << 6) - 1;
/** The set of all kinds.
*/
public final static int AllKinds = ERR;
/** Kinds for erroneous symbols that complement the above
*/
public static final int ERRONEOUS = 1 << 7;
public static final int AMBIGUOUS = ERRONEOUS + 1; // ambiguous reference
public static final int HIDDEN = ERRONEOUS + 2; // hidden method or field
public static final int STATICERR = ERRONEOUS + 3; // nonstatic member from static context
public static final int MISSING_ENCL = ERRONEOUS + 4; // missing enclosing class
public static final int ABSENT_VAR = ERRONEOUS + 5; // missing variable
public static final int WRONG_MTHS = ERRONEOUS + 6; // methods with wrong arguments
public static final int WRONG_MTH = ERRONEOUS + 7; // one method with wrong arguments
public static final int ABSENT_MTH = ERRONEOUS + 8; // missing method
public static final int ABSENT_TYP = ERRONEOUS + 9; // missing type
public static final int WRONG_STATICNESS = ERRONEOUS + 10; // wrong staticness for method references
public enum KindName implements Formattable {
ANNOTATION("kindname.annotation"),
CONSTRUCTOR("kindname.constructor"),
INTERFACE("kindname.interface"),
ENUM("kindname.enum"),
STATIC("kindname.static"),
TYPEVAR("kindname.type.variable"),
BOUND("kindname.type.variable.bound"),
VAR("kindname.variable"),
VAL("kindname.value"),
METHOD("kindname.method"),
CLASS("kindname.class"),
STATIC_INIT("kindname.static.init"),
INSTANCE_INIT("kindname.instance.init"),
PACKAGE("kindname.package");
private final String name;
KindName(String name) {
this.name = name;
}
public String toString() {
return name;
}
public String getKind() {
return "Kindname";
}
public String toString(Locale locale, Messages messages) {
String s = toString();
return messages.getLocalizedString(locale, "compiler.misc." + s);
}
}
/** A KindName representing a given symbol kind
*/
public static KindName kindName(int kind) {
switch (kind) {
case PCK: return KindName.PACKAGE;
case TYP: return KindName.CLASS;
case VAR: return KindName.VAR;
case VAL: return KindName.VAL;
case MTH: return KindName.METHOD;
default : throw new AssertionError("Unexpected kind: "+kind);
}
}
public static KindName kindName(MemberReferenceTree.ReferenceMode mode) {
switch (mode) {
case INVOKE: return KindName.METHOD;
case NEW: return KindName.CONSTRUCTOR;
default : throw new AssertionError("Unexpected mode: "+ mode);
}
}
/** A KindName representing a given symbol
*/
public static KindName kindName(Symbol sym) {
switch (sym.getKind()) {
case PACKAGE:
return KindName.PACKAGE;
case ENUM:
return KindName.ENUM;
case ANNOTATION_TYPE:
case CLASS:
return KindName.CLASS;
case INTERFACE:
return KindName.INTERFACE;
case TYPE_PARAMETER:
return KindName.TYPEVAR;
case ENUM_CONSTANT:
case FIELD:
case PARAMETER:
case LOCAL_VARIABLE:
case EXCEPTION_PARAMETER:
case RESOURCE_VARIABLE:
return KindName.VAR;
case CONSTRUCTOR:
return KindName.CONSTRUCTOR;
case METHOD:
return KindName.METHOD;
case STATIC_INIT:
return KindName.STATIC_INIT;
case INSTANCE_INIT:
return KindName.INSTANCE_INIT;
default:
if (sym.kind == VAL)
// I don't think this can happen but it can't harm
// playing it safe --ahe
return KindName.VAL;
else
throw new AssertionError("Unexpected kind: "+sym.getKind());
}
}
/** A set of KindName(s) representing a set of symbol's kinds.
*/
public static EnumSet<KindName> kindNames(int kind) {
EnumSet<KindName> kinds = EnumSet.noneOf(KindName.class);
if ((kind & VAL) != 0)
kinds.add(((kind & VAL) == VAR) ? KindName.VAR : KindName.VAL);
if ((kind & MTH) != 0) kinds.add(KindName.METHOD);
if ((kind & TYP) != 0) kinds.add(KindName.CLASS);
if ((kind & PCK) != 0) kinds.add(KindName.PACKAGE);
return kinds;
}
/** A KindName representing the kind of a given class/interface type.
*/
public static KindName typeKindName(Type t) {
if (t.hasTag(TYPEVAR) ||
t.hasTag(CLASS) && (t.tsym.flags() & COMPOUND) != 0)
return KindName.BOUND;
else if (t.hasTag(PACKAGE))
return KindName.PACKAGE;
else if ((t.tsym.flags_field & ANNOTATION) != 0)
return KindName.ANNOTATION;
else if ((t.tsym.flags_field & INTERFACE) != 0)
return KindName.INTERFACE;
else
return KindName.CLASS;
}
/** A KindName representing the kind of a missing symbol, given an
* error kind.
* */
public static KindName absentKind(int kind) {
switch (kind) {
case ABSENT_VAR:
return KindName.VAR;
case WRONG_MTHS: case WRONG_MTH: case ABSENT_MTH: case WRONG_STATICNESS:
return KindName.METHOD;
case ABSENT_TYP:
return KindName.CLASS;
default:
throw new AssertionError("Unexpected kind: "+kind);
}
}
}

View File

@@ -0,0 +1,345 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.code;
import java.util.EnumSet;
import java.util.Map;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Options;
import com.sun.tools.javac.util.Pair;
/**
* A class for handling -Xlint suboptions and @SuppresssWarnings.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class Lint
{
/** The context key for the root Lint object. */
protected static final Context.Key<Lint> lintKey = new Context.Key<Lint>();
/** Get the root Lint instance. */
public static Lint instance(Context context) {
Lint instance = context.get(lintKey);
if (instance == null)
instance = new Lint(context);
return instance;
}
/**
* Returns the result of combining the values in this object with
* the given annotation.
*/
public Lint augment(Attribute.Compound attr) {
return augmentor.augment(this, attr);
}
/**
* Returns the result of combining the values in this object with
* the metadata on the given symbol.
*/
public Lint augment(Symbol sym) {
Lint l = augmentor.augment(this, sym.getDeclarationAttributes());
if (sym.isDeprecated()) {
if (l == this)
l = new Lint(this);
l.values.remove(LintCategory.DEPRECATION);
l.suppressedValues.add(LintCategory.DEPRECATION);
}
return l;
}
private final AugmentVisitor augmentor;
private final EnumSet<LintCategory> values;
private final EnumSet<LintCategory> suppressedValues;
private static final Map<String, LintCategory> map =
new java.util.concurrent.ConcurrentHashMap<String, LintCategory>(20);
protected Lint(Context context) {
// initialize values according to the lint options
Options options = Options.instance(context);
values = EnumSet.noneOf(LintCategory.class);
for (Map.Entry<String, LintCategory> e: map.entrySet()) {
if (options.lint(e.getKey()))
values.add(e.getValue());
}
suppressedValues = EnumSet.noneOf(LintCategory.class);
context.put(lintKey, this);
augmentor = new AugmentVisitor(context);
}
protected Lint(Lint other) {
this.augmentor = other.augmentor;
this.values = other.values.clone();
this.suppressedValues = other.suppressedValues.clone();
}
@Override
public String toString() {
return "Lint:[values" + values + " suppressedValues" + suppressedValues + "]";
}
/**
* Categories of warnings that can be generated by the compiler.
*/
public enum LintCategory {
/**
* Warn when code refers to a auxiliary class that is hidden in a source file (ie source file name is
* different from the class name, and the type is not properly nested) and the referring code
* is not located in the same source file.
*/
AUXILIARYCLASS("auxiliaryclass"),
/**
* Warn about use of unnecessary casts.
*/
CAST("cast"),
/**
* Warn about issues related to classfile contents
*/
CLASSFILE("classfile"),
/**
* Warn about use of deprecated items.
*/
DEPRECATION("deprecation"),
/**
* Warn about items which are documented with an {@code @deprecated} JavaDoc
* comment, but which do not have {@code @Deprecated} annotation.
*/
DEP_ANN("dep-ann"),
/**
* Warn about division by constant integer 0.
*/
DIVZERO("divzero"),
/**
* Warn about empty statement after if.
*/
EMPTY("empty"),
/**
* Warn about falling through from one case of a switch statement to the next.
*/
FALLTHROUGH("fallthrough"),
/**
* Warn about finally clauses that do not terminate normally.
*/
FINALLY("finally"),
/**
* Warn about issues relating to use of command line options
*/
OPTIONS("options"),
/**
* Warn about issues regarding method overloads.
*/
OVERLOADS("overloads"),
/**
* Warn about issues regarding method overrides.
*/
OVERRIDES("overrides"),
/**
* Warn about invalid path elements on the command line.
* Such warnings cannot be suppressed with the SuppressWarnings
* annotation.
*/
PATH("path"),
/**
* Warn about issues regarding annotation processing.
*/
PROCESSING("processing"),
/**
* Warn about unchecked operations on raw types.
*/
RAW("rawtypes"),
/**
* Warn about Serializable classes that do not provide a serial version ID.
*/
SERIAL("serial"),
/**
* Warn about issues relating to use of statics
*/
STATIC("static"),
/**
* Warn about proprietary API that may be removed in a future release.
*/
SUNAPI("sunapi", true),
/**
* Warn about issues relating to use of try blocks (i.e. try-with-resources)
*/
TRY("try"),
/**
* Warn about unchecked operations on raw types.
*/
UNCHECKED("unchecked"),
/**
* Warn about potentially unsafe vararg methods
*/
VARARGS("varargs");
LintCategory(String option) {
this(option, false);
}
LintCategory(String option, boolean hidden) {
this.option = option;
this.hidden = hidden;
map.put(option, this);
}
static LintCategory get(String option) {
return map.get(option);
}
public final String option;
public final boolean hidden;
};
/**
* Checks if a warning category is enabled. A warning category may be enabled
* on the command line, or by default, and can be temporarily disabled with
* the SuppressWarnings annotation.
*/
public boolean isEnabled(LintCategory lc) {
return values.contains(lc);
}
/**
* Checks is a warning category has been specifically suppressed, by means
* of the SuppressWarnings annotation, or, in the case of the deprecated
* category, whether it has been implicitly suppressed by virtue of the
* current entity being itself deprecated.
*/
public boolean isSuppressed(LintCategory lc) {
return suppressedValues.contains(lc);
}
protected static class AugmentVisitor implements Attribute.Visitor {
private final Context context;
private Symtab syms;
private Lint parent;
private Lint lint;
AugmentVisitor(Context context) {
// to break an ugly sequence of initialization dependencies,
// we defer the initialization of syms until it is needed
this.context = context;
}
Lint augment(Lint parent, Attribute.Compound attr) {
initSyms();
this.parent = parent;
lint = null;
attr.accept(this);
return (lint == null ? parent : lint);
}
Lint augment(Lint parent, List<Attribute.Compound> attrs) {
initSyms();
this.parent = parent;
lint = null;
for (Attribute.Compound a: attrs) {
a.accept(this);
}
return (lint == null ? parent : lint);
}
private void initSyms() {
if (syms == null)
syms = Symtab.instance(context);
}
private void suppress(LintCategory lc) {
if (lint == null)
lint = new Lint(parent);
lint.suppressedValues.add(lc);
lint.values.remove(lc);
}
public void visitConstant(Attribute.Constant value) {
if (value.type.tsym == syms.stringType.tsym) {
LintCategory lc = LintCategory.get((String) (value.value));
if (lc != null)
suppress(lc);
}
}
public void visitClass(Attribute.Class clazz) {
}
// If we find a @SuppressWarnings annotation, then we continue
// walking the tree, in order to suppress the individual warnings
// specified in the @SuppressWarnings annotation.
public void visitCompound(Attribute.Compound compound) {
if (compound.type.tsym == syms.suppressWarningsType.tsym) {
for (List<Pair<MethodSymbol,Attribute>> v = compound.values;
v.nonEmpty(); v = v.tail) {
Pair<MethodSymbol,Attribute> value = v.head;
if (value.fst.name.toString().equals("value"))
value.snd.accept(this);
}
}
}
public void visitArray(Attribute.Array array) {
for (Attribute value : array.values)
value.accept(this);
}
public void visitEnum(Attribute.Enum e) {
}
public void visitError(Attribute.Error e) {
}
};
}

View File

@@ -0,0 +1,417 @@
/*
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.code;
import java.util.Locale;
import com.sun.tools.javac.api.Messages;
import com.sun.tools.javac.code.Type.AnnotatedType;
import com.sun.tools.javac.code.Type.ArrayType;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import static com.sun.tools.javac.code.BoundKind.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.TypeTag.CLASS;
import static com.sun.tools.javac.code.TypeTag.FORALL;
/**
* A combined type/symbol visitor for generating non-trivial localized string
* representation of types and symbols.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Visitor<String, Locale> {
List<Type> seenCaptured = List.nil();
static final int PRIME = 997; // largest prime less than 1000
protected Printer() { }
/**
* This method should be overriden in order to provide proper i18n support.
*
* @param locale the locale in which the string is to be rendered
* @param key the key corresponding to the message to be displayed
* @param args a list of optional arguments
* @return localized string representation
*/
protected abstract String localize(Locale locale, String key, Object... args);
/**
* Maps a captured type into an unique identifier.
*
* @param t the captured type for which an id is to be retrieved
* @param locale locale settings
* @return unique id representing this captured type
*/
protected abstract String capturedVarId(CapturedType t, Locale locale);
/**
* Create a printer with default i18n support provided by Messages. By default,
* captured types ids are generated using hashcode.
*
* @param messages Messages class to be used for i18n
* @return printer visitor instance
*/
public static Printer createStandardPrinter(final Messages messages) {
return new Printer() {
@Override
protected String localize(Locale locale, String key, Object... args) {
return messages.getLocalizedString(locale, key, args);
}
@Override
protected String capturedVarId(CapturedType t, Locale locale) {
return (t.hashCode() & 0xFFFFFFFFL) % PRIME + "";
}};
}
/**
* Get a localized string representation for all the types in the input list.
*
* @param ts types to be displayed
* @param locale the locale in which the string is to be rendered
* @return localized string representation
*/
public String visitTypes(List<Type> ts, Locale locale) {
ListBuffer<String> sbuf = new ListBuffer<>();
for (Type t : ts) {
sbuf.append(visit(t, locale));
}
return sbuf.toList().toString();
}
/**
* * Get a localized string representation for all the symbols in the input list.
*
* @param ts symbols to be displayed
* @param locale the locale in which the string is to be rendered
* @return localized string representation
*/
public String visitSymbols(List<Symbol> ts, Locale locale) {
ListBuffer<String> sbuf = new ListBuffer<>();
for (Symbol t : ts) {
sbuf.append(visit(t, locale));
}
return sbuf.toList().toString();
}
/**
* Get a localized string representation for a given type.
*
* @param t type to be displayed
* @param locale the locale in which the string is to be rendered
* @return localized string representation
*/
public String visit(Type t, Locale locale) {
return t.accept(this, locale);
}
/**
* Get a localized string representation for a given symbol.
*
* @param s symbol to be displayed
* @param locale the locale in which the string is to be rendered
* @return localized string representation
*/
public String visit(Symbol s, Locale locale) {
return s.accept(this, locale);
}
@Override
public String visitCapturedType(CapturedType t, Locale locale) {
if (seenCaptured.contains(t))
return localize(locale, "compiler.misc.type.captureof.1",
capturedVarId(t, locale));
else {
try {
seenCaptured = seenCaptured.prepend(t);
return localize(locale, "compiler.misc.type.captureof",
capturedVarId(t, locale),
visit(t.wildcard, locale));
}
finally {
seenCaptured = seenCaptured.tail;
}
}
}
@Override
public String visitForAll(ForAll t, Locale locale) {
return "<" + visitTypes(t.tvars, locale) + ">" + visit(t.qtype, locale);
}
@Override
public String visitUndetVar(UndetVar t, Locale locale) {
if (t.inst != null) {
return visit(t.inst, locale);
} else {
return visit(t.qtype, locale) + "?";
}
}
@Override
public String visitArrayType(ArrayType t, Locale locale) {
StringBuilder res = new StringBuilder();
printBaseElementType(t, res, locale);
printBrackets(t, res, locale);
return res.toString();
}
void printBaseElementType(Type t, StringBuilder sb, Locale locale) {
Type arrel = t;
while (arrel.hasTag(TypeTag.ARRAY)) {
arrel = arrel.unannotatedType();
arrel = ((ArrayType) arrel).elemtype;
}
sb.append(visit(arrel, locale));
}
void printBrackets(Type t, StringBuilder sb, Locale locale) {
Type arrel = t;
while (arrel.hasTag(TypeTag.ARRAY)) {
if (arrel.isAnnotated()) {
sb.append(' ');
sb.append(arrel.getAnnotationMirrors());
sb.append(' ');
}
sb.append("[]");
arrel = arrel.unannotatedType();
arrel = ((ArrayType) arrel).elemtype;
}
}
@Override
public String visitClassType(ClassType t, Locale locale) {
StringBuilder buf = new StringBuilder();
if (t.getEnclosingType().hasTag(CLASS) && t.tsym.owner.kind == Kinds.TYP) {
buf.append(visit(t.getEnclosingType(), locale));
buf.append('.');
buf.append(className(t, false, locale));
} else {
buf.append(className(t, true, locale));
}
if (t.getTypeArguments().nonEmpty()) {
buf.append('<');
buf.append(visitTypes(t.getTypeArguments(), locale));
buf.append('>');
}
return buf.toString();
}
@Override
public String visitMethodType(MethodType t, Locale locale) {
return "(" + printMethodArgs(t.argtypes, false, locale) + ")" + visit(t.restype, locale);
}
@Override
public String visitPackageType(PackageType t, Locale locale) {
return t.tsym.getQualifiedName().toString();
}
@Override
public String visitWildcardType(WildcardType t, Locale locale) {
StringBuilder s = new StringBuilder();
s.append(t.kind);
if (t.kind != UNBOUND) {
s.append(visit(t.type, locale));
}
return s.toString();
}
@Override
public String visitErrorType(ErrorType t, Locale locale) {
return visitType(t, locale);
}
@Override
public String visitTypeVar(TypeVar t, Locale locale) {
return visitType(t, locale);
}
@Override
public String visitAnnotatedType(AnnotatedType t, Locale locale) {
if (t.getAnnotationMirrors().nonEmpty()) {
if (t.unannotatedType().hasTag(TypeTag.ARRAY)) {
StringBuilder res = new StringBuilder();
printBaseElementType(t, res, locale);
printBrackets(t, res, locale);
return res.toString();
} else if (t.unannotatedType().hasTag(TypeTag.CLASS) &&
t.unannotatedType().getEnclosingType() != Type.noType) {
return visit(t.unannotatedType().getEnclosingType(), locale) +
". " +
t.getAnnotationMirrors() +
" " + className((ClassType)t.unannotatedType(), false, locale);
} else {
return t.getAnnotationMirrors() + " " + visit(t.unannotatedType(), locale);
}
} else {
return visit(t.unannotatedType(), locale);
}
}
public String visitType(Type t, Locale locale) {
String s = (t.tsym == null || t.tsym.name == null)
? localize(locale, "compiler.misc.type.none")
: t.tsym.name.toString();
return s;
}
/**
* Converts a class name into a (possibly localized) string. Anonymous
* inner classes get converted into a localized string.
*
* @param t the type of the class whose name is to be rendered
* @param longform if set, the class' fullname is displayed - if unset the
* short name is chosen (w/o package)
* @param locale the locale in which the string is to be rendered
* @return localized string representation
*/
protected String className(ClassType t, boolean longform, Locale locale) {
Symbol sym = t.tsym;
if (sym.name.length() == 0 && (sym.flags() & COMPOUND) != 0) {
StringBuilder s = new StringBuilder(visit(t.supertype_field, locale));
for (List<Type> is = t.interfaces_field; is.nonEmpty(); is = is.tail) {
s.append('&');
s.append(visit(is.head, locale));
}
return s.toString();
} else if (sym.name.length() == 0) {
String s;
ClassType norm = (ClassType) t.tsym.type;
if (norm == null) {
s = localize(locale, "compiler.misc.anonymous.class", (Object) null);
} else if (norm.interfaces_field != null && norm.interfaces_field.nonEmpty()) {
s = localize(locale, "compiler.misc.anonymous.class",
visit(norm.interfaces_field.head, locale));
} else {
s = localize(locale, "compiler.misc.anonymous.class",
visit(norm.supertype_field, locale));
}
return s;
} else if (longform) {
return sym.getQualifiedName().toString();
} else {
return sym.name.toString();
}
}
/**
* Converts a set of method argument types into their corresponding
* localized string representation.
*
* @param args arguments to be rendered
* @param varArgs if true, the last method argument is regarded as a vararg
* @param locale the locale in which the string is to be rendered
* @return localized string representation
*/
protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) {
if (!varArgs) {
return visitTypes(args, locale);
} else {
StringBuilder buf = new StringBuilder();
while (args.tail.nonEmpty()) {
buf.append(visit(args.head, locale));
args = args.tail;
buf.append(',');
}
if (args.head.unannotatedType().hasTag(TypeTag.ARRAY)) {
buf.append(visit(((ArrayType) args.head.unannotatedType()).elemtype, locale));
if (args.head.getAnnotationMirrors().nonEmpty()) {
buf.append(' ');
buf.append(args.head.getAnnotationMirrors());
buf.append(' ');
}
buf.append("...");
} else {
buf.append(visit(args.head, locale));
}
return buf.toString();
}
}
@Override
public String visitClassSymbol(ClassSymbol sym, Locale locale) {
return sym.name.isEmpty()
? localize(locale, "compiler.misc.anonymous.class", sym.flatname)
: sym.fullname.toString();
}
@Override
public String visitMethodSymbol(MethodSymbol s, Locale locale) {
if (s.isStaticOrInstanceInit()) {
return s.owner.name.toString();
} else {
String ms = (s.name == s.name.table.names.init)
? s.owner.name.toString()
: s.name.toString();
if (s.type != null) {
if (s.type.hasTag(FORALL)) {
ms = "<" + visitTypes(s.type.getTypeArguments(), locale) + ">" + ms;
}
ms += "(" + printMethodArgs(
s.type.getParameterTypes(),
(s.flags() & VARARGS) != 0,
locale) + ")";
}
return ms;
}
}
@Override
public String visitOperatorSymbol(OperatorSymbol s, Locale locale) {
return visitMethodSymbol(s, locale);
}
@Override
public String visitPackageSymbol(PackageSymbol s, Locale locale) {
return s.isUnnamed()
? localize(locale, "compiler.misc.unnamed.package")
: s.fullname.toString();
}
@Override
public String visitTypeSymbol(TypeSymbol s, Locale locale) {
return visitSymbol(s, locale);
}
@Override
public String visitVarSymbol(VarSymbol s, Locale locale) {
return visitSymbol(s, locale);
}
@Override
public String visitSymbol(Symbol s, Locale locale) {
return s.name.toString();
}
}

View File

@@ -0,0 +1,766 @@
/*
* Copyright (c) 1999, 2015, 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.code;
import java.util.Iterator;
import com.sun.tools.javac.util.*;
/** A scope represents an area of visibility in a Java program. The
* Scope class is a container for symbols which provides
* efficient access to symbols given their names. Scopes are implemented
* as hash tables with "open addressing" and "double hashing".
* Scopes can be nested; the next field of a scope points
* to its next outer scope. Nested scopes can share their hash tables.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class Scope {
/** The number of scopes that share this scope's hash table.
*/
private int shared;
/** Next enclosing scope (with whom this scope may share a hashtable)
*/
public Scope next;
/** The scope's owner.
*/
public Symbol owner;
/** A hash table for the scope's entries.
*/
Entry[] table;
/** Mask for hash codes, always equal to (table.length - 1).
*/
int hashMask;
/** A linear list that also contains all entries in
* reverse order of appearance (i.e later entries are pushed on top).
*/
public Entry elems;
/** The number of elements in this scope.
* This includes deleted elements, whose value is the sentinel.
*/
int nelems = 0;
/** A list of scopes to be notified if items are to be removed from this scope.
*/
List<ScopeListener> listeners = List.nil();
/** Use as a "not-found" result for lookup.
* Also used to mark deleted entries in the table.
*/
private static final Entry sentinel = new Entry(null, null, null, null);
/** The hash table's initial size.
*/
private static final int INITIAL_SIZE = 0x10;
/** A value for the empty scope.
*/
public static final Scope emptyScope = new Scope(null, null, new Entry[]{});
/** Construct a new scope, within scope next, with given owner, using
* given table. The table's length must be an exponent of 2.
*/
private Scope(Scope next, Symbol owner, Entry[] table) {
this.next = next;
Assert.check(emptyScope == null || owner != null);
this.owner = owner;
this.table = table;
this.hashMask = table.length - 1;
}
/** Convenience constructor used for dup and dupUnshared. */
private Scope(Scope next, Symbol owner, Entry[] table, int nelems) {
this(next, owner, table);
this.nelems = nelems;
}
/** Construct a new scope, within scope next, with given owner,
* using a fresh table of length INITIAL_SIZE.
*/
public Scope(Symbol owner) {
this(null, owner, new Entry[INITIAL_SIZE]);
}
/** Construct a fresh scope within this scope, with same owner,
* which shares its table with the outer scope. Used in connection with
* method leave if scope access is stack-like in order to avoid allocation
* of fresh tables.
*/
public Scope dup() {
return dup(this.owner);
}
/** Construct a fresh scope within this scope, with new owner,
* which shares its table with the outer scope. Used in connection with
* method leave if scope access is stack-like in order to avoid allocation
* of fresh tables.
*/
public Scope dup(Symbol newOwner) {
Scope result = new Scope(this, newOwner, this.table, this.nelems);
shared++;
// System.out.println("====> duping scope " + this.hashCode() + " owned by " + newOwner + " to " + result.hashCode());
// new Error().printStackTrace(System.out);
return result;
}
/** Construct a fresh scope within this scope, with same owner,
* with a new hash table, whose contents initially are those of
* the table of its outer scope.
*/
public Scope dupUnshared() {
return new Scope(this, this.owner, this.table.clone(), this.nelems);
}
/** Remove all entries of this scope from its table, if shared
* with next.
*/
public Scope leave() {
Assert.check(shared == 0);
if (table != next.table) return next;
while (elems != null) {
int hash = getIndex(elems.sym.name);
Entry e = table[hash];
Assert.check(e == elems, elems.sym);
table[hash] = elems.shadowed;
elems = elems.sibling;
}
Assert.check(next.shared > 0);
next.shared--;
next.nelems = nelems;
// System.out.println("====> leaving scope " + this.hashCode() + " owned by " + this.owner + " to " + next.hashCode());
// new Error().printStackTrace(System.out);
return next;
}
/** Double size of hash table.
*/
private void dble() {
Assert.check(shared == 0);
Entry[] oldtable = table;
Entry[] newtable = new Entry[oldtable.length * 2];
for (Scope s = this; s != null; s = s.next) {
if (s.table == oldtable) {
Assert.check(s == this || s.shared != 0);
s.table = newtable;
s.hashMask = newtable.length - 1;
}
}
int n = 0;
for (int i = oldtable.length; --i >= 0; ) {
Entry e = oldtable[i];
if (e != null && e != sentinel) {
table[getIndex(e.sym.name)] = e;
n++;
}
}
// We don't need to update nelems for shared inherited scopes,
// since that gets handled by leave().
nelems = n;
}
/** Enter symbol sym in this scope.
*/
public void enter(Symbol sym) {
Assert.check(shared == 0);
enter(sym, this);
}
public void enter(Symbol sym, Scope s) {
enter(sym, s, s, false);
}
/**
* Enter symbol sym in this scope, but mark that it comes from
* given scope `s' accessed through `origin'. The last two
* arguments are only used in import scopes.
*/
public void enter(Symbol sym, Scope s, Scope origin, boolean staticallyImported) {
Assert.check(shared == 0);
if (nelems * 3 >= hashMask * 2)
dble();
int hash = getIndex(sym.name);
Entry old = table[hash];
if (old == null) {
old = sentinel;
nelems++;
}
Entry e = makeEntry(sym, old, elems, s, origin, staticallyImported);
table[hash] = e;
elems = e;
//notify listeners
for (List<ScopeListener> l = listeners; l.nonEmpty(); l = l.tail) {
l.head.symbolAdded(sym, this);
}
}
Entry makeEntry(Symbol sym, Entry shadowed, Entry sibling, Scope scope, Scope origin, boolean staticallyImported) {
return new Entry(sym, shadowed, sibling, scope);
}
public interface ScopeListener {
public void symbolAdded(Symbol sym, Scope s);
public void symbolRemoved(Symbol sym, Scope s);
}
public void addScopeListener(ScopeListener sl) {
listeners = listeners.prepend(sl);
}
/** Remove symbol from this scope.
*/
public void remove(final Symbol sym) {
Assert.check(shared == 0);
Entry e = lookup(sym.name, new Filter<Symbol>() {
@Override
public boolean accepts(Symbol candidate) {
return candidate == sym;
}
});
if (e.scope == null) return;
// remove e from table and shadowed list;
int i = getIndex(sym.name);
Entry te = table[i];
if (te == e)
table[i] = e.shadowed;
else while (true) {
if (te.shadowed == e) {
te.shadowed = e.shadowed;
break;
}
te = te.shadowed;
}
// remove e from elems and sibling list
te = elems;
if (te == e)
elems = e.sibling;
else while (true) {
if (te.sibling == e) {
te.sibling = e.sibling;
break;
}
te = te.sibling;
}
//notify listeners
for (List<ScopeListener> l = listeners; l.nonEmpty(); l = l.tail) {
l.head.symbolRemoved(sym, this);
}
}
/** Enter symbol sym in this scope if not already there.
*/
public void enterIfAbsent(Symbol sym) {
Assert.check(shared == 0);
Entry e = lookup(sym.name);
while (e.scope == this && e.sym.kind != sym.kind) e = e.next();
if (e.scope != this) enter(sym);
}
/** Given a class, is there already a class with same fully
* qualified name in this (import) scope?
*/
public boolean includes(Symbol c) {
for (Scope.Entry e = lookup(c.name);
e.scope == this;
e = e.next()) {
if (e.sym == c) return true;
}
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
* both its scope and sym fields, whereas both fields are non-null
* for regular entries.
*/
public Entry lookup(Name name) {
return lookup(name, noFilter);
}
public Entry lookup(Name name, Filter<Symbol> sf) {
Entry e = table[getIndex(name)];
if (e == null || e == sentinel)
return sentinel;
while (e.scope != null && (e.sym.name != name || !sf.accepts(e.sym)))
e = e.shadowed;
return e;
}
/*void dump (java.io.PrintStream out) {
out.println(this);
for (int l=0; l < table.length; l++) {
Entry le = table[l];
out.print("#"+l+": ");
if (le==sentinel) out.println("sentinel");
else if(le == null) out.println("null");
else out.println(""+le+" s:"+le.sym);
}
}*/
/** Look for slot in the table.
* We use open addressing with double hashing.
*/
int getIndex (Name name) {
int h = name.hashCode();
int i = h & hashMask;
// The expression below is always odd, so it is guaranteed
// to be mutually prime with table.length, a power of 2.
int x = hashMask - ((h + (h >> 16)) << 1);
int d = -1; // Index of a deleted item.
for (;;) {
Entry e = table[i];
if (e == null)
return d >= 0 ? d : i;
if (e == sentinel) {
// We have to keep searching even if we see a deleted item.
// However, remember the index in case we fail to find the name.
if (d < 0)
d = i;
} else if (e.sym.name == name)
return i;
i = (i + x) & hashMask;
}
}
public boolean anyMatch(Filter<Symbol> sf) {
return getElements(sf).iterator().hasNext();
}
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>() {
private Scope currScope = Scope.this;
private Scope.Entry currEntry = elems;
{
update();
}
public boolean hasNext() {
return currEntry != null;
}
public Symbol next() {
Symbol sym = (currEntry == null ? null : currEntry.sym);
if (currEntry != null) {
currEntry = currEntry.sibling;
}
update();
return sym;
}
public void remove() {
throw new UnsupportedOperationException();
}
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;
}
}
};
}
};
}
public Iterable<Symbol> getElementsByName(Name name) {
return getElementsByName(name, noFilter);
}
public Iterable<Symbol> getElementsByName(final Name name, final Filter<Symbol> sf) {
return new Iterable<Symbol>() {
public Iterator<Symbol> iterator() {
return new Iterator<Symbol>() {
Scope.Entry currentEntry = lookup(name, sf);
public boolean hasNext() {
return currentEntry.scope != null;
}
public Symbol next() {
Scope.Entry prevEntry = currentEntry;
currentEntry = currentEntry.next(sf);
return prevEntry.sym;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
public String toString() {
StringBuilder result = new StringBuilder();
result.append("Scope[");
for (Scope s = this; s != null ; s = s.next) {
if (s != this) result.append(" | ");
for (Entry e = s.elems; e != null; e = e.sibling) {
if (e != s.elems) result.append(", ");
result.append(e.sym);
}
}
result.append("]");
return result.toString();
}
/** A class for scope entries.
*/
public static class Entry {
/** The referenced symbol.
* sym == null iff this == sentinel
*/
public Symbol sym;
/** An entry with the same hash code, or sentinel.
*/
private Entry shadowed;
/** Next entry in same scope.
*/
public Entry sibling;
/** The entry's scope.
* scope == null iff this == sentinel
* for an entry in an import scope, this is the scope
* where the entry came from (i.e. was imported from).
*/
public Scope scope;
public Entry(Symbol sym, Entry shadowed, Entry sibling, Scope scope) {
this.sym = sym;
this.shadowed = shadowed;
this.sibling = sibling;
this.scope = scope;
}
/** Return next entry with the same name as this entry, proceeding
* outwards if not found in this scope.
*/
public Entry next() {
return shadowed;
}
public Entry next(Filter<Symbol> sf) {
if (shadowed.sym == null || sf.accepts(shadowed.sym)) return shadowed;
else return shadowed.next(sf);
}
public boolean isStaticallyImported() {
return false;
}
public Scope getOrigin() {
// The origin is only recorded for import scopes. For all
// other scope entries, the "enclosing" type is available
// from other sources. See Attr.visitSelect and
// Attr.visitIdent. Rather than throwing an assertion
// error, we return scope which will be the same as origin
// in many cases.
return scope;
}
}
public static class ImportScope extends Scope {
public ImportScope(Symbol owner) {
super(owner);
}
@Override
Entry makeEntry(Symbol sym, Entry shadowed, Entry sibling, Scope scope,
final Scope origin, final boolean staticallyImported) {
return new Entry(sym, shadowed, sibling, scope) {
@Override
public Scope getOrigin() {
return origin;
}
@Override
public boolean isStaticallyImported() {
return staticallyImported;
}
};
}
}
public static class StarImportScope extends ImportScope implements ScopeListener {
public StarImportScope(Symbol owner) {
super(owner);
}
public void importAll (Scope fromScope) {
for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) {
if (e.sym.kind == Kinds.TYP && !includes(e.sym))
enter(e.sym, fromScope);
}
// Register to be notified when imported items are removed
fromScope.addScopeListener(this);
}
public void symbolRemoved(Symbol sym, Scope s) {
remove(sym);
}
public void symbolAdded(Symbol sym, Scope s) { }
}
/** An empty scope, into which you can't place anything. Used for
* the scope for a variable initializer.
*/
public static class DelegatedScope extends Scope {
Scope delegatee;
public static final Entry[] emptyTable = new Entry[0];
public DelegatedScope(Scope outer) {
super(outer, outer.owner, emptyTable);
delegatee = outer;
}
public Scope dup() {
return new DelegatedScope(next);
}
public Scope dupUnshared() {
return new DelegatedScope(next);
}
public Scope leave() {
return next;
}
public void enter(Symbol sym) {
// only anonymous classes could be put here
}
public void enter(Symbol sym, Scope s) {
// only anonymous classes could be put here
}
public void remove(Symbol sym) {
throw new AssertionError(sym);
}
public Entry lookup(Name name) {
return delegatee.lookup(name);
}
}
/** A class scope adds capabilities to keep track of changes in related
* class scopes - this allows client to realize whether a class scope
* has changed, either directly (because a new member has been added/removed
* to this scope) or indirectly (i.e. because a new member has been
* added/removed into a supertype scope)
*/
public static class CompoundScope extends Scope implements ScopeListener {
public static final Entry[] emptyTable = new Entry[0];
private List<Scope> subScopes = List.nil();
private int mark = 0;
public CompoundScope(Symbol owner) {
super(null, owner, emptyTable);
}
public void addSubScope(Scope that) {
if (that != null) {
subScopes = subScopes.prepend(that);
that.addScopeListener(this);
mark++;
for (ScopeListener sl : listeners) {
sl.symbolAdded(null, this); //propagate upwards in case of nested CompoundScopes
}
}
}
public void symbolAdded(Symbol sym, Scope s) {
mark++;
for (ScopeListener sl : listeners) {
sl.symbolAdded(sym, s);
}
}
public void symbolRemoved(Symbol sym, Scope s) {
mark++;
for (ScopeListener sl : listeners) {
sl.symbolRemoved(sym, s);
}
}
public int getMark() {
return mark;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("CompoundScope{");
String sep = "";
for (Scope s : subScopes) {
buf.append(sep);
buf.append(s);
sep = ",";
}
buf.append("}");
return buf.toString();
}
@Override
public Iterable<Symbol> getElements(final Filter<Symbol> sf) {
return new Iterable<Symbol>() {
public Iterator<Symbol> iterator() {
return new CompoundScopeIterator(subScopes) {
Iterator<Symbol> nextIterator(Scope s) {
return s.getElements(sf).iterator();
}
};
}
};
}
@Override
public Iterable<Symbol> getElementsByName(final Name name, final Filter<Symbol> sf) {
return new Iterable<Symbol>() {
public Iterator<Symbol> iterator() {
return new CompoundScopeIterator(subScopes) {
Iterator<Symbol> nextIterator(Scope s) {
return s.getElementsByName(name, sf).iterator();
}
};
}
};
}
abstract class CompoundScopeIterator implements Iterator<Symbol> {
private Iterator<Symbol> currentIterator;
private List<Scope> scopesToScan;
public CompoundScopeIterator(List<Scope> scopesToScan) {
this.scopesToScan = scopesToScan;
update();
}
abstract Iterator<Symbol> nextIterator(Scope s);
public boolean hasNext() {
return currentIterator != null;
}
public Symbol next() {
Symbol sym = currentIterator.next();
if (!currentIterator.hasNext()) {
update();
}
return sym;
}
public void remove() {
throw new UnsupportedOperationException();
}
private void update() {
while (scopesToScan.nonEmpty()) {
currentIterator = nextIterator(scopesToScan.head);
scopesToScan = scopesToScan.tail;
if (currentIterator.hasNext()) return;
}
currentIterator = null;
}
}
@Override
public Entry lookup(Name name, Filter<Symbol> sf) {
throw new UnsupportedOperationException();
}
@Override
public Scope dup(Symbol newOwner) {
throw new UnsupportedOperationException();
}
@Override
public void enter(Symbol sym, Scope s, Scope origin, boolean staticallyImported) {
throw new UnsupportedOperationException();
}
@Override
public void remove(Symbol sym) {
throw new UnsupportedOperationException();
}
}
/** An error scope, for which the owner should be an error symbol. */
public static class ErrorScope extends Scope {
ErrorScope(Scope next, Symbol errSymbol, Entry[] table) {
super(next, /*owner=*/errSymbol, table);
}
public ErrorScope(Symbol errSymbol) {
super(errSymbol);
}
public Scope dup() {
return new ErrorScope(this, owner, table);
}
public Scope dupUnshared() {
return new ErrorScope(this, owner, table.clone());
}
public Entry lookup(Name name) {
Entry e = super.lookup(name);
if (e.scope == null)
return new Entry(owner, null, null, null);
else
return e;
}
}
}

View File

@@ -0,0 +1,259 @@
/*
* Copyright (c) 2002, 2014, 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.code;
import java.util.*;
import javax.lang.model.SourceVersion;
import static javax.lang.model.SourceVersion.*;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.util.*;
import static com.sun.tools.javac.main.Option.*;
/** The source language version accepted.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public enum Source {
/** 1.0 had no inner classes, and so could not pass the JCK. */
// public static final Source JDK1_0 = new Source("1.0");
/** 1.1 did not have strictfp, and so could not pass the JCK. */
// public static final Source JDK1_1 = new Source("1.1");
/** 1.2 introduced strictfp. */
JDK1_2("1.2"),
/** 1.3 is the same language as 1.2. */
JDK1_3("1.3"),
/** 1.4 introduced assert. */
JDK1_4("1.4"),
/** 1.5 introduced generics, attributes, foreach, boxing, static import,
* covariant return, enums, varargs, et al. */
JDK1_5("1.5"),
/** 1.6 reports encoding problems as errors instead of warnings. */
JDK1_6("1.6"),
/** 1.7 introduced try-with-resources, multi-catch, string switch, etc. */
JDK1_7("1.7"),
/** 1.8 covers the to be determined language features that will be added in JDK 8. */
JDK1_8("1.8");
private static final Context.Key<Source> sourceKey
= new Context.Key<Source>();
public static Source instance(Context context) {
Source instance = context.get(sourceKey);
if (instance == null) {
Options options = Options.instance(context);
String sourceString = options.get(SOURCE);
if (sourceString != null) instance = lookup(sourceString);
if (instance == null) instance = DEFAULT;
context.put(sourceKey, instance);
}
return instance;
}
public final String name;
private static final Map<String,Source> tab = new HashMap<String,Source>();
static {
for (Source s : values()) {
tab.put(s.name, s);
}
tab.put("5", JDK1_5); // Make 5 an alias for 1.5
tab.put("6", JDK1_6); // Make 6 an alias for 1.6
tab.put("7", JDK1_7); // Make 7 an alias for 1.7
tab.put("8", JDK1_8); // Make 8 an alias for 1.8
}
private Source(String name) {
this.name = name;
}
public static final Source DEFAULT = JDK1_8;
public static Source lookup(String name) {
return tab.get(name);
}
public Target requiredTarget() {
if (this.compareTo(JDK1_8) >= 0) return Target.JDK1_8;
if (this.compareTo(JDK1_7) >= 0) return Target.JDK1_7;
if (this.compareTo(JDK1_6) >= 0) return Target.JDK1_6;
if (this.compareTo(JDK1_5) >= 0) return Target.JDK1_5;
if (this.compareTo(JDK1_4) >= 0) return Target.JDK1_4;
return Target.JDK1_1;
}
/** Allow encoding errors, giving only warnings. */
public boolean allowEncodingErrors() {
return compareTo(JDK1_6) < 0;
}
public boolean allowAsserts() {
return compareTo(JDK1_4) >= 0;
}
public boolean allowCovariantReturns() {
return compareTo(JDK1_5) >= 0;
}
public boolean allowGenerics() {
return compareTo(JDK1_5) >= 0;
}
public boolean allowDiamond() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowMulticatch() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowImprovedRethrowAnalysis() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowImprovedCatchAnalysis() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowEnums() {
return compareTo(JDK1_5) >= 0;
}
public boolean allowForeach() {
return compareTo(JDK1_5) >= 0;
}
public boolean allowStaticImport() {
return compareTo(JDK1_5) >= 0;
}
public boolean allowBoxing() {
return compareTo(JDK1_5) >= 0;
}
public boolean allowVarargs() {
return compareTo(JDK1_5) >= 0;
}
public boolean allowAnnotations() {
return compareTo(JDK1_5) >= 0;
}
// hex floating-point literals supported?
public boolean allowHexFloats() {
return compareTo(JDK1_5) >= 0;
}
public boolean allowAnonOuterThis() {
return compareTo(JDK1_5) >= 0;
}
public boolean addBridges() {
return compareTo(JDK1_5) >= 0;
}
public boolean enforceMandatoryWarnings() {
return compareTo(JDK1_5) >= 0;
}
public boolean allowTryWithResources() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowBinaryLiterals() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowUnderscoresInLiterals() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowStringsInSwitch() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowSimplifiedVarargs() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowObjectToPrimitiveCast() {
return compareTo(JDK1_7) >= 0;
}
public boolean enforceThisDotInit() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowPoly() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowLambda() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowMethodReferences() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowDefaultMethods() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowStaticInterfaceMethods() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowStrictMethodClashCheck() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowEffectivelyFinalInInnerClasses() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowTypeAnnotations() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowAnnotationsAfterTypeParams() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowRepeatedAnnotations() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowIntersectionTypesInCast() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowGraphInference() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowFunctionalInterfaceMostSpecific() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowPostApplicabilityVarargsAccessCheck() {
return compareTo(JDK1_8) >= 0;
}
public static SourceVersion toSourceVersion(Source source) {
switch(source) {
case JDK1_2:
return RELEASE_2;
case JDK1_3:
return RELEASE_3;
case JDK1_4:
return RELEASE_4;
case JDK1_5:
return RELEASE_5;
case JDK1_6:
return RELEASE_6;
case JDK1_7:
return RELEASE_7;
case JDK1_8:
return RELEASE_8;
default:
return null;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,467 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.code;
import java.util.Map;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.comp.Annotate;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.code.Attribute.TypeCompound;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Pair;
import static com.sun.tools.javac.code.Kinds.PCK;
/**
* Container for all annotations (attributes in javac) on a Symbol.
*
* This class is explicitly mutable. Its contents will change when attributes
* are annotated onto the Symbol. However this class depends on the facts that
* List (in javac) is immutable.
*
* An instance of this class can be in one of three states:
*
* NOT_STARTED indicates that the Symbol this instance belongs to has not been
* annotated (yet). Specifically if the declaration is not annotated this
* instance will never move past NOT_STARTED. You can never go back to
* NOT_STARTED.
*
* IN_PROGRESS annotations have been found on the declaration. Will be processed
* later. You can reset to IN_PROGRESS. While IN_PROGRESS you can set the list
* of attributes (and this moves out of the IN_PROGRESS state).
*
* "unnamed" this SymbolMetadata contains some attributes, possibly the final set.
* While in this state you can only prepend or append to the attributes not set
* it directly. You can also move back to the IN_PROGRESS state using reset().
*
* <p><b>This is NOT part of any supported API. If you write code that depends
* on this, you do so at your own risk. This code and its internal interfaces
* are subject to change or deletion without notice.</b>
*/
public class SymbolMetadata {
private static final List<Attribute.Compound> DECL_NOT_STARTED = List.of(null);
private static final List<Attribute.Compound> DECL_IN_PROGRESS = List.of(null);
/*
* This field should never be null
*/
private List<Attribute.Compound> attributes = DECL_NOT_STARTED;
/*
* Type attributes for this symbol.
* This field should never be null.
*/
private List<Attribute.TypeCompound> type_attributes = List.<Attribute.TypeCompound>nil();
/*
* Type attributes of initializers in this class.
* Unused if the current symbol is not a ClassSymbol.
*/
private List<Attribute.TypeCompound> init_type_attributes = List.<Attribute.TypeCompound>nil();
/*
* Type attributes of class initializers in this class.
* Unused if the current symbol is not a ClassSymbol.
*/
private List<Attribute.TypeCompound> clinit_type_attributes = List.<Attribute.TypeCompound>nil();
/*
* The Symbol this SymbolMetadata instance belongs to
*/
private final Symbol sym;
public SymbolMetadata(Symbol sym) {
this.sym = sym;
}
public List<Attribute.Compound> getDeclarationAttributes() {
return filterDeclSentinels(attributes);
}
public List<Attribute.TypeCompound> getTypeAttributes() {
return type_attributes;
}
public List<Attribute.TypeCompound> getInitTypeAttributes() {
return init_type_attributes;
}
public List<Attribute.TypeCompound> getClassInitTypeAttributes() {
return clinit_type_attributes;
}
public void setDeclarationAttributes(List<Attribute.Compound> a) {
Assert.check(pendingCompletion() || !isStarted());
if (a == null) {
throw new NullPointerException();
}
attributes = a;
}
public void setTypeAttributes(List<Attribute.TypeCompound> a) {
if (a == null) {
throw new NullPointerException();
}
type_attributes = a;
}
public void setInitTypeAttributes(List<Attribute.TypeCompound> a) {
if (a == null) {
throw new NullPointerException();
}
init_type_attributes = a;
}
public void setClassInitTypeAttributes(List<Attribute.TypeCompound> a) {
if (a == null) {
throw new NullPointerException();
}
clinit_type_attributes = a;
}
public void setAttributes(SymbolMetadata other) {
if (other == null) {
throw new NullPointerException();
}
setDeclarationAttributes(other.getDeclarationAttributes());
if ((sym.flags() & Flags.BRIDGE) != 0) {
Assert.check(other.sym.kind == Kinds.MTH);
ListBuffer<TypeCompound> typeAttributes = new ListBuffer<>();
for (TypeCompound tc : other.getTypeAttributes()) {
// Carry over only contractual type annotations: i.e nothing interior to method body.
if (!tc.position.type.isLocal())
typeAttributes.append(tc);
}
setTypeAttributes(typeAttributes.toList());
} else {
setTypeAttributes(other.getTypeAttributes());
}
if (sym.kind == Kinds.TYP) {
setInitTypeAttributes(other.getInitTypeAttributes());
setClassInitTypeAttributes(other.getClassInitTypeAttributes());
}
}
public void setDeclarationAttributesWithCompletion(final Annotate.AnnotateRepeatedContext<Attribute.Compound> ctx) {
Assert.check(pendingCompletion() || (!isStarted() && sym.kind == PCK));
this.setDeclarationAttributes(getAttributesForCompletion(ctx));
}
public void appendTypeAttributesWithCompletion(final Annotate.AnnotateRepeatedContext<Attribute.TypeCompound> ctx) {
this.appendUniqueTypes(getAttributesForCompletion(ctx));
}
private <T extends Attribute.Compound> List<T> getAttributesForCompletion(
final Annotate.AnnotateRepeatedContext<T> ctx) {
Map<Symbol.TypeSymbol, ListBuffer<T>> annotated = ctx.annotated;
boolean atLeastOneRepeated = false;
List<T> buf = List.<T>nil();
for (ListBuffer<T> lb : annotated.values()) {
if (lb.size() == 1) {
buf = buf.prepend(lb.first());
} else { // repeated
// This will break when other subtypes of Attributs.Compound
// are introduced, because PlaceHolder is a subtype of TypeCompound.
T res;
@SuppressWarnings("unchecked")
T ph = (T) new Placeholder<T>(ctx, lb.toList(), sym);
res = ph;
buf = buf.prepend(res);
atLeastOneRepeated = true;
}
}
if (atLeastOneRepeated) {
// The Symbol s is now annotated with a combination of
// finished non-repeating annotations and placeholders for
// repeating annotations.
//
// We need to do this in two passes because when creating
// a container for a repeating annotation we must
// guarantee that the @Repeatable on the
// contained annotation is fully annotated
//
// The way we force this order is to do all repeating
// annotations in a pass after all non-repeating are
// finished. This will work because @Repeatable
// is non-repeating and therefore will be annotated in the
// fist pass.
// Queue a pass that will replace Attribute.Placeholders
// with Attribute.Compound (made from synthesized containers).
ctx.annotateRepeated(new Annotate.Worker() {
@Override
public String toString() {
return "repeated annotation pass of: " + sym + " in: " + sym.owner;
}
@Override
public void run() {
complete(ctx);
}
});
}
// Add non-repeating attributes
return buf.reverse();
}
public SymbolMetadata reset() {
attributes = DECL_IN_PROGRESS;
return this;
}
public boolean isEmpty() {
return !isStarted()
|| pendingCompletion()
|| attributes.isEmpty();
}
public boolean isTypesEmpty() {
return type_attributes.isEmpty();
}
public boolean pendingCompletion() {
return attributes == DECL_IN_PROGRESS;
}
public SymbolMetadata append(List<Attribute.Compound> l) {
attributes = filterDeclSentinels(attributes);
if (l.isEmpty()) {
; // no-op
} else if (attributes.isEmpty()) {
attributes = l;
} else {
attributes = attributes.appendList(l);
}
return this;
}
public SymbolMetadata appendUniqueTypes(List<Attribute.TypeCompound> l) {
if (l.isEmpty()) {
; // no-op
} else if (type_attributes.isEmpty()) {
type_attributes = l;
} else {
// TODO: in case we expect a large number of annotations, this
// might be inefficient.
for (Attribute.TypeCompound tc : l) {
if (!type_attributes.contains(tc))
type_attributes = type_attributes.append(tc);
}
}
return this;
}
public SymbolMetadata appendInitTypeAttributes(List<Attribute.TypeCompound> l) {
if (l.isEmpty()) {
; // no-op
} else if (init_type_attributes.isEmpty()) {
init_type_attributes = l;
} else {
init_type_attributes = init_type_attributes.appendList(l);
}
return this;
}
public SymbolMetadata appendClassInitTypeAttributes(List<Attribute.TypeCompound> l) {
if (l.isEmpty()) {
; // no-op
} else if (clinit_type_attributes.isEmpty()) {
clinit_type_attributes = l;
} else {
clinit_type_attributes = clinit_type_attributes.appendList(l);
}
return this;
}
public SymbolMetadata prepend(List<Attribute.Compound> l) {
attributes = filterDeclSentinels(attributes);
if (l.isEmpty()) {
; // no-op
} else if (attributes.isEmpty()) {
attributes = l;
} else {
attributes = attributes.prependList(l);
}
return this;
}
private List<Attribute.Compound> filterDeclSentinels(List<Attribute.Compound> a) {
return (a == DECL_IN_PROGRESS || a == DECL_NOT_STARTED)
? List.<Attribute.Compound>nil()
: a;
}
private boolean isStarted() {
return attributes != DECL_NOT_STARTED;
}
private List<Attribute.Compound> getPlaceholders() {
List<Attribute.Compound> res = List.<Attribute.Compound>nil();
for (Attribute.Compound a : filterDeclSentinels(attributes)) {
if (a instanceof Placeholder) {
res = res.prepend(a);
}
}
return res.reverse();
}
private List<Attribute.TypeCompound> getTypePlaceholders() {
List<Attribute.TypeCompound> res = List.<Attribute.TypeCompound>nil();
for (Attribute.TypeCompound a : type_attributes) {
if (a instanceof Placeholder) {
res = res.prepend(a);
}
}
return res.reverse();
}
/*
* Replace Placeholders for repeating annotations with their containers
*/
private <T extends Attribute.Compound> void complete(Annotate.AnnotateRepeatedContext<T> ctx) {
Log log = ctx.log;
Env<AttrContext> env = ctx.env;
JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
try {
// TODO: can we reduce duplication in the following branches?
if (ctx.isTypeCompound) {
Assert.check(!isTypesEmpty());
if (isTypesEmpty()) {
return;
}
List<Attribute.TypeCompound> result = List.nil();
for (Attribute.TypeCompound a : getTypeAttributes()) {
if (a instanceof Placeholder) {
@SuppressWarnings("unchecked")
Placeholder<Attribute.TypeCompound> ph = (Placeholder<Attribute.TypeCompound>) a;
Attribute.TypeCompound replacement = replaceOne(ph, ph.getRepeatedContext());
if (null != replacement) {
result = result.prepend(replacement);
}
} else {
result = result.prepend(a);
}
}
type_attributes = result.reverse();
Assert.check(SymbolMetadata.this.getTypePlaceholders().isEmpty());
} else {
Assert.check(!pendingCompletion());
if (isEmpty()) {
return;
}
List<Attribute.Compound> result = List.nil();
for (Attribute.Compound a : getDeclarationAttributes()) {
if (a instanceof Placeholder) {
@SuppressWarnings("unchecked")
Attribute.Compound replacement = replaceOne((Placeholder<T>) a, ctx);
if (null != replacement) {
result = result.prepend(replacement);
}
} else {
result = result.prepend(a);
}
}
attributes = result.reverse();
Assert.check(SymbolMetadata.this.getPlaceholders().isEmpty());
}
} finally {
log.useSource(oldSource);
}
}
private <T extends Attribute.Compound> T replaceOne(Placeholder<T> placeholder, Annotate.AnnotateRepeatedContext<T> ctx) {
Log log = ctx.log;
// Process repeated annotations
T validRepeated = ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor(), sym);
if (validRepeated != null) {
// Check that the container isn't manually
// present along with repeated instances of
// its contained annotation.
ListBuffer<T> manualContainer = ctx.annotated.get(validRepeated.type.tsym);
if (manualContainer != null) {
log.error(ctx.pos.get(manualContainer.first()), "invalid.repeatable.annotation.repeated.and.container.present",
manualContainer.first().type.tsym);
}
}
// A null return will delete the Placeholder
return validRepeated;
}
private static class Placeholder<T extends Attribute.Compound> extends Attribute.TypeCompound {
private final Annotate.AnnotateRepeatedContext<T> ctx;
private final List<T> placeholderFor;
private final Symbol on;
public Placeholder(Annotate.AnnotateRepeatedContext<T> ctx, List<T> placeholderFor, Symbol on) {
super(on.type, List.<Pair<Symbol.MethodSymbol, Attribute>>nil(),
ctx.isTypeCompound ?
((Attribute.TypeCompound)placeholderFor.head).position :
new TypeAnnotationPosition());
this.ctx = ctx;
this.placeholderFor = placeholderFor;
this.on = on;
}
@Override
public String toString() {
return "<placeholder: " + placeholderFor + " on: " + on + ">";
}
public List<T> getPlaceholderFor() {
return placeholderFor;
}
public Annotate.AnnotateRepeatedContext<T> getRepeatedContext() {
return ctx;
}
}
}

View File

@@ -0,0 +1,723 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.code;
import java.util.*;
import javax.lang.model.element.ElementVisitor;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.jvm.ByteCodes.*;
import static com.sun.tools.javac.code.TypeTag.*;
/** A class that defines all predefined constants and operators
* as well as special classes such as java.lang.Object, which need
* to be known to the compiler. All symbols are held in instance
* fields. This makes it possible to work in multiple concurrent
* projects, which might use different class files for library classes.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class Symtab {
/** The context key for the symbol table. */
protected static final Context.Key<Symtab> symtabKey =
new Context.Key<Symtab>();
/** Get the symbol table instance. */
public static Symtab instance(Context context) {
Symtab instance = context.get(symtabKey);
if (instance == null)
instance = new Symtab(context);
return instance;
}
/** Builtin types.
*/
public final JCPrimitiveType byteType = new JCPrimitiveType(BYTE, null);
public final JCPrimitiveType charType = new JCPrimitiveType(CHAR, null);
public final JCPrimitiveType shortType = new JCPrimitiveType(SHORT, null);
public final JCPrimitiveType intType = new JCPrimitiveType(INT, null);
public final JCPrimitiveType longType = new JCPrimitiveType(LONG, null);
public final JCPrimitiveType floatType = new JCPrimitiveType(FLOAT, null);
public final JCPrimitiveType doubleType = new JCPrimitiveType(DOUBLE, null);
public final JCPrimitiveType booleanType = new JCPrimitiveType(BOOLEAN, null);
public final Type botType = new BottomType();
public final JCVoidType voidType = new JCVoidType();
private final Names names;
private final ClassReader reader;
private final Target target;
/** A symbol for the root package.
*/
public final PackageSymbol rootPackage;
/** A symbol for the unnamed package.
*/
public final PackageSymbol unnamedPackage;
/** A symbol that stands for a missing symbol.
*/
public final TypeSymbol noSymbol;
/** The error symbol.
*/
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;
/** A value for the unknown type. */
public final Type unknownType;
/** The builtin type of all arrays. */
public final ClassSymbol arrayClass;
public final MethodSymbol arrayCloneMethod;
/** VGJ: The (singleton) type of all bound types. */
public final ClassSymbol boundClass;
/** The builtin type of all methods. */
public final ClassSymbol methodClass;
/** Predefined types.
*/
public final Type objectType;
public final Type classType;
public final Type classLoaderType;
public final Type stringType;
public final Type stringBufferType;
public final Type stringBuilderType;
public final Type cloneableType;
public final Type serializableType;
public final Type serializedLambdaType;
public final Type methodHandleType;
public final Type methodHandleLookupType;
public final Type methodTypeType;
public final Type nativeHeaderType;
public final Type throwableType;
public final Type errorType;
public final Type interruptedExceptionType;
public final Type illegalArgumentExceptionType;
public final Type exceptionType;
public final Type runtimeExceptionType;
public final Type classNotFoundExceptionType;
public final Type noClassDefFoundErrorType;
public final Type noSuchFieldErrorType;
public final Type assertionErrorType;
public final Type cloneNotSupportedExceptionType;
public final Type annotationType;
public final TypeSymbol enumSym;
public final Type listType;
public final Type collectionsType;
public final Type comparableType;
public final Type comparatorType;
public final Type arraysType;
public final Type iterableType;
public final Type iteratorType;
public final Type annotationTargetType;
public final Type overrideType;
public final Type retentionType;
public final Type deprecatedType;
public final Type suppressWarningsType;
public final Type inheritedType;
public final Type profileType;
public final Type proprietaryType;
public final Type systemType;
public final Type autoCloseableType;
public final Type trustMeType;
public final Type lambdaMetafactory;
public final Type repeatableType;
public final Type documentedType;
public final Type elementTypeType;
public final Type functionalInterfaceType;
/** The symbol representing the length field of an array.
*/
public final VarSymbol lengthVar;
/** The null check operator. */
public final OperatorSymbol nullcheck;
/** The symbol representing the final finalize method on enums */
public final MethodSymbol enumFinalFinalize;
/** The symbol representing the close method on TWR AutoCloseable type */
public final MethodSymbol autoCloseableClose;
/** The predefined type that belongs to a tag.
*/
public final Type[] typeOfTag = new Type[TypeTag.getTypeTagCount()];
/** The name of the class that belongs to a basix type tag.
*/
public final Name[] boxedName = new Name[TypeTag.getTypeTagCount()];
/** A set containing all operator names.
*/
public final Set<Name> operatorNames = new HashSet<Name>();
/** A hashtable containing the encountered top-level and member classes,
* indexed by flat names. The table does not contain local classes.
* It should be updated from the outside to reflect classes defined
* by compiled source files.
*/
public final Map<Name, ClassSymbol> classes = new HashMap<Name, ClassSymbol>();
/** A hashtable containing the encountered packages.
* the table should be updated from outside to reflect packages defined
* by compiled source files.
*/
public final Map<Name, PackageSymbol> packages = new HashMap<Name, PackageSymbol>();
public void initType(Type type, ClassSymbol c) {
type.tsym = c;
typeOfTag[type.getTag().ordinal()] = type;
}
public void initType(Type type, String name) {
initType(
type,
new ClassSymbol(
PUBLIC, names.fromString(name), type, rootPackage));
}
public void initType(Type type, String name, String bname) {
initType(type, name);
boxedName[type.getTag().ordinal()] = names.fromString("java.lang." + bname);
}
/** The class symbol that owns all predefined symbols.
*/
public final ClassSymbol predefClass;
/** Enter a constant into symbol table.
* @param name The constant's name.
* @param type The constant's type.
*/
private VarSymbol enterConstant(String name, Type type) {
VarSymbol c = new VarSymbol(
PUBLIC | STATIC | FINAL,
names.fromString(name),
type,
predefClass);
c.setData(type.constValue());
predefClass.members().enter(c);
return c;
}
/** Enter a binary operation into symbol table.
* @param name The name of the operator.
* @param left The type of the left operand.
* @param right The type of the left operand.
* @param res The operation's result type.
* @param opcode The operation's bytecode instruction.
*/
private void enterBinop(String name,
Type left, Type right, Type res,
int opcode) {
predefClass.members().enter(
new OperatorSymbol(
makeOperatorName(name),
new MethodType(List.of(left, right), res,
List.<Type>nil(), methodClass),
opcode,
predefClass));
}
/** Enter a binary operation, as above but with two opcodes,
* which get encoded as
* {@code (opcode1 << ByteCodeTags.preShift) + opcode2 }.
* @param opcode1 First opcode.
* @param opcode2 Second opcode.
*/
private void enterBinop(String name,
Type left, Type right, Type res,
int opcode1, int opcode2) {
enterBinop(
name, left, right, res, (opcode1 << ByteCodes.preShift) | opcode2);
}
/** Enter a unary operation into symbol table.
* @param name The name of the operator.
* @param arg The type of the operand.
* @param res The operation's result type.
* @param opcode The operation's bytecode instruction.
*/
private OperatorSymbol enterUnop(String name,
Type arg,
Type res,
int opcode) {
OperatorSymbol sym =
new OperatorSymbol(makeOperatorName(name),
new MethodType(List.of(arg),
res,
List.<Type>nil(),
methodClass),
opcode,
predefClass);
predefClass.members().enter(sym);
return sym;
}
/**
* Create a new operator name from corresponding String representation
* and add the name to the set of known operator names.
*/
private Name makeOperatorName(String name) {
Name opName = names.fromString(name);
operatorNames.add(opName);
return opName;
}
/** Enter a class into symbol table.
* @param s The name of the class.
*/
private Type enterClass(String s) {
return reader.enterClass(names.fromString(s)).type;
}
public void synthesizeEmptyInterfaceIfMissing(final Type type) {
final Completer completer = type.tsym.completer;
if (completer != null) {
type.tsym.completer = new Completer() {
public void complete(Symbol sym) throws CompletionFailure {
try {
completer.complete(sym);
} catch (CompletionFailure e) {
sym.flags_field |= (PUBLIC | INTERFACE);
((ClassType) sym.type).supertype_field = objectType;
}
}
};
}
}
public void synthesizeBoxTypeIfMissing(final Type type) {
ClassSymbol sym = reader.enterClass(boxedName[type.getTag().ordinal()]);
final Completer completer = sym.completer;
if (completer != null) {
sym.completer = new Completer() {
public void complete(Symbol sym) throws CompletionFailure {
try {
completer.complete(sym);
} catch (CompletionFailure e) {
sym.flags_field |= PUBLIC;
((ClassType) sym.type).supertype_field = objectType;
Name n = target.boxWithConstructors() ? names.init : names.valueOf;
MethodSymbol boxMethod =
new MethodSymbol(PUBLIC | STATIC,
n,
new MethodType(List.of(type), sym.type,
List.<Type>nil(), methodClass),
sym);
sym.members().enter(boxMethod);
MethodSymbol unboxMethod =
new MethodSymbol(PUBLIC,
type.tsym.name.append(names.Value), // x.intValue()
new MethodType(List.<Type>nil(), type,
List.<Type>nil(), methodClass),
sym);
sym.members().enter(unboxMethod);
}
}
};
}
}
// Enter a synthetic class that is used to mark classes in ct.sym.
// This class does not have a class file.
private Type enterSyntheticAnnotation(String name) {
ClassType type = (ClassType)enterClass(name);
ClassSymbol sym = (ClassSymbol)type.tsym;
sym.completer = null;
sym.flags_field = PUBLIC|ACYCLIC|ANNOTATION|INTERFACE;
sym.erasure_field = type;
sym.members_field = new Scope(sym);
type.typarams_field = List.nil();
type.allparams_field = List.nil();
type.supertype_field = annotationType;
type.interfaces_field = List.nil();
return type;
}
/** Constructor; enters all predefined identifiers and operators
* into symbol table.
*/
protected Symtab(Context context) throws CompletionFailure {
context.put(symtabKey, this);
names = Names.instance(context);
target = Target.instance(context);
// Create the unknown type
unknownType = new UnknownType();
// create the basic builtin symbols
rootPackage = new PackageSymbol(names.empty, null);
final JavacMessages messages = JavacMessages.instance(context);
unnamedPackage = new PackageSymbol(names.empty, rootPackage) {
public String toString() {
return messages.getLocalizedString("compiler.misc.unnamed.package");
}
};
noSymbol = new TypeSymbol(Kinds.NIL, 0, names.empty, Type.noType, rootPackage) {
public <R, P> R accept(ElementVisitor<R, P> v, P p) {
return v.visitUnknown(this, p);
}
};
// create the error symbols
errSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.any, null, rootPackage);
errType = new ErrorType(errSymbol, Type.noType);
unknownSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.fromString("<any?>"), null, rootPackage);
unknownSymbol.members_field = new Scope.ErrorScope(unknownSymbol);
unknownSymbol.type = unknownType;
// initialize builtin types
initType(byteType, "byte", "Byte");
initType(shortType, "short", "Short");
initType(charType, "char", "Character");
initType(intType, "int", "Integer");
initType(longType, "long", "Long");
initType(floatType, "float", "Float");
initType(doubleType, "double", "Double");
initType(booleanType, "boolean", "Boolean");
initType(voidType, "void", "Void");
initType(botType, "<nulltype>");
initType(errType, errSymbol);
initType(unknownType, unknownSymbol);
// the builtin class of all arrays
arrayClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Array, noSymbol);
// VGJ
boundClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Bound, noSymbol);
boundClass.members_field = new Scope.ErrorScope(boundClass);
// the builtin class of all methods
methodClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Method, noSymbol);
methodClass.members_field = new Scope.ErrorScope(boundClass);
// Create class to hold all predefined constants and operations.
predefClass = new ClassSymbol(PUBLIC|ACYCLIC, names.empty, rootPackage);
Scope scope = new Scope(predefClass);
predefClass.members_field = scope;
// Enter symbols for basic types.
scope.enter(byteType.tsym);
scope.enter(shortType.tsym);
scope.enter(charType.tsym);
scope.enter(intType.tsym);
scope.enter(longType.tsym);
scope.enter(floatType.tsym);
scope.enter(doubleType.tsym);
scope.enter(booleanType.tsym);
scope.enter(errType.tsym);
// Enter symbol for the errSymbol
scope.enter(errSymbol);
classes.put(predefClass.fullname, predefClass);
reader = ClassReader.instance(context);
reader.init(this);
// Enter predefined classes.
objectType = enterClass("java.lang.Object");
classType = enterClass("java.lang.Class");
stringType = enterClass("java.lang.String");
stringBufferType = enterClass("java.lang.StringBuffer");
stringBuilderType = enterClass("java.lang.StringBuilder");
cloneableType = enterClass("java.lang.Cloneable");
throwableType = enterClass("java.lang.Throwable");
serializableType = enterClass("java.io.Serializable");
serializedLambdaType = enterClass("java.lang.invoke.SerializedLambda");
methodHandleType = enterClass("java.lang.invoke.MethodHandle");
methodHandleLookupType = enterClass("java.lang.invoke.MethodHandles$Lookup");
methodTypeType = enterClass("java.lang.invoke.MethodType");
errorType = enterClass("java.lang.Error");
illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException");
interruptedExceptionType = enterClass("java.lang.InterruptedException");
exceptionType = enterClass("java.lang.Exception");
runtimeExceptionType = enterClass("java.lang.RuntimeException");
classNotFoundExceptionType = enterClass("java.lang.ClassNotFoundException");
noClassDefFoundErrorType = enterClass("java.lang.NoClassDefFoundError");
noSuchFieldErrorType = enterClass("java.lang.NoSuchFieldError");
assertionErrorType = enterClass("java.lang.AssertionError");
cloneNotSupportedExceptionType = enterClass("java.lang.CloneNotSupportedException");
annotationType = enterClass("java.lang.annotation.Annotation");
classLoaderType = enterClass("java.lang.ClassLoader");
enumSym = reader.enterClass(names.java_lang_Enum);
enumFinalFinalize =
new MethodSymbol(PROTECTED|FINAL|HYPOTHETICAL,
names.finalize,
new MethodType(List.<Type>nil(), voidType,
List.<Type>nil(), methodClass),
enumSym);
listType = enterClass("java.util.List");
collectionsType = enterClass("java.util.Collections");
comparableType = enterClass("java.lang.Comparable");
comparatorType = enterClass("java.util.Comparator");
arraysType = enterClass("java.util.Arrays");
iterableType = target.hasIterable()
? enterClass("java.lang.Iterable")
: enterClass("java.util.Collection");
iteratorType = enterClass("java.util.Iterator");
annotationTargetType = enterClass("java.lang.annotation.Target");
overrideType = enterClass("java.lang.Override");
retentionType = enterClass("java.lang.annotation.Retention");
deprecatedType = enterClass("java.lang.Deprecated");
suppressWarningsType = enterClass("java.lang.SuppressWarnings");
inheritedType = enterClass("java.lang.annotation.Inherited");
repeatableType = enterClass("java.lang.annotation.Repeatable");
documentedType = enterClass("java.lang.annotation.Documented");
elementTypeType = enterClass("java.lang.annotation.ElementType");
systemType = enterClass("java.lang.System");
autoCloseableType = enterClass("java.lang.AutoCloseable");
autoCloseableClose = new MethodSymbol(PUBLIC,
names.close,
new MethodType(List.<Type>nil(), voidType,
List.of(exceptionType), methodClass),
autoCloseableType.tsym);
trustMeType = enterClass("java.lang.SafeVarargs");
nativeHeaderType = enterClass("java.lang.annotation.Native");
lambdaMetafactory = enterClass("java.lang.invoke.LambdaMetafactory");
functionalInterfaceType = enterClass("java.lang.FunctionalInterface");
synthesizeEmptyInterfaceIfMissing(autoCloseableType);
synthesizeEmptyInterfaceIfMissing(cloneableType);
synthesizeEmptyInterfaceIfMissing(serializableType);
synthesizeEmptyInterfaceIfMissing(lambdaMetafactory);
synthesizeEmptyInterfaceIfMissing(serializedLambdaType);
synthesizeBoxTypeIfMissing(doubleType);
synthesizeBoxTypeIfMissing(floatType);
synthesizeBoxTypeIfMissing(voidType);
// Enter a synthetic class that is used to mark internal
// proprietary classes in ct.sym. This class does not have a
// class file.
proprietaryType = enterSyntheticAnnotation("sun.Proprietary+Annotation");
// Enter a synthetic class that is used to provide profile info for
// classes in ct.sym. This class does not have a class file.
profileType = enterSyntheticAnnotation("jdk.Profile+Annotation");
MethodSymbol m = new MethodSymbol(PUBLIC | ABSTRACT, names.value, intType, profileType.tsym);
profileType.tsym.members().enter(m);
// Enter a class for arrays.
// The class implements java.lang.Cloneable and java.io.Serializable.
// It has a final length field and a clone method.
ClassType arrayClassType = (ClassType)arrayClass.type;
arrayClassType.supertype_field = objectType;
arrayClassType.interfaces_field = List.of(cloneableType, serializableType);
arrayClass.members_field = new Scope(arrayClass);
lengthVar = new VarSymbol(
PUBLIC | FINAL,
names.length,
intType,
arrayClass);
arrayClass.members().enter(lengthVar);
arrayCloneMethod = new MethodSymbol(
PUBLIC,
names.clone,
new MethodType(List.<Type>nil(), objectType,
List.<Type>nil(), methodClass),
arrayClass);
arrayClass.members().enter(arrayCloneMethod);
// Enter operators.
/* Internally we use +++, --- for unary +, - to reduce +, - operators
* overloading
*/
enterUnop("+++", doubleType, doubleType, nop);
enterUnop("+++", floatType, floatType, nop);
enterUnop("+++", longType, longType, nop);
enterUnop("+++", intType, intType, nop);
enterUnop("---", doubleType, doubleType, dneg);
enterUnop("---", floatType, floatType, fneg);
enterUnop("---", longType, longType, lneg);
enterUnop("---", intType, intType, ineg);
enterUnop("~", longType, longType, lxor);
enterUnop("~", intType, intType, ixor);
enterUnop("++", doubleType, doubleType, dadd);
enterUnop("++", floatType, floatType, fadd);
enterUnop("++", longType, longType, ladd);
enterUnop("++", intType, intType, iadd);
enterUnop("++", charType, charType, iadd);
enterUnop("++", shortType, shortType, iadd);
enterUnop("++", byteType, byteType, iadd);
enterUnop("--", doubleType, doubleType, dsub);
enterUnop("--", floatType, floatType, fsub);
enterUnop("--", longType, longType, lsub);
enterUnop("--", intType, intType, isub);
enterUnop("--", charType, charType, isub);
enterUnop("--", shortType, shortType, isub);
enterUnop("--", byteType, byteType, isub);
enterUnop("!", booleanType, booleanType, bool_not);
nullcheck = enterUnop("<*nullchk*>", objectType, objectType, nullchk);
// string concatenation
enterBinop("+", stringType, objectType, stringType, string_add);
enterBinop("+", objectType, stringType, stringType, string_add);
enterBinop("+", stringType, stringType, stringType, string_add);
enterBinop("+", stringType, intType, stringType, string_add);
enterBinop("+", stringType, longType, stringType, string_add);
enterBinop("+", stringType, floatType, stringType, string_add);
enterBinop("+", stringType, doubleType, stringType, string_add);
enterBinop("+", stringType, booleanType, stringType, string_add);
enterBinop("+", stringType, botType, stringType, string_add);
enterBinop("+", intType, stringType, stringType, string_add);
enterBinop("+", longType, stringType, stringType, string_add);
enterBinop("+", floatType, stringType, stringType, string_add);
enterBinop("+", doubleType, stringType, stringType, string_add);
enterBinop("+", booleanType, stringType, stringType, string_add);
enterBinop("+", botType, stringType, stringType, string_add);
// these errors would otherwise be matched as string concatenation
enterBinop("+", botType, botType, botType, error);
enterBinop("+", botType, intType, botType, error);
enterBinop("+", botType, longType, botType, error);
enterBinop("+", botType, floatType, botType, error);
enterBinop("+", botType, doubleType, botType, error);
enterBinop("+", botType, booleanType, botType, error);
enterBinop("+", botType, objectType, botType, error);
enterBinop("+", intType, botType, botType, error);
enterBinop("+", longType, botType, botType, error);
enterBinop("+", floatType, botType, botType, error);
enterBinop("+", doubleType, botType, botType, error);
enterBinop("+", booleanType, botType, botType, error);
enterBinop("+", objectType, botType, botType, error);
enterBinop("+", doubleType, doubleType, doubleType, dadd);
enterBinop("+", floatType, floatType, floatType, fadd);
enterBinop("+", longType, longType, longType, ladd);
enterBinop("+", intType, intType, intType, iadd);
enterBinop("-", doubleType, doubleType, doubleType, dsub);
enterBinop("-", floatType, floatType, floatType, fsub);
enterBinop("-", longType, longType, longType, lsub);
enterBinop("-", intType, intType, intType, isub);
enterBinop("*", doubleType, doubleType, doubleType, dmul);
enterBinop("*", floatType, floatType, floatType, fmul);
enterBinop("*", longType, longType, longType, lmul);
enterBinop("*", intType, intType, intType, imul);
enterBinop("/", doubleType, doubleType, doubleType, ddiv);
enterBinop("/", floatType, floatType, floatType, fdiv);
enterBinop("/", longType, longType, longType, ldiv);
enterBinop("/", intType, intType, intType, idiv);
enterBinop("%", doubleType, doubleType, doubleType, dmod);
enterBinop("%", floatType, floatType, floatType, fmod);
enterBinop("%", longType, longType, longType, lmod);
enterBinop("%", intType, intType, intType, imod);
enterBinop("&", booleanType, booleanType, booleanType, iand);
enterBinop("&", longType, longType, longType, land);
enterBinop("&", intType, intType, intType, iand);
enterBinop("|", booleanType, booleanType, booleanType, ior);
enterBinop("|", longType, longType, longType, lor);
enterBinop("|", intType, intType, intType, ior);
enterBinop("^", booleanType, booleanType, booleanType, ixor);
enterBinop("^", longType, longType, longType, lxor);
enterBinop("^", intType, intType, intType, ixor);
enterBinop("<<", longType, longType, longType, lshll);
enterBinop("<<", intType, longType, intType, ishll);
enterBinop("<<", longType, intType, longType, lshl);
enterBinop("<<", intType, intType, intType, ishl);
enterBinop(">>", longType, longType, longType, lshrl);
enterBinop(">>", intType, longType, intType, ishrl);
enterBinop(">>", longType, intType, longType, lshr);
enterBinop(">>", intType, intType, intType, ishr);
enterBinop(">>>", longType, longType, longType, lushrl);
enterBinop(">>>", intType, longType, intType, iushrl);
enterBinop(">>>", longType, intType, longType, lushr);
enterBinop(">>>", intType, intType, intType, iushr);
enterBinop("<", doubleType, doubleType, booleanType, dcmpg, iflt);
enterBinop("<", floatType, floatType, booleanType, fcmpg, iflt);
enterBinop("<", longType, longType, booleanType, lcmp, iflt);
enterBinop("<", intType, intType, booleanType, if_icmplt);
enterBinop(">", doubleType, doubleType, booleanType, dcmpl, ifgt);
enterBinop(">", floatType, floatType, booleanType, fcmpl, ifgt);
enterBinop(">", longType, longType, booleanType, lcmp, ifgt);
enterBinop(">", intType, intType, booleanType, if_icmpgt);
enterBinop("<=", doubleType, doubleType, booleanType, dcmpg, ifle);
enterBinop("<=", floatType, floatType, booleanType, fcmpg, ifle);
enterBinop("<=", longType, longType, booleanType, lcmp, ifle);
enterBinop("<=", intType, intType, booleanType, if_icmple);
enterBinop(">=", doubleType, doubleType, booleanType, dcmpl, ifge);
enterBinop(">=", floatType, floatType, booleanType, fcmpl, ifge);
enterBinop(">=", longType, longType, booleanType, lcmp, ifge);
enterBinop(">=", intType, intType, booleanType, if_icmpge);
enterBinop("==", objectType, objectType, booleanType, if_acmpeq);
enterBinop("==", booleanType, booleanType, booleanType, if_icmpeq);
enterBinop("==", doubleType, doubleType, booleanType, dcmpl, ifeq);
enterBinop("==", floatType, floatType, booleanType, fcmpl, ifeq);
enterBinop("==", longType, longType, booleanType, lcmp, ifeq);
enterBinop("==", intType, intType, booleanType, if_icmpeq);
enterBinop("!=", objectType, objectType, booleanType, if_acmpne);
enterBinop("!=", booleanType, booleanType, booleanType, if_icmpne);
enterBinop("!=", doubleType, doubleType, booleanType, dcmpl, ifne);
enterBinop("!=", floatType, floatType, booleanType, fcmpl, ifne);
enterBinop("!=", longType, longType, booleanType, lcmp, ifne);
enterBinop("!=", intType, intType, booleanType, if_icmpne);
enterBinop("&&", booleanType, booleanType, booleanType, bool_and);
enterBinop("||", booleanType, booleanType, booleanType, bool_or);
}
}

View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.code;
import com.sun.tools.javac.util.Assert;
/**
* Describes the type of program element an extended annotation (or extended
* compound attribute) targets.
*
* By comparison, a Tree.Kind has enum values for all elements in the AST, and
* it does not provide enough resolution for type arguments (i.e., whether an
* annotation targets a type argument in a local variable, method return type,
* or a typecast).
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
// Code duplicated in com.sun.tools.classfile.TypeAnnotation.TargetType
public enum TargetType {
/** For annotations on a class type parameter declaration. */
CLASS_TYPE_PARAMETER(0x00),
/** For annotations on a method type parameter declaration. */
METHOD_TYPE_PARAMETER(0x01),
/** For annotations on the type of an "extends" or "implements" clause. */
CLASS_EXTENDS(0x10),
/** For annotations on a bound of a type parameter of a class. */
CLASS_TYPE_PARAMETER_BOUND(0x11),
/** For annotations on a bound of a type parameter of a method. */
METHOD_TYPE_PARAMETER_BOUND(0x12),
/** For annotations on a field. */
FIELD(0x13),
/** For annotations on a method return type. */
METHOD_RETURN(0x14),
/** For annotations on the method receiver. */
METHOD_RECEIVER(0x15),
/** For annotations on a method parameter. */
METHOD_FORMAL_PARAMETER(0x16),
/** For annotations on a throws clause in a method declaration. */
THROWS(0x17),
/** For annotations on a local variable. */
LOCAL_VARIABLE(0x40, true),
/** For annotations on a resource variable. */
RESOURCE_VARIABLE(0x41, true),
/** For annotations on an exception parameter. */
EXCEPTION_PARAMETER(0x42, true),
/** For annotations on a type test. */
INSTANCEOF(0x43, true),
/** For annotations on an object creation expression. */
NEW(0x44, true),
/** For annotations on a constructor reference receiver. */
CONSTRUCTOR_REFERENCE(0x45, true),
/** For annotations on a method reference receiver. */
METHOD_REFERENCE(0x46, true),
/** For annotations on a typecast. */
CAST(0x47, true),
/** For annotations on a type argument of an object creation expression. */
CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(0x48, true),
/** For annotations on a type argument of a method call. */
METHOD_INVOCATION_TYPE_ARGUMENT(0x49, true),
/** For annotations on a type argument of a constructor reference. */
CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT(0x4A, true),
/** For annotations on a type argument of a method reference. */
METHOD_REFERENCE_TYPE_ARGUMENT(0x4B, true),
/** For annotations with an unknown target. */
UNKNOWN(0xFF);
private static final int MAXIMUM_TARGET_TYPE_VALUE = 0x4B;
private final int targetTypeValue;
private final boolean isLocal;
private TargetType(int targetTypeValue) {
this(targetTypeValue, false);
}
private TargetType(int targetTypeValue, boolean isLocal) {
if (targetTypeValue < 0
|| targetTypeValue > 255)
Assert.error("Attribute type value needs to be an unsigned byte: " + String.format("0x%02X", targetTypeValue));
this.targetTypeValue = targetTypeValue;
this.isLocal = isLocal;
}
/**
* Returns whether or not this TargetType represents an annotation whose
* target is exclusively a tree in a method body
*
* Note: wildcard bound targets could target a local tree and a class
* member declaration signature tree
*/
public boolean isLocal() {
return isLocal;
}
public int targetTypeValue() {
return this.targetTypeValue;
}
private static final TargetType[] targets;
static {
targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1];
TargetType[] alltargets = values();
for (TargetType target : alltargets) {
if (target.targetTypeValue != UNKNOWN.targetTypeValue)
targets[target.targetTypeValue] = target;
}
for (int i = 0; i <= MAXIMUM_TARGET_TYPE_VALUE; ++i) {
if (targets[i] == null)
targets[i] = UNKNOWN;
}
}
public static boolean isValidTargetTypeValue(int tag) {
if (tag == UNKNOWN.targetTypeValue)
return true;
return (tag >= 0 && tag < targets.length);
}
public static TargetType fromTargetTypeValue(int tag) {
if (tag == UNKNOWN.targetTypeValue)
return UNKNOWN;
if (tag < 0 || tag >= targets.length)
Assert.error("Unknown TargetType: " + tag);
return targets[tag];
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,326 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.code;
import java.util.Iterator;
import com.sun.tools.javac.tree.JCTree.JCLambda;
import com.sun.tools.javac.util.*;
/** A type annotation position.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
// Code duplicated in com.sun.tools.classfile.TypeAnnotation.Position
public class TypeAnnotationPosition {
public enum TypePathEntryKind {
ARRAY(0),
INNER_TYPE(1),
WILDCARD(2),
TYPE_ARGUMENT(3);
public final int tag;
private TypePathEntryKind(int tag) {
this.tag = tag;
}
}
public static class TypePathEntry {
/** The fixed number of bytes per TypePathEntry. */
public static final int bytesPerEntry = 2;
public final TypePathEntryKind tag;
public final int arg;
public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY);
public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE);
public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD);
private TypePathEntry(TypePathEntryKind tag) {
Assert.check(tag == TypePathEntryKind.ARRAY ||
tag == TypePathEntryKind.INNER_TYPE ||
tag == TypePathEntryKind.WILDCARD,
"Invalid TypePathEntryKind: " + tag);
this.tag = tag;
this.arg = 0;
}
public TypePathEntry(TypePathEntryKind tag, int arg) {
Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT,
"Invalid TypePathEntryKind: " + tag);
this.tag = tag;
this.arg = arg;
}
public static TypePathEntry fromBinary(int tag, int arg) {
Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag,
"Invalid TypePathEntry tag/arg: " + tag + "/" + arg);
switch (tag) {
case 0:
return ARRAY;
case 1:
return INNER_TYPE;
case 2:
return WILDCARD;
case 3:
return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg);
default:
Assert.error("Invalid TypePathEntryKind tag: " + tag);
return null;
}
}
@Override
public String toString() {
return tag.toString() +
(tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : "");
}
@Override
public boolean equals(Object other) {
if (! (other instanceof TypePathEntry)) {
return false;
}
TypePathEntry tpe = (TypePathEntry) other;
return this.tag == tpe.tag && this.arg == tpe.arg;
}
@Override
public int hashCode() {
return this.tag.hashCode() * 17 + this.arg;
}
}
public TargetType type = TargetType.UNKNOWN;
// For generic/array types.
public List<TypePathEntry> location = List.nil();
// Tree position.
public int pos = -1;
// For type casts, type tests, new, locals (as start_pc),
// and method and constructor reference type arguments.
public boolean isValidOffset = false;
public int offset = -1;
// For locals. arrays same length
public int[] lvarOffset = null;
public int[] lvarLength = null;
public int[] lvarIndex = null;
// For type parameter bound
public int bound_index = Integer.MIN_VALUE;
// For type parameter and method parameter
public int parameter_index = Integer.MIN_VALUE;
// For class extends, implements, and throws clauses
public int type_index = Integer.MIN_VALUE;
// For exception parameters, index into exception table.
// In com.sun.tools.javac.jvm.Gen.genCatch we first set the type_index
// to the catch type index - that value is only temporary.
// Then in com.sun.tools.javac.jvm.Code.fillExceptionParameterPositions
// we use that value to determine the exception table index.
public int exception_index = Integer.MIN_VALUE;
// If this type annotation is within a lambda expression,
// store a pointer to the lambda expression tree in order
// to allow a later translation to the right method.
public JCLambda onLambda = null;
public TypeAnnotationPosition() {}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
sb.append(type);
switch (type) {
// instanceof
case INSTANCEOF:
// new expression
case NEW:
// constructor/method reference receiver
case CONSTRUCTOR_REFERENCE:
case METHOD_REFERENCE:
sb.append(", offset = ");
sb.append(offset);
break;
// local variable
case LOCAL_VARIABLE:
// resource variable
case RESOURCE_VARIABLE:
if (lvarOffset == null) {
sb.append(", lvarOffset is null!");
break;
}
sb.append(", {");
for (int i = 0; i < lvarOffset.length; ++i) {
if (i != 0) sb.append("; ");
sb.append("start_pc = ");
sb.append(lvarOffset[i]);
sb.append(", length = ");
sb.append(lvarLength[i]);
sb.append(", index = ");
sb.append(lvarIndex[i]);
}
sb.append("}");
break;
// method receiver
case METHOD_RECEIVER:
// Do nothing
break;
// type parameter
case CLASS_TYPE_PARAMETER:
case METHOD_TYPE_PARAMETER:
sb.append(", param_index = ");
sb.append(parameter_index);
break;
// type parameter bound
case CLASS_TYPE_PARAMETER_BOUND:
case METHOD_TYPE_PARAMETER_BOUND:
sb.append(", param_index = ");
sb.append(parameter_index);
sb.append(", bound_index = ");
sb.append(bound_index);
break;
// class extends or implements clause
case CLASS_EXTENDS:
sb.append(", type_index = ");
sb.append(type_index);
break;
// throws
case THROWS:
sb.append(", type_index = ");
sb.append(type_index);
break;
// exception parameter
case EXCEPTION_PARAMETER:
sb.append(", exception_index = ");
sb.append(exception_index);
break;
// method parameter
case METHOD_FORMAL_PARAMETER:
sb.append(", param_index = ");
sb.append(parameter_index);
break;
// type cast
case CAST:
// method/constructor/reference type argument
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
case METHOD_INVOCATION_TYPE_ARGUMENT:
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
case METHOD_REFERENCE_TYPE_ARGUMENT:
sb.append(", offset = ");
sb.append(offset);
sb.append(", type_index = ");
sb.append(type_index);
break;
// We don't need to worry about these
case METHOD_RETURN:
case FIELD:
break;
case UNKNOWN:
sb.append(", position UNKNOWN!");
break;
default:
Assert.error("Unknown target type: " + type);
}
// Append location data for generics/arrays.
if (!location.isEmpty()) {
sb.append(", location = (");
sb.append(location);
sb.append(")");
}
sb.append(", pos = ");
sb.append(pos);
if (onLambda != null) {
sb.append(", onLambda hash = ");
sb.append(onLambda.hashCode());
}
sb.append(']');
return sb.toString();
}
/**
* Indicates whether the target tree of the annotation has been optimized
* away from classfile or not.
* @return true if the target has not been optimized away
*/
public boolean emitToClassfile() {
return !type.isLocal() || isValidOffset;
}
public boolean matchesPos(int pos) {
return this.pos == pos;
}
public void updatePosOffset(int to) {
offset = to;
lvarOffset = new int[]{to};
isValidOffset = true;
}
/**
* Decode the binary representation for a type path and set
* the {@code location} field.
*
* @param list The bytecode representation of the type path.
*/
public static List<TypePathEntry> getTypePathFromBinary(java.util.List<Integer> list) {
ListBuffer<TypePathEntry> loc = new ListBuffer<>();
Iterator<Integer> iter = list.iterator();
while (iter.hasNext()) {
Integer fst = iter.next();
Assert.check(iter.hasNext(), "Could not decode type path: " + list);
Integer snd = iter.next();
loc = loc.append(TypePathEntry.fromBinary(fst, snd));
}
return loc.toList();
}
public static List<Integer> getBinaryFromTypePath(java.util.List<TypePathEntry> locs) {
ListBuffer<Integer> loc = new ListBuffer<>();
for (TypePathEntry tpe : locs) {
loc = loc.append(tpe.tag.tag);
loc = loc.append(tpe.arg);
}
return loc.toList();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,240 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.code;
import com.sun.source.tree.Tree.Kind;
import javax.lang.model.type.TypeKind;
import static com.sun.tools.javac.code.TypeTag.NumericClasses.*;
/** An interface for type tag values, which distinguish between different
* sorts of types.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public enum TypeTag {
/** The tag of the basic type `byte'.
*/
BYTE(BYTE_CLASS, BYTE_SUPERCLASSES, true),
/** The tag of the basic type `char'.
*/
CHAR(CHAR_CLASS, CHAR_SUPERCLASSES, true),
/** The tag of the basic type `short'.
*/
SHORT(SHORT_CLASS, SHORT_SUPERCLASSES, true),
/** The tag of the basic type `long'.
*/
LONG(LONG_CLASS, LONG_SUPERCLASSES, true),
/** The tag of the basic type `float'.
*/
FLOAT(FLOAT_CLASS, FLOAT_SUPERCLASSES, true),
/** The tag of the basic type `int'.
*/
INT(INT_CLASS, INT_SUPERCLASSES, true),
/** The tag of the basic type `double'.
*/
DOUBLE(DOUBLE_CLASS, DOUBLE_CLASS, true),
/** The tag of the basic type `boolean'.
*/
BOOLEAN(0, 0, true),
/** The tag of the type `void'.
*/
VOID,
/** The tag of all class and interface types.
*/
CLASS,
/** The tag of all array types.
*/
ARRAY,
/** The tag of all (monomorphic) method types.
*/
METHOD,
/** The tag of all package "types".
*/
PACKAGE,
/** The tag of all (source-level) type variables.
*/
TYPEVAR,
/** The tag of all type arguments.
*/
WILDCARD,
/** The tag of all polymorphic (method-) types.
*/
FORALL,
/** The tag of deferred expression types in method context
*/
DEFERRED,
/** The tag of the bottom type {@code <null>}.
*/
BOT,
/** The tag of a missing type.
*/
NONE,
/** The tag of the error type.
*/
ERROR,
/** The tag of an unknown type
*/
UNKNOWN,
/** The tag of all instantiatable type variables.
*/
UNDETVAR,
/** Pseudo-types, these are special tags
*/
UNINITIALIZED_THIS,
UNINITIALIZED_OBJECT;
final int superClasses;
final int numericClass;
final boolean isPrimitive;
private TypeTag() {
this(0, 0, false);
}
private TypeTag(int numericClass, int superClasses, boolean isPrimitive) {
this.superClasses = superClasses;
this.numericClass = numericClass;
this.isPrimitive = isPrimitive;
}
public static class NumericClasses {
public static final int BYTE_CLASS = 1;
public static final int CHAR_CLASS = 2;
public static final int SHORT_CLASS = 4;
public static final int INT_CLASS = 8;
public static final int LONG_CLASS = 16;
public static final int FLOAT_CLASS = 32;
public static final int DOUBLE_CLASS = 64;
static final int BYTE_SUPERCLASSES = BYTE_CLASS | SHORT_CLASS | INT_CLASS |
LONG_CLASS | FLOAT_CLASS | DOUBLE_CLASS;
static final int CHAR_SUPERCLASSES = CHAR_CLASS | INT_CLASS |
LONG_CLASS | FLOAT_CLASS | DOUBLE_CLASS;
static final int SHORT_SUPERCLASSES = SHORT_CLASS | INT_CLASS |
LONG_CLASS | FLOAT_CLASS | DOUBLE_CLASS;
static final int INT_SUPERCLASSES = INT_CLASS | LONG_CLASS | FLOAT_CLASS | DOUBLE_CLASS;
static final int LONG_SUPERCLASSES = LONG_CLASS | FLOAT_CLASS | DOUBLE_CLASS;
static final int FLOAT_SUPERCLASSES = FLOAT_CLASS | DOUBLE_CLASS;
}
public boolean isStrictSubRangeOf(TypeTag tag) {
/* Please don't change the implementation of this method to call method
* isSubRangeOf. Both methods are called from hotspot code, the current
* implementation is better performance-wise than the commented modification.
*/
return (this.superClasses & tag.numericClass) != 0 && this != tag;
}
public boolean isSubRangeOf(TypeTag tag) {
return (this.superClasses & tag.numericClass) != 0;
}
/** Returns the number of type tags.
*/
public static int getTypeTagCount() {
// last two tags are not included in the total as long as they are pseudo-types
return (UNDETVAR.ordinal() + 1);
}
public Kind getKindLiteral() {
switch (this) {
case INT:
return Kind.INT_LITERAL;
case LONG:
return Kind.LONG_LITERAL;
case FLOAT:
return Kind.FLOAT_LITERAL;
case DOUBLE:
return Kind.DOUBLE_LITERAL;
case BOOLEAN:
return Kind.BOOLEAN_LITERAL;
case CHAR:
return Kind.CHAR_LITERAL;
case CLASS:
return Kind.STRING_LITERAL;
case BOT:
return Kind.NULL_LITERAL;
default:
throw new AssertionError("unknown literal kind " + this);
}
}
public TypeKind getPrimitiveTypeKind() {
switch (this) {
case BOOLEAN:
return TypeKind.BOOLEAN;
case BYTE:
return TypeKind.BYTE;
case SHORT:
return TypeKind.SHORT;
case INT:
return TypeKind.INT;
case LONG:
return TypeKind.LONG;
case CHAR:
return TypeKind.CHAR;
case FLOAT:
return TypeKind.FLOAT;
case DOUBLE:
return TypeKind.DOUBLE;
case VOID:
return TypeKind.VOID;
default:
throw new AssertionError("unknown primitive type " + this);
}
}
}

File diff suppressed because it is too large Load Diff