feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
683
jdkSrc/jdk8/com/sun/tools/javac/comp/Annotate.java
Normal file
683
jdkSrc/jdk8/com/sun/tools/javac/comp/Annotate.java
Normal file
@@ -0,0 +1,683 @@
|
||||
/*
|
||||
* 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.comp;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.tree.*;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
|
||||
import static com.sun.tools.javac.code.TypeTag.ARRAY;
|
||||
import static com.sun.tools.javac.code.TypeTag.CLASS;
|
||||
import static com.sun.tools.javac.tree.JCTree.Tag.*;
|
||||
import javax.lang.model.type.ErrorType;
|
||||
|
||||
/** Enter annotations on symbols. Annotations accumulate in a queue,
|
||||
* which is processed at the top level of any set of recursive calls
|
||||
* requesting it be processed.
|
||||
*
|
||||
* <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 Annotate {
|
||||
protected static final Context.Key<Annotate> annotateKey =
|
||||
new Context.Key<Annotate>();
|
||||
|
||||
public static Annotate instance(Context context) {
|
||||
Annotate instance = context.get(annotateKey);
|
||||
if (instance == null)
|
||||
instance = new Annotate(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
final Attr attr;
|
||||
final TreeMaker make;
|
||||
final Log log;
|
||||
final Symtab syms;
|
||||
final Names names;
|
||||
final Resolve rs;
|
||||
final Types types;
|
||||
final ConstFold cfolder;
|
||||
final Check chk;
|
||||
|
||||
protected Annotate(Context context) {
|
||||
context.put(annotateKey, this);
|
||||
attr = Attr.instance(context);
|
||||
make = TreeMaker.instance(context);
|
||||
log = Log.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
names = Names.instance(context);
|
||||
rs = Resolve.instance(context);
|
||||
types = Types.instance(context);
|
||||
cfolder = ConstFold.instance(context);
|
||||
chk = Check.instance(context);
|
||||
}
|
||||
|
||||
/* ********************************************************************
|
||||
* Queue maintenance
|
||||
*********************************************************************/
|
||||
|
||||
private int enterCount = 0;
|
||||
|
||||
ListBuffer<Worker> q = new ListBuffer<Worker>();
|
||||
ListBuffer<Worker> typesQ = new ListBuffer<Worker>();
|
||||
ListBuffer<Worker> repeatedQ = new ListBuffer<Worker>();
|
||||
ListBuffer<Worker> afterRepeatedQ = new ListBuffer<Worker>();
|
||||
ListBuffer<Worker> validateQ = new ListBuffer<Worker>();
|
||||
|
||||
public void earlier(Worker a) {
|
||||
q.prepend(a);
|
||||
}
|
||||
|
||||
public void normal(Worker a) {
|
||||
q.append(a);
|
||||
}
|
||||
|
||||
public void typeAnnotation(Worker a) {
|
||||
typesQ.append(a);
|
||||
}
|
||||
|
||||
public void repeated(Worker a) {
|
||||
repeatedQ.append(a);
|
||||
}
|
||||
|
||||
public void afterRepeated(Worker a) {
|
||||
afterRepeatedQ.append(a);
|
||||
}
|
||||
|
||||
public void validate(Worker a) {
|
||||
validateQ.append(a);
|
||||
}
|
||||
|
||||
/** Called when the Enter phase starts. */
|
||||
public void enterStart() {
|
||||
enterCount++;
|
||||
}
|
||||
|
||||
/** Called after the Enter phase completes. */
|
||||
public void enterDone() {
|
||||
enterCount--;
|
||||
flush();
|
||||
}
|
||||
|
||||
/** Variant which allows for a delayed flush of annotations.
|
||||
* Needed by ClassReader */
|
||||
public void enterDoneWithoutFlush() {
|
||||
enterCount--;
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
if (enterCount != 0) return;
|
||||
enterCount++;
|
||||
try {
|
||||
while (q.nonEmpty()) {
|
||||
q.next().run();
|
||||
}
|
||||
while (typesQ.nonEmpty()) {
|
||||
typesQ.next().run();
|
||||
}
|
||||
while (repeatedQ.nonEmpty()) {
|
||||
repeatedQ.next().run();
|
||||
}
|
||||
while (afterRepeatedQ.nonEmpty()) {
|
||||
afterRepeatedQ.next().run();
|
||||
}
|
||||
while (validateQ.nonEmpty()) {
|
||||
validateQ.next().run();
|
||||
}
|
||||
} finally {
|
||||
enterCount--;
|
||||
}
|
||||
}
|
||||
|
||||
/** A client that needs to run during {@link #flush()} registers an worker
|
||||
* into one of the queues defined in this class. The queues are: {@link #earlier(Worker)},
|
||||
* {@link #normal(Worker)}, {@link #typeAnnotation(Worker)}, {@link #repeated(Worker)},
|
||||
* {@link #afterRepeated(Worker)}, {@link #validate(Worker)}.
|
||||
* The {@link Worker#run()} method will called inside the {@link #flush()}
|
||||
* call. Queues are empties in the abovementioned order.
|
||||
*/
|
||||
public interface Worker {
|
||||
void run();
|
||||
String toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* This context contains all the information needed to synthesize new
|
||||
* annotations trees by the completer for repeating annotations.
|
||||
*/
|
||||
public class AnnotateRepeatedContext<T extends Attribute.Compound> {
|
||||
public final Env<AttrContext> env;
|
||||
public final Map<Symbol.TypeSymbol, ListBuffer<T>> annotated;
|
||||
public final Map<T, JCDiagnostic.DiagnosticPosition> pos;
|
||||
public final Log log;
|
||||
public final boolean isTypeCompound;
|
||||
|
||||
public AnnotateRepeatedContext(Env<AttrContext> env,
|
||||
Map<Symbol.TypeSymbol, ListBuffer<T>> annotated,
|
||||
Map<T, JCDiagnostic.DiagnosticPosition> pos,
|
||||
Log log,
|
||||
boolean isTypeCompound) {
|
||||
Assert.checkNonNull(env);
|
||||
Assert.checkNonNull(annotated);
|
||||
Assert.checkNonNull(pos);
|
||||
Assert.checkNonNull(log);
|
||||
|
||||
this.env = env;
|
||||
this.annotated = annotated;
|
||||
this.pos = pos;
|
||||
this.log = log;
|
||||
this.isTypeCompound = isTypeCompound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a list of repeating annotations returning a new
|
||||
* Attribute.Compound that is the attribute for the synthesized tree
|
||||
* for the container.
|
||||
*
|
||||
* @param repeatingAnnotations a List of repeating annotations
|
||||
* @return a new Attribute.Compound that is the container for the repeatingAnnotations
|
||||
*/
|
||||
public T processRepeatedAnnotations(List<T> repeatingAnnotations, Symbol sym) {
|
||||
return Annotate.this.processRepeatedAnnotations(repeatingAnnotations, this, sym);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue the Worker a on the repeating annotations queue of the
|
||||
* Annotate instance this context belongs to.
|
||||
*
|
||||
* @param a the Worker to enqueue for repeating annotation annotating
|
||||
*/
|
||||
public void annotateRepeated(Worker a) {
|
||||
Annotate.this.repeated(a);
|
||||
}
|
||||
}
|
||||
|
||||
/* ********************************************************************
|
||||
* Compute an attribute from its annotation.
|
||||
*********************************************************************/
|
||||
|
||||
/** Process a single compound annotation, returning its
|
||||
* Attribute. Used from MemberEnter for attaching the attributes
|
||||
* to the annotated symbol.
|
||||
*/
|
||||
Attribute.Compound enterAnnotation(JCAnnotation a,
|
||||
Type expected,
|
||||
Env<AttrContext> env) {
|
||||
return enterAnnotation(a, expected, env, false);
|
||||
}
|
||||
|
||||
Attribute.TypeCompound enterTypeAnnotation(JCAnnotation a,
|
||||
Type expected,
|
||||
Env<AttrContext> env) {
|
||||
return (Attribute.TypeCompound) enterAnnotation(a, expected, env, true);
|
||||
}
|
||||
|
||||
// boolean typeAnnotation determines whether the method returns
|
||||
// a Compound (false) or TypeCompound (true).
|
||||
Attribute.Compound enterAnnotation(JCAnnotation a,
|
||||
Type expected,
|
||||
Env<AttrContext> env,
|
||||
boolean typeAnnotation) {
|
||||
// The annotation might have had its type attributed (but not checked)
|
||||
// by attr.attribAnnotationTypes during MemberEnter, in which case we do not
|
||||
// need to do it again.
|
||||
Type at = (a.annotationType.type != null ? a.annotationType.type
|
||||
: attr.attribType(a.annotationType, env));
|
||||
a.type = chk.checkType(a.annotationType.pos(), at, expected);
|
||||
if (a.type.isErroneous()) {
|
||||
// Need to make sure nested (anno)trees does not have null as .type
|
||||
attr.postAttr(a);
|
||||
|
||||
if (typeAnnotation) {
|
||||
return new Attribute.TypeCompound(a.type, List.<Pair<MethodSymbol,Attribute>>nil(),
|
||||
new TypeAnnotationPosition());
|
||||
} else {
|
||||
return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil());
|
||||
}
|
||||
}
|
||||
if ((a.type.tsym.flags() & Flags.ANNOTATION) == 0) {
|
||||
log.error(a.annotationType.pos(),
|
||||
"not.annotation.type", a.type.toString());
|
||||
|
||||
// Need to make sure nested (anno)trees does not have null as .type
|
||||
attr.postAttr(a);
|
||||
|
||||
if (typeAnnotation) {
|
||||
return new Attribute.TypeCompound(a.type, List.<Pair<MethodSymbol,Attribute>>nil(), null);
|
||||
} else {
|
||||
return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil());
|
||||
}
|
||||
}
|
||||
List<JCExpression> args = a.args;
|
||||
if (args.length() == 1 && !args.head.hasTag(ASSIGN)) {
|
||||
// special case: elided "value=" assumed
|
||||
args.head = make.at(args.head.pos).
|
||||
Assign(make.Ident(names.value), args.head);
|
||||
}
|
||||
ListBuffer<Pair<MethodSymbol,Attribute>> buf =
|
||||
new ListBuffer<>();
|
||||
for (List<JCExpression> tl = args; tl.nonEmpty(); tl = tl.tail) {
|
||||
JCExpression t = tl.head;
|
||||
if (!t.hasTag(ASSIGN)) {
|
||||
log.error(t.pos(), "annotation.value.must.be.name.value");
|
||||
continue;
|
||||
}
|
||||
JCAssign assign = (JCAssign)t;
|
||||
if (!assign.lhs.hasTag(IDENT)) {
|
||||
log.error(t.pos(), "annotation.value.must.be.name.value");
|
||||
continue;
|
||||
}
|
||||
JCIdent left = (JCIdent)assign.lhs;
|
||||
Symbol method = rs.resolveQualifiedMethod(assign.rhs.pos(),
|
||||
env,
|
||||
a.type,
|
||||
left.name,
|
||||
List.<Type>nil(),
|
||||
null);
|
||||
left.sym = method;
|
||||
left.type = method.type;
|
||||
if (method.owner != a.type.tsym)
|
||||
log.error(left.pos(), "no.annotation.member", left.name, a.type);
|
||||
Type result = method.type.getReturnType();
|
||||
Attribute value = enterAttributeValue(result, assign.rhs, env);
|
||||
if (!method.type.isErroneous())
|
||||
buf.append(new Pair<>((MethodSymbol)method, value));
|
||||
t.type = result;
|
||||
}
|
||||
if (typeAnnotation) {
|
||||
if (a.attribute == null || !(a.attribute instanceof Attribute.TypeCompound)) {
|
||||
// Create a new TypeCompound
|
||||
Attribute.TypeCompound tc = new Attribute.TypeCompound(a.type, buf.toList(), new TypeAnnotationPosition());
|
||||
a.attribute = tc;
|
||||
return tc;
|
||||
} else {
|
||||
// Use an existing TypeCompound
|
||||
return a.attribute;
|
||||
}
|
||||
} else {
|
||||
Attribute.Compound ac = new Attribute.Compound(a.type, buf.toList());
|
||||
a.attribute = ac;
|
||||
return ac;
|
||||
}
|
||||
}
|
||||
|
||||
Attribute enterAttributeValue(Type expected,
|
||||
JCExpression tree,
|
||||
Env<AttrContext> env) {
|
||||
//first, try completing the attribution value sym - if a completion
|
||||
//error is thrown, we should recover gracefully, and display an
|
||||
//ordinary resolution diagnostic.
|
||||
try {
|
||||
expected.tsym.complete();
|
||||
} catch(CompletionFailure e) {
|
||||
log.error(tree.pos(), "cant.resolve", Kinds.kindName(e.sym), e.sym);
|
||||
expected = syms.errType;
|
||||
}
|
||||
if (expected.hasTag(ARRAY)) {
|
||||
if (!tree.hasTag(NEWARRAY)) {
|
||||
tree = make.at(tree.pos).
|
||||
NewArray(null, List.<JCExpression>nil(), List.of(tree));
|
||||
}
|
||||
JCNewArray na = (JCNewArray)tree;
|
||||
if (na.elemtype != null) {
|
||||
log.error(na.elemtype.pos(), "new.not.allowed.in.annotation");
|
||||
}
|
||||
ListBuffer<Attribute> buf = new ListBuffer<Attribute>();
|
||||
for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
|
||||
buf.append(enterAttributeValue(types.elemtype(expected),
|
||||
l.head,
|
||||
env));
|
||||
}
|
||||
na.type = expected;
|
||||
return new Attribute.
|
||||
Array(expected, buf.toArray(new Attribute[buf.length()]));
|
||||
}
|
||||
if (tree.hasTag(NEWARRAY)) { //error recovery
|
||||
if (!expected.isErroneous())
|
||||
log.error(tree.pos(), "annotation.value.not.allowable.type");
|
||||
JCNewArray na = (JCNewArray)tree;
|
||||
if (na.elemtype != null) {
|
||||
log.error(na.elemtype.pos(), "new.not.allowed.in.annotation");
|
||||
}
|
||||
for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
|
||||
enterAttributeValue(syms.errType,
|
||||
l.head,
|
||||
env);
|
||||
}
|
||||
return new Attribute.Error(syms.errType);
|
||||
}
|
||||
if ((expected.tsym.flags() & Flags.ANNOTATION) != 0) {
|
||||
if (tree.hasTag(ANNOTATION)) {
|
||||
return enterAnnotation((JCAnnotation)tree, expected, env);
|
||||
} else {
|
||||
log.error(tree.pos(), "annotation.value.must.be.annotation");
|
||||
expected = syms.errType;
|
||||
}
|
||||
}
|
||||
if (tree.hasTag(ANNOTATION)) { //error recovery
|
||||
if (!expected.isErroneous())
|
||||
log.error(tree.pos(), "annotation.not.valid.for.type", expected);
|
||||
enterAnnotation((JCAnnotation)tree, syms.errType, env);
|
||||
return new Attribute.Error(((JCAnnotation)tree).annotationType.type);
|
||||
}
|
||||
if (expected.isPrimitive() || types.isSameType(expected, syms.stringType)) {
|
||||
Type result = attr.attribExpr(tree, env, expected);
|
||||
if (result.isErroneous())
|
||||
return new Attribute.Error(result.getOriginalType());
|
||||
if (result.constValue() == null) {
|
||||
log.error(tree.pos(), "attribute.value.must.be.constant");
|
||||
return new Attribute.Error(expected);
|
||||
}
|
||||
result = cfolder.coerce(result, expected);
|
||||
return new Attribute.Constant(expected, result.constValue());
|
||||
}
|
||||
if (expected.tsym == syms.classType.tsym) {
|
||||
Type result = attr.attribExpr(tree, env, expected);
|
||||
if (result.isErroneous()) {
|
||||
// Does it look like an unresolved class literal?
|
||||
if (TreeInfo.name(tree) == names._class &&
|
||||
((JCFieldAccess) tree).selected.type.isErroneous()) {
|
||||
Name n = (((JCFieldAccess) tree).selected).type.tsym.flatName();
|
||||
return new Attribute.UnresolvedClass(expected,
|
||||
types.createErrorType(n,
|
||||
syms.unknownSymbol, syms.classType));
|
||||
} else {
|
||||
return new Attribute.Error(result.getOriginalType());
|
||||
}
|
||||
}
|
||||
|
||||
// Class literals look like field accesses of a field named class
|
||||
// at the tree level
|
||||
if (TreeInfo.name(tree) != names._class) {
|
||||
log.error(tree.pos(), "annotation.value.must.be.class.literal");
|
||||
return new Attribute.Error(syms.errType);
|
||||
}
|
||||
return new Attribute.Class(types,
|
||||
(((JCFieldAccess) tree).selected).type);
|
||||
}
|
||||
if (expected.hasTag(CLASS) &&
|
||||
(expected.tsym.flags() & Flags.ENUM) != 0) {
|
||||
Type result = attr.attribExpr(tree, env, expected);
|
||||
Symbol sym = TreeInfo.symbol(tree);
|
||||
if (sym == null ||
|
||||
TreeInfo.nonstaticSelect(tree) ||
|
||||
sym.kind != Kinds.VAR ||
|
||||
(sym.flags() & Flags.ENUM) == 0) {
|
||||
log.error(tree.pos(), "enum.annotation.must.be.enum.constant");
|
||||
return new Attribute.Error(result.getOriginalType());
|
||||
}
|
||||
VarSymbol enumerator = (VarSymbol) sym;
|
||||
return new Attribute.Enum(expected, enumerator);
|
||||
}
|
||||
//error recovery:
|
||||
if (!expected.isErroneous())
|
||||
log.error(tree.pos(), "annotation.value.not.allowable.type");
|
||||
return new Attribute.Error(attr.attribExpr(tree, env, expected));
|
||||
}
|
||||
|
||||
/* *********************************
|
||||
* Support for repeating annotations
|
||||
***********************************/
|
||||
|
||||
/* Process repeated annotations. This method returns the
|
||||
* synthesized container annotation or null IFF all repeating
|
||||
* annotation are invalid. This method reports errors/warnings.
|
||||
*/
|
||||
private <T extends Attribute.Compound> T processRepeatedAnnotations(List<T> annotations,
|
||||
AnnotateRepeatedContext<T> ctx,
|
||||
Symbol on) {
|
||||
T firstOccurrence = annotations.head;
|
||||
List<Attribute> repeated = List.nil();
|
||||
Type origAnnoType = null;
|
||||
Type arrayOfOrigAnnoType = null;
|
||||
Type targetContainerType = null;
|
||||
MethodSymbol containerValueSymbol = null;
|
||||
|
||||
Assert.check(!annotations.isEmpty() &&
|
||||
!annotations.tail.isEmpty()); // i.e. size() > 1
|
||||
|
||||
int count = 0;
|
||||
for (List<T> al = annotations;
|
||||
!al.isEmpty();
|
||||
al = al.tail)
|
||||
{
|
||||
count++;
|
||||
|
||||
// There must be more than a single anno in the annotation list
|
||||
Assert.check(count > 1 || !al.tail.isEmpty());
|
||||
|
||||
T currentAnno = al.head;
|
||||
|
||||
origAnnoType = currentAnno.type;
|
||||
if (arrayOfOrigAnnoType == null) {
|
||||
arrayOfOrigAnnoType = types.makeArrayType(origAnnoType);
|
||||
}
|
||||
|
||||
// Only report errors if this isn't the first occurrence I.E. count > 1
|
||||
boolean reportError = count > 1;
|
||||
Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno), reportError);
|
||||
if (currentContainerType == null) {
|
||||
continue;
|
||||
}
|
||||
// Assert that the target Container is == for all repeated
|
||||
// annos of the same annotation type, the types should
|
||||
// come from the same Symbol, i.e. be '=='
|
||||
Assert.check(targetContainerType == null || currentContainerType == targetContainerType);
|
||||
targetContainerType = currentContainerType;
|
||||
|
||||
containerValueSymbol = validateContainer(targetContainerType, origAnnoType, ctx.pos.get(currentAnno));
|
||||
|
||||
if (containerValueSymbol == null) { // Check of CA type failed
|
||||
// errors are already reported
|
||||
continue;
|
||||
}
|
||||
|
||||
repeated = repeated.prepend(currentAnno);
|
||||
}
|
||||
|
||||
if (!repeated.isEmpty()) {
|
||||
repeated = repeated.reverse();
|
||||
TreeMaker m = make.at(ctx.pos.get(firstOccurrence));
|
||||
Pair<MethodSymbol, Attribute> p =
|
||||
new Pair<MethodSymbol, Attribute>(containerValueSymbol,
|
||||
new Attribute.Array(arrayOfOrigAnnoType, repeated));
|
||||
if (ctx.isTypeCompound) {
|
||||
/* TODO: the following code would be cleaner:
|
||||
Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
|
||||
((Attribute.TypeCompound)annotations.head).position);
|
||||
JCTypeAnnotation annoTree = m.TypeAnnotation(at);
|
||||
at = enterTypeAnnotation(annoTree, targetContainerType, ctx.env);
|
||||
*/
|
||||
// However, we directly construct the TypeCompound to keep the
|
||||
// direct relation to the contained TypeCompounds.
|
||||
Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
|
||||
((Attribute.TypeCompound)annotations.head).position);
|
||||
|
||||
// TODO: annotation applicability checks from below?
|
||||
|
||||
at.setSynthesized(true);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
T x = (T) at;
|
||||
return x;
|
||||
} else {
|
||||
Attribute.Compound c = new Attribute.Compound(targetContainerType, List.of(p));
|
||||
JCAnnotation annoTree = m.Annotation(c);
|
||||
|
||||
if (!chk.annotationApplicable(annoTree, on))
|
||||
log.error(annoTree.pos(), "invalid.repeatable.annotation.incompatible.target", targetContainerType, origAnnoType);
|
||||
|
||||
if (!chk.validateAnnotationDeferErrors(annoTree))
|
||||
log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType);
|
||||
|
||||
c = enterAnnotation(annoTree, targetContainerType, ctx.env);
|
||||
c.setSynthesized(true);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
T x = (T) c;
|
||||
return x;
|
||||
}
|
||||
} else {
|
||||
return null; // errors should have been reported elsewhere
|
||||
}
|
||||
}
|
||||
|
||||
/** Fetches the actual Type that should be the containing annotation. */
|
||||
private Type getContainingType(Attribute.Compound currentAnno,
|
||||
DiagnosticPosition pos,
|
||||
boolean reportError)
|
||||
{
|
||||
Type origAnnoType = currentAnno.type;
|
||||
TypeSymbol origAnnoDecl = origAnnoType.tsym;
|
||||
|
||||
// Fetch the Repeatable annotation from the current
|
||||
// annotation's declaration, or null if it has none
|
||||
Attribute.Compound ca = origAnnoDecl.attribute(syms.repeatableType.tsym);
|
||||
if (ca == null) { // has no Repeatable annotation
|
||||
if (reportError)
|
||||
log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.repeatableType);
|
||||
return null;
|
||||
}
|
||||
|
||||
return filterSame(extractContainingType(ca, pos, origAnnoDecl),
|
||||
origAnnoType);
|
||||
}
|
||||
|
||||
// returns null if t is same as 's', returns 't' otherwise
|
||||
private Type filterSame(Type t, Type s) {
|
||||
if (t == null || s == null) {
|
||||
return t;
|
||||
}
|
||||
|
||||
return types.isSameType(t, s) ? null : t;
|
||||
}
|
||||
|
||||
/** Extract the actual Type to be used for a containing annotation. */
|
||||
private Type extractContainingType(Attribute.Compound ca,
|
||||
DiagnosticPosition pos,
|
||||
TypeSymbol annoDecl)
|
||||
{
|
||||
// The next three checks check that the Repeatable annotation
|
||||
// on the declaration of the annotation type that is repeating is
|
||||
// valid.
|
||||
|
||||
// Repeatable must have at least one element
|
||||
if (ca.values.isEmpty()) {
|
||||
log.error(pos, "invalid.repeatable.annotation", annoDecl);
|
||||
return null;
|
||||
}
|
||||
Pair<MethodSymbol,Attribute> p = ca.values.head;
|
||||
Name name = p.fst.name;
|
||||
if (name != names.value) { // should contain only one element, named "value"
|
||||
log.error(pos, "invalid.repeatable.annotation", annoDecl);
|
||||
return null;
|
||||
}
|
||||
if (!(p.snd instanceof Attribute.Class)) { // check that the value of "value" is an Attribute.Class
|
||||
log.error(pos, "invalid.repeatable.annotation", annoDecl);
|
||||
return null;
|
||||
}
|
||||
|
||||
return ((Attribute.Class)p.snd).getValue();
|
||||
}
|
||||
|
||||
/* Validate that the suggested targetContainerType Type is a valid
|
||||
* container type for repeated instances of originalAnnoType
|
||||
* annotations. Return null and report errors if this is not the
|
||||
* case, return the MethodSymbol of the value element in
|
||||
* targetContainerType if it is suitable (this is needed to
|
||||
* synthesize the container). */
|
||||
private MethodSymbol validateContainer(Type targetContainerType,
|
||||
Type originalAnnoType,
|
||||
DiagnosticPosition pos) {
|
||||
MethodSymbol containerValueSymbol = null;
|
||||
boolean fatalError = false;
|
||||
|
||||
// Validate that there is a (and only 1) value method
|
||||
Scope scope = targetContainerType.tsym.members();
|
||||
int nr_value_elems = 0;
|
||||
boolean error = false;
|
||||
for(Symbol elm : scope.getElementsByName(names.value)) {
|
||||
nr_value_elems++;
|
||||
|
||||
if (nr_value_elems == 1 &&
|
||||
elm.kind == Kinds.MTH) {
|
||||
containerValueSymbol = (MethodSymbol)elm;
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
log.error(pos,
|
||||
"invalid.repeatable.annotation.multiple.values",
|
||||
targetContainerType,
|
||||
nr_value_elems);
|
||||
return null;
|
||||
} else if (nr_value_elems == 0) {
|
||||
log.error(pos,
|
||||
"invalid.repeatable.annotation.no.value",
|
||||
targetContainerType);
|
||||
return null;
|
||||
}
|
||||
|
||||
// validate that the 'value' element is a method
|
||||
// probably "impossible" to fail this
|
||||
if (containerValueSymbol.kind != Kinds.MTH) {
|
||||
log.error(pos,
|
||||
"invalid.repeatable.annotation.invalid.value",
|
||||
targetContainerType);
|
||||
fatalError = true;
|
||||
}
|
||||
|
||||
// validate that the 'value' element has the correct return type
|
||||
// i.e. array of original anno
|
||||
Type valueRetType = containerValueSymbol.type.getReturnType();
|
||||
Type expectedType = types.makeArrayType(originalAnnoType);
|
||||
if (!(types.isArray(valueRetType) &&
|
||||
types.isSameType(expectedType, valueRetType))) {
|
||||
log.error(pos,
|
||||
"invalid.repeatable.annotation.value.return",
|
||||
targetContainerType,
|
||||
valueRetType,
|
||||
expectedType);
|
||||
fatalError = true;
|
||||
}
|
||||
if (error) {
|
||||
fatalError = true;
|
||||
}
|
||||
|
||||
// The conditions for a valid containing annotation are made
|
||||
// in Check.validateRepeatedAnnotaton();
|
||||
|
||||
return fatalError ? null : containerValueSymbol;
|
||||
}
|
||||
}
|
||||
4860
jdkSrc/jdk8/com/sun/tools/javac/comp/Attr.java
Normal file
4860
jdkSrc/jdk8/com/sun/tools/javac/comp/Attr.java
Normal file
File diff suppressed because it is too large
Load Diff
130
jdkSrc/jdk8/com/sun/tools/javac/comp/AttrContext.java
Normal file
130
jdkSrc/jdk8/com/sun/tools/javac/comp/AttrContext.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.comp;
|
||||
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.code.*;
|
||||
|
||||
/** Contains information specific to the attribute and enter
|
||||
* passes, to be used in place of the generic field in environments.
|
||||
*
|
||||
* <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 AttrContext {
|
||||
|
||||
/** The scope of local symbols.
|
||||
*/
|
||||
Scope scope = null;
|
||||
|
||||
/** The number of enclosing `static' modifiers.
|
||||
*/
|
||||
int staticLevel = 0;
|
||||
|
||||
/** Is this an environment for a this(...) or super(...) call?
|
||||
*/
|
||||
boolean isSelfCall = false;
|
||||
|
||||
/** Are we evaluating the selector of a `super' or type name?
|
||||
*/
|
||||
boolean selectSuper = false;
|
||||
|
||||
/** Is the current target of lambda expression or method reference serializable?
|
||||
*/
|
||||
boolean isSerializable = false;
|
||||
|
||||
/** Are arguments to current function applications boxed into an array for varargs?
|
||||
*/
|
||||
Resolve.MethodResolutionPhase pendingResolutionPhase = null;
|
||||
|
||||
/** A record of the lint/SuppressWarnings currently in effect
|
||||
*/
|
||||
Lint lint;
|
||||
|
||||
/** The variable whose initializer is being attributed
|
||||
* useful for detecting self-references in variable initializers
|
||||
*/
|
||||
Symbol enclVar = null;
|
||||
|
||||
/** ResultInfo to be used for attributing 'return' statement expressions
|
||||
* (set by Attr.visitMethod and Attr.visitLambda)
|
||||
*/
|
||||
Attr.ResultInfo returnResult = null;
|
||||
|
||||
/** Symbol corresponding to the site of a qualified default super call
|
||||
*/
|
||||
Type defaultSuperCallSite = null;
|
||||
|
||||
/** Tree that when non null, is to be preferentially used in diagnostics.
|
||||
* Usually Env<AttrContext>.tree is the tree to be referred to in messages,
|
||||
* but this may not be true during the window a method is looked up in enclosing
|
||||
* contexts (JDK-8145466)
|
||||
*/
|
||||
JCTree preferredTreeForDiagnostics;
|
||||
|
||||
/** Duplicate this context, replacing scope field and copying all others.
|
||||
*/
|
||||
AttrContext dup(Scope scope) {
|
||||
AttrContext info = new AttrContext();
|
||||
info.scope = scope;
|
||||
info.staticLevel = staticLevel;
|
||||
info.isSelfCall = isSelfCall;
|
||||
info.selectSuper = selectSuper;
|
||||
info.pendingResolutionPhase = pendingResolutionPhase;
|
||||
info.lint = lint;
|
||||
info.enclVar = enclVar;
|
||||
info.returnResult = returnResult;
|
||||
info.defaultSuperCallSite = defaultSuperCallSite;
|
||||
info.isSerializable = isSerializable;
|
||||
info.preferredTreeForDiagnostics = preferredTreeForDiagnostics;
|
||||
return info;
|
||||
}
|
||||
|
||||
/** Duplicate this context, copying all fields.
|
||||
*/
|
||||
AttrContext dup() {
|
||||
return dup(scope);
|
||||
}
|
||||
|
||||
public Iterable<Symbol> getLocalElements() {
|
||||
if (scope == null)
|
||||
return List.nil();
|
||||
return scope.getElements();
|
||||
}
|
||||
|
||||
boolean lastResolveVarargs() {
|
||||
return pendingResolutionPhase != null &&
|
||||
pendingResolutionPhase.isVarargsRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AttrContext[" + scope.toString() + "]";
|
||||
}
|
||||
}
|
||||
46
jdkSrc/jdk8/com/sun/tools/javac/comp/AttrContextEnv.java
Normal file
46
jdkSrc/jdk8/com/sun/tools/javac/comp/AttrContextEnv.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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.comp;
|
||||
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
|
||||
|
||||
/** {@code Env<A>} specialized as {@code Env<AttrContext>}
|
||||
*
|
||||
* <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 AttrContextEnv extends Env<AttrContext> {
|
||||
|
||||
/** Create an outermost environment for a given (toplevel)tree,
|
||||
* with a given info field.
|
||||
*/
|
||||
public AttrContextEnv(JCTree tree, AttrContext info) {
|
||||
super(tree, info);
|
||||
}
|
||||
}
|
||||
3541
jdkSrc/jdk8/com/sun/tools/javac/comp/Check.java
Normal file
3541
jdkSrc/jdk8/com/sun/tools/javac/comp/Check.java
Normal file
File diff suppressed because it is too large
Load Diff
92
jdkSrc/jdk8/com/sun/tools/javac/comp/CompileStates.java
Normal file
92
jdkSrc/jdk8/com/sun/tools/javac/comp/CompileStates.java
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. 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.comp;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.sun.tools.javac.util.Context;
|
||||
|
||||
/** Partial map to record which compiler phases have been executed
|
||||
* for each compilation unit. Used for ATTR and FLOW phases.
|
||||
*
|
||||
* <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 CompileStates extends HashMap<Env<AttrContext>, CompileStates.CompileState> {
|
||||
/** The context key for the compile states. */
|
||||
protected static final Context.Key<CompileStates> compileStatesKey =
|
||||
new Context.Key<CompileStates>();
|
||||
|
||||
/** Get the CompileStates instance for this context. */
|
||||
public static CompileStates instance(Context context) {
|
||||
CompileStates instance = context.get(compileStatesKey);
|
||||
if (instance == null) {
|
||||
instance = new CompileStates(context);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/** Ordered list of compiler phases for each compilation unit. */
|
||||
public enum CompileState {
|
||||
INIT(0),
|
||||
PARSE(1),
|
||||
ENTER(2),
|
||||
PROCESS(3),
|
||||
ATTR(4),
|
||||
FLOW(5),
|
||||
TRANSTYPES(6),
|
||||
UNLAMBDA(7),
|
||||
LOWER(8),
|
||||
GENERATE(9);
|
||||
|
||||
CompileState(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
public boolean isAfter(CompileState other) {
|
||||
return value > other.value;
|
||||
}
|
||||
public static CompileState max(CompileState a, CompileState b) {
|
||||
return a.value > b.value ? a : b;
|
||||
}
|
||||
private final int value;
|
||||
};
|
||||
|
||||
private static final long serialVersionUID = 1812267524140424433L;
|
||||
|
||||
protected Context context;
|
||||
|
||||
public CompileStates(Context context) {
|
||||
this.context = context;
|
||||
context.put(compileStatesKey, this);
|
||||
}
|
||||
|
||||
public boolean isDone(Env<AttrContext> env, CompileState cs) {
|
||||
CompileState ecs = get(env);
|
||||
return (ecs != null) && !cs.isAfter(ecs);
|
||||
}
|
||||
}
|
||||
357
jdkSrc/jdk8/com/sun/tools/javac/comp/ConstFold.java
Normal file
357
jdkSrc/jdk8/com/sun/tools/javac/comp/ConstFold.java
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* 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.comp;
|
||||
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.jvm.*;
|
||||
import com.sun.tools.javac.util.*;
|
||||
|
||||
import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
|
||||
|
||||
import static com.sun.tools.javac.jvm.ByteCodes.*;
|
||||
|
||||
/** Helper class for constant folding, used by the attribution phase.
|
||||
* This class is marked strictfp as mandated by JLS 15.4.
|
||||
*
|
||||
* <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>
|
||||
*/
|
||||
strictfp class ConstFold {
|
||||
protected static final Context.Key<ConstFold> constFoldKey =
|
||||
new Context.Key<ConstFold>();
|
||||
|
||||
private Symtab syms;
|
||||
|
||||
public static ConstFold instance(Context context) {
|
||||
ConstFold instance = context.get(constFoldKey);
|
||||
if (instance == null)
|
||||
instance = new ConstFold(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ConstFold(Context context) {
|
||||
context.put(constFoldKey, this);
|
||||
|
||||
syms = Symtab.instance(context);
|
||||
}
|
||||
|
||||
static final Integer minusOne = -1;
|
||||
static final Integer zero = 0;
|
||||
static final Integer one = 1;
|
||||
|
||||
/** Convert boolean to integer (true = 1, false = 0).
|
||||
*/
|
||||
private static Integer b2i(boolean b) {
|
||||
return b ? one : zero;
|
||||
}
|
||||
private static int intValue(Object x) { return ((Number)x).intValue(); }
|
||||
private static long longValue(Object x) { return ((Number)x).longValue(); }
|
||||
private static float floatValue(Object x) { return ((Number)x).floatValue(); }
|
||||
private static double doubleValue(Object x) { return ((Number)x).doubleValue(); }
|
||||
|
||||
/** Fold binary or unary operation, returning constant type reflecting the
|
||||
* operations result. Return null if fold failed due to an
|
||||
* arithmetic exception.
|
||||
* @param opcode The operation's opcode instruction (usually a byte code),
|
||||
* as entered by class Symtab.
|
||||
* @param argtypes The operation's argument types (a list of length 1 or 2).
|
||||
* Argument types are assumed to have non-null constValue's.
|
||||
*/
|
||||
Type fold(int opcode, List<Type> argtypes) {
|
||||
int argCount = argtypes.length();
|
||||
if (argCount == 1)
|
||||
return fold1(opcode, argtypes.head);
|
||||
else if (argCount == 2)
|
||||
return fold2(opcode, argtypes.head, argtypes.tail.head);
|
||||
else
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/** Fold unary operation.
|
||||
* @param opcode The operation's opcode instruction (usually a byte code),
|
||||
* as entered by class Symtab.
|
||||
* opcode's ifeq to ifge are for postprocessing
|
||||
* xcmp; ifxx pairs of instructions.
|
||||
* @param operand The operation's operand type.
|
||||
* Argument types are assumed to have non-null constValue's.
|
||||
*/
|
||||
Type fold1(int opcode, Type operand) {
|
||||
try {
|
||||
Object od = operand.constValue();
|
||||
switch (opcode) {
|
||||
case nop:
|
||||
return operand;
|
||||
case ineg: // unary -
|
||||
return syms.intType.constType(-intValue(od));
|
||||
case ixor: // ~
|
||||
return syms.intType.constType(~intValue(od));
|
||||
case bool_not: // !
|
||||
return syms.booleanType.constType(b2i(intValue(od) == 0));
|
||||
case ifeq:
|
||||
return syms.booleanType.constType(b2i(intValue(od) == 0));
|
||||
case ifne:
|
||||
return syms.booleanType.constType(b2i(intValue(od) != 0));
|
||||
case iflt:
|
||||
return syms.booleanType.constType(b2i(intValue(od) < 0));
|
||||
case ifgt:
|
||||
return syms.booleanType.constType(b2i(intValue(od) > 0));
|
||||
case ifle:
|
||||
return syms.booleanType.constType(b2i(intValue(od) <= 0));
|
||||
case ifge:
|
||||
return syms.booleanType.constType(b2i(intValue(od) >= 0));
|
||||
|
||||
case lneg: // unary -
|
||||
return syms.longType.constType(new Long(-longValue(od)));
|
||||
case lxor: // ~
|
||||
return syms.longType.constType(new Long(~longValue(od)));
|
||||
|
||||
case fneg: // unary -
|
||||
return syms.floatType.constType(new Float(-floatValue(od)));
|
||||
|
||||
case dneg: // ~
|
||||
return syms.doubleType.constType(new Double(-doubleValue(od)));
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} catch (ArithmeticException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Fold binary operation.
|
||||
* @param opcode The operation's opcode instruction (usually a byte code),
|
||||
* as entered by class Symtab.
|
||||
* opcode's ifeq to ifge are for postprocessing
|
||||
* xcmp; ifxx pairs of instructions.
|
||||
* @param left The type of the operation's left operand.
|
||||
* @param right The type of the operation's right operand.
|
||||
*/
|
||||
Type fold2(int opcode, Type left, Type right) {
|
||||
try {
|
||||
if (opcode > ByteCodes.preMask) {
|
||||
// we are seeing a composite instruction of the form xcmp; ifxx.
|
||||
// In this case fold both instructions separately.
|
||||
Type t1 = fold2(opcode >> ByteCodes.preShift, left, right);
|
||||
return (t1.constValue() == null) ? t1
|
||||
: fold1(opcode & ByteCodes.preMask, t1);
|
||||
} else {
|
||||
Object l = left.constValue();
|
||||
Object r = right.constValue();
|
||||
switch (opcode) {
|
||||
case iadd:
|
||||
return syms.intType.constType(intValue(l) + intValue(r));
|
||||
case isub:
|
||||
return syms.intType.constType(intValue(l) - intValue(r));
|
||||
case imul:
|
||||
return syms.intType.constType(intValue(l) * intValue(r));
|
||||
case idiv:
|
||||
return syms.intType.constType(intValue(l) / intValue(r));
|
||||
case imod:
|
||||
return syms.intType.constType(intValue(l) % intValue(r));
|
||||
case iand:
|
||||
return (left.hasTag(BOOLEAN)
|
||||
? syms.booleanType : syms.intType)
|
||||
.constType(intValue(l) & intValue(r));
|
||||
case bool_and:
|
||||
return syms.booleanType.constType(b2i((intValue(l) & intValue(r)) != 0));
|
||||
case ior:
|
||||
return (left.hasTag(BOOLEAN)
|
||||
? syms.booleanType : syms.intType)
|
||||
.constType(intValue(l) | intValue(r));
|
||||
case bool_or:
|
||||
return syms.booleanType.constType(b2i((intValue(l) | intValue(r)) != 0));
|
||||
case ixor:
|
||||
return (left.hasTag(BOOLEAN)
|
||||
? syms.booleanType : syms.intType)
|
||||
.constType(intValue(l) ^ intValue(r));
|
||||
case ishl: case ishll:
|
||||
return syms.intType.constType(intValue(l) << intValue(r));
|
||||
case ishr: case ishrl:
|
||||
return syms.intType.constType(intValue(l) >> intValue(r));
|
||||
case iushr: case iushrl:
|
||||
return syms.intType.constType(intValue(l) >>> intValue(r));
|
||||
case if_icmpeq:
|
||||
return syms.booleanType.constType(
|
||||
b2i(intValue(l) == intValue(r)));
|
||||
case if_icmpne:
|
||||
return syms.booleanType.constType(
|
||||
b2i(intValue(l) != intValue(r)));
|
||||
case if_icmplt:
|
||||
return syms.booleanType.constType(
|
||||
b2i(intValue(l) < intValue(r)));
|
||||
case if_icmpgt:
|
||||
return syms.booleanType.constType(
|
||||
b2i(intValue(l) > intValue(r)));
|
||||
case if_icmple:
|
||||
return syms.booleanType.constType(
|
||||
b2i(intValue(l) <= intValue(r)));
|
||||
case if_icmpge:
|
||||
return syms.booleanType.constType(
|
||||
b2i(intValue(l) >= intValue(r)));
|
||||
|
||||
case ladd:
|
||||
return syms.longType.constType(
|
||||
new Long(longValue(l) + longValue(r)));
|
||||
case lsub:
|
||||
return syms.longType.constType(
|
||||
new Long(longValue(l) - longValue(r)));
|
||||
case lmul:
|
||||
return syms.longType.constType(
|
||||
new Long(longValue(l) * longValue(r)));
|
||||
case ldiv:
|
||||
return syms.longType.constType(
|
||||
new Long(longValue(l) / longValue(r)));
|
||||
case lmod:
|
||||
return syms.longType.constType(
|
||||
new Long(longValue(l) % longValue(r)));
|
||||
case land:
|
||||
return syms.longType.constType(
|
||||
new Long(longValue(l) & longValue(r)));
|
||||
case lor:
|
||||
return syms.longType.constType(
|
||||
new Long(longValue(l) | longValue(r)));
|
||||
case lxor:
|
||||
return syms.longType.constType(
|
||||
new Long(longValue(l) ^ longValue(r)));
|
||||
case lshl: case lshll:
|
||||
return syms.longType.constType(
|
||||
new Long(longValue(l) << intValue(r)));
|
||||
case lshr: case lshrl:
|
||||
return syms.longType.constType(
|
||||
new Long(longValue(l) >> intValue(r)));
|
||||
case lushr:
|
||||
return syms.longType.constType(
|
||||
new Long(longValue(l) >>> intValue(r)));
|
||||
case lcmp:
|
||||
if (longValue(l) < longValue(r))
|
||||
return syms.intType.constType(minusOne);
|
||||
else if (longValue(l) > longValue(r))
|
||||
return syms.intType.constType(one);
|
||||
else
|
||||
return syms.intType.constType(zero);
|
||||
case fadd:
|
||||
return syms.floatType.constType(
|
||||
new Float(floatValue(l) + floatValue(r)));
|
||||
case fsub:
|
||||
return syms.floatType.constType(
|
||||
new Float(floatValue(l) - floatValue(r)));
|
||||
case fmul:
|
||||
return syms.floatType.constType(
|
||||
new Float(floatValue(l) * floatValue(r)));
|
||||
case fdiv:
|
||||
return syms.floatType.constType(
|
||||
new Float(floatValue(l) / floatValue(r)));
|
||||
case fmod:
|
||||
return syms.floatType.constType(
|
||||
new Float(floatValue(l) % floatValue(r)));
|
||||
case fcmpg: case fcmpl:
|
||||
if (floatValue(l) < floatValue(r))
|
||||
return syms.intType.constType(minusOne);
|
||||
else if (floatValue(l) > floatValue(r))
|
||||
return syms.intType.constType(one);
|
||||
else if (floatValue(l) == floatValue(r))
|
||||
return syms.intType.constType(zero);
|
||||
else if (opcode == fcmpg)
|
||||
return syms.intType.constType(one);
|
||||
else
|
||||
return syms.intType.constType(minusOne);
|
||||
case dadd:
|
||||
return syms.doubleType.constType(
|
||||
new Double(doubleValue(l) + doubleValue(r)));
|
||||
case dsub:
|
||||
return syms.doubleType.constType(
|
||||
new Double(doubleValue(l) - doubleValue(r)));
|
||||
case dmul:
|
||||
return syms.doubleType.constType(
|
||||
new Double(doubleValue(l) * doubleValue(r)));
|
||||
case ddiv:
|
||||
return syms.doubleType.constType(
|
||||
new Double(doubleValue(l) / doubleValue(r)));
|
||||
case dmod:
|
||||
return syms.doubleType.constType(
|
||||
new Double(doubleValue(l) % doubleValue(r)));
|
||||
case dcmpg: case dcmpl:
|
||||
if (doubleValue(l) < doubleValue(r))
|
||||
return syms.intType.constType(minusOne);
|
||||
else if (doubleValue(l) > doubleValue(r))
|
||||
return syms.intType.constType(one);
|
||||
else if (doubleValue(l) == doubleValue(r))
|
||||
return syms.intType.constType(zero);
|
||||
else if (opcode == dcmpg)
|
||||
return syms.intType.constType(one);
|
||||
else
|
||||
return syms.intType.constType(minusOne);
|
||||
case if_acmpeq:
|
||||
return syms.booleanType.constType(b2i(l.equals(r)));
|
||||
case if_acmpne:
|
||||
return syms.booleanType.constType(b2i(!l.equals(r)));
|
||||
case string_add:
|
||||
return syms.stringType.constType(
|
||||
left.stringValue() + right.stringValue());
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} catch (ArithmeticException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Coerce constant type to target type.
|
||||
* @param etype The source type of the coercion,
|
||||
* which is assumed to be a constant type compatible with
|
||||
* ttype.
|
||||
* @param ttype The target type of the coercion.
|
||||
*/
|
||||
Type coerce(Type etype, Type ttype) {
|
||||
// WAS if (etype.baseType() == ttype.baseType())
|
||||
if (etype.tsym.type == ttype.tsym.type)
|
||||
return etype;
|
||||
if (etype.isNumeric()) {
|
||||
Object n = etype.constValue();
|
||||
switch (ttype.getTag()) {
|
||||
case BYTE:
|
||||
return syms.byteType.constType(0 + (byte)intValue(n));
|
||||
case CHAR:
|
||||
return syms.charType.constType(0 + (char)intValue(n));
|
||||
case SHORT:
|
||||
return syms.shortType.constType(0 + (short)intValue(n));
|
||||
case INT:
|
||||
return syms.intType.constType(intValue(n));
|
||||
case LONG:
|
||||
return syms.longType.constType(longValue(n));
|
||||
case FLOAT:
|
||||
return syms.floatType.constType(floatValue(n));
|
||||
case DOUBLE:
|
||||
return syms.doubleType.constType(doubleValue(n));
|
||||
}
|
||||
}
|
||||
return ttype;
|
||||
}
|
||||
}
|
||||
1421
jdkSrc/jdk8/com/sun/tools/javac/comp/DeferredAttr.java
Normal file
1421
jdkSrc/jdk8/com/sun/tools/javac/comp/DeferredAttr.java
Normal file
File diff suppressed because it is too large
Load Diff
515
jdkSrc/jdk8/com/sun/tools/javac/comp/Enter.java
Normal file
515
jdkSrc/jdk8/com/sun/tools/javac/comp/Enter.java
Normal file
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* 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.comp;
|
||||
|
||||
import java.util.*;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.JavaFileManager;
|
||||
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.code.Scope.*;
|
||||
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.main.Option.PkgInfo;
|
||||
import com.sun.tools.javac.tree.*;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
import com.sun.tools.javac.util.List;
|
||||
|
||||
|
||||
import static com.sun.tools.javac.code.Flags.*;
|
||||
import static com.sun.tools.javac.code.Kinds.*;
|
||||
|
||||
/** This class enters symbols for all encountered definitions into
|
||||
* the symbol table. The pass consists of two phases, organized as
|
||||
* follows:
|
||||
*
|
||||
* <p>In the first phase, all class symbols are entered into their
|
||||
* enclosing scope, descending recursively down the tree for classes
|
||||
* which are members of other classes. The class symbols are given a
|
||||
* MemberEnter object as completer.
|
||||
*
|
||||
* <p>In the second phase classes are completed using
|
||||
* MemberEnter.complete(). Completion might occur on demand, but
|
||||
* any classes that are not completed that way will be eventually
|
||||
* completed by processing the `uncompleted' queue. Completion
|
||||
* entails (1) determination of a class's parameters, supertype and
|
||||
* interfaces, as well as (2) entering all symbols defined in the
|
||||
* class into its scope, with the exception of class symbols which
|
||||
* have been entered in phase 1. (2) depends on (1) having been
|
||||
* completed for a class and all its superclasses and enclosing
|
||||
* classes. That's why, after doing (1), we put classes in a
|
||||
* `halfcompleted' queue. Only when we have performed (1) for a class
|
||||
* and all it's superclasses and enclosing classes, we proceed to
|
||||
* (2).
|
||||
*
|
||||
* <p>Whereas the first phase is organized as a sweep through all
|
||||
* compiled syntax trees, the second phase is demand. Members of a
|
||||
* class are entered when the contents of a class are first
|
||||
* accessed. This is accomplished by installing completer objects in
|
||||
* class symbols for compiled classes which invoke the member-enter
|
||||
* phase for the corresponding class tree.
|
||||
*
|
||||
* <p>Classes migrate from one phase to the next via queues:
|
||||
*
|
||||
* <pre>{@literal
|
||||
* class enter -> (Enter.uncompleted) --> member enter (1)
|
||||
* -> (MemberEnter.halfcompleted) --> member enter (2)
|
||||
* -> (Todo) --> attribute
|
||||
* (only for toplevel classes)
|
||||
* }</pre>
|
||||
*
|
||||
* <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 Enter extends JCTree.Visitor {
|
||||
protected static final Context.Key<Enter> enterKey =
|
||||
new Context.Key<Enter>();
|
||||
|
||||
Log log;
|
||||
Symtab syms;
|
||||
Check chk;
|
||||
TreeMaker make;
|
||||
ClassReader reader;
|
||||
Annotate annotate;
|
||||
MemberEnter memberEnter;
|
||||
Types types;
|
||||
Lint lint;
|
||||
Names names;
|
||||
JavaFileManager fileManager;
|
||||
PkgInfo pkginfoOpt;
|
||||
TypeEnvs typeEnvs;
|
||||
|
||||
private final Todo todo;
|
||||
|
||||
public static Enter instance(Context context) {
|
||||
Enter instance = context.get(enterKey);
|
||||
if (instance == null)
|
||||
instance = new Enter(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
protected Enter(Context context) {
|
||||
context.put(enterKey, this);
|
||||
|
||||
log = Log.instance(context);
|
||||
reader = ClassReader.instance(context);
|
||||
make = TreeMaker.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
chk = Check.instance(context);
|
||||
memberEnter = MemberEnter.instance(context);
|
||||
types = Types.instance(context);
|
||||
annotate = Annotate.instance(context);
|
||||
lint = Lint.instance(context);
|
||||
names = Names.instance(context);
|
||||
|
||||
predefClassDef = make.ClassDef(
|
||||
make.Modifiers(PUBLIC),
|
||||
syms.predefClass.name,
|
||||
List.<JCTypeParameter>nil(),
|
||||
null,
|
||||
List.<JCExpression>nil(),
|
||||
List.<JCTree>nil());
|
||||
predefClassDef.sym = syms.predefClass;
|
||||
todo = Todo.instance(context);
|
||||
fileManager = context.get(JavaFileManager.class);
|
||||
|
||||
Options options = Options.instance(context);
|
||||
pkginfoOpt = PkgInfo.get(options);
|
||||
typeEnvs = TypeEnvs.instance(context);
|
||||
}
|
||||
|
||||
/** Accessor for typeEnvs
|
||||
*/
|
||||
public Env<AttrContext> getEnv(TypeSymbol sym) {
|
||||
return typeEnvs.get(sym);
|
||||
}
|
||||
|
||||
public Env<AttrContext> getClassEnv(TypeSymbol sym) {
|
||||
Env<AttrContext> localEnv = getEnv(sym);
|
||||
Env<AttrContext> lintEnv = localEnv;
|
||||
while (lintEnv.info.lint == null)
|
||||
lintEnv = lintEnv.next;
|
||||
localEnv.info.lint = lintEnv.info.lint.augment(sym);
|
||||
return localEnv;
|
||||
}
|
||||
|
||||
/** The queue of all classes that might still need to be completed;
|
||||
* saved and initialized by main().
|
||||
*/
|
||||
ListBuffer<ClassSymbol> uncompleted;
|
||||
|
||||
/** A dummy class to serve as enclClass for toplevel environments.
|
||||
*/
|
||||
private JCClassDecl predefClassDef;
|
||||
|
||||
/* ************************************************************************
|
||||
* environment construction
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
/** Create a fresh environment for class bodies.
|
||||
* This will create a fresh scope for local symbols of a class, referred
|
||||
* to by the environments info.scope field.
|
||||
* This scope will contain
|
||||
* - symbols for this and super
|
||||
* - symbols for any type parameters
|
||||
* In addition, it serves as an anchor for scopes of methods and initializers
|
||||
* which are nested in this scope via Scope.dup().
|
||||
* This scope should not be confused with the members scope of a class.
|
||||
*
|
||||
* @param tree The class definition.
|
||||
* @param env The environment current outside of the class definition.
|
||||
*/
|
||||
public Env<AttrContext> classEnv(JCClassDecl tree, Env<AttrContext> env) {
|
||||
Env<AttrContext> localEnv =
|
||||
env.dup(tree, env.info.dup(new Scope(tree.sym)));
|
||||
localEnv.enclClass = tree;
|
||||
localEnv.outer = env;
|
||||
localEnv.info.isSelfCall = false;
|
||||
localEnv.info.lint = null; // leave this to be filled in by Attr,
|
||||
// when annotations have been processed
|
||||
return localEnv;
|
||||
}
|
||||
|
||||
/** Create a fresh environment for toplevels.
|
||||
* @param tree The toplevel tree.
|
||||
*/
|
||||
Env<AttrContext> topLevelEnv(JCCompilationUnit tree) {
|
||||
Env<AttrContext> localEnv = new Env<AttrContext>(tree, new AttrContext());
|
||||
localEnv.toplevel = tree;
|
||||
localEnv.enclClass = predefClassDef;
|
||||
tree.namedImportScope = new ImportScope(tree.packge);
|
||||
tree.starImportScope = new StarImportScope(tree.packge);
|
||||
localEnv.info.scope = tree.namedImportScope;
|
||||
localEnv.info.lint = lint;
|
||||
return localEnv;
|
||||
}
|
||||
|
||||
public Env<AttrContext> getTopLevelEnv(JCCompilationUnit tree) {
|
||||
Env<AttrContext> localEnv = new Env<AttrContext>(tree, new AttrContext());
|
||||
localEnv.toplevel = tree;
|
||||
localEnv.enclClass = predefClassDef;
|
||||
localEnv.info.scope = tree.namedImportScope;
|
||||
localEnv.info.lint = lint;
|
||||
return localEnv;
|
||||
}
|
||||
|
||||
/** The scope in which a member definition in environment env is to be entered
|
||||
* This is usually the environment's scope, except for class environments,
|
||||
* where the local scope is for type variables, and the this and super symbol
|
||||
* only, and members go into the class member scope.
|
||||
*/
|
||||
Scope enterScope(Env<AttrContext> env) {
|
||||
return (env.tree.hasTag(JCTree.Tag.CLASSDEF))
|
||||
? ((JCClassDecl) env.tree).sym.members_field
|
||||
: env.info.scope;
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
* Visitor methods for phase 1: class enter
|
||||
*************************************************************************/
|
||||
|
||||
/** Visitor argument: the current environment.
|
||||
*/
|
||||
protected Env<AttrContext> env;
|
||||
|
||||
/** Visitor result: the computed type.
|
||||
*/
|
||||
Type result;
|
||||
|
||||
/** Visitor method: enter all classes in given tree, catching any
|
||||
* completion failure exceptions. Return the tree's type.
|
||||
*
|
||||
* @param tree The tree to be visited.
|
||||
* @param env The environment visitor argument.
|
||||
*/
|
||||
Type classEnter(JCTree tree, Env<AttrContext> env) {
|
||||
Env<AttrContext> prevEnv = this.env;
|
||||
try {
|
||||
this.env = env;
|
||||
tree.accept(this);
|
||||
return result;
|
||||
} catch (CompletionFailure ex) {
|
||||
return chk.completionError(tree.pos(), ex);
|
||||
} finally {
|
||||
this.env = prevEnv;
|
||||
}
|
||||
}
|
||||
|
||||
/** Visitor method: enter classes of a list of trees, returning a list of types.
|
||||
*/
|
||||
<T extends JCTree> List<Type> classEnter(List<T> trees, Env<AttrContext> env) {
|
||||
ListBuffer<Type> ts = new ListBuffer<Type>();
|
||||
for (List<T> l = trees; l.nonEmpty(); l = l.tail) {
|
||||
Type t = classEnter(l.head, env);
|
||||
if (t != null)
|
||||
ts.append(t);
|
||||
}
|
||||
return ts.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTopLevel(JCCompilationUnit tree) {
|
||||
JavaFileObject prev = log.useSource(tree.sourcefile);
|
||||
boolean addEnv = false;
|
||||
boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info",
|
||||
JavaFileObject.Kind.SOURCE);
|
||||
if (tree.pid != null) {
|
||||
tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid));
|
||||
if (tree.packageAnnotations.nonEmpty()
|
||||
|| pkginfoOpt == PkgInfo.ALWAYS
|
||||
|| tree.docComments != null) {
|
||||
if (isPkgInfo) {
|
||||
addEnv = true;
|
||||
} else if (tree.packageAnnotations.nonEmpty()){
|
||||
log.error(tree.packageAnnotations.head.pos(),
|
||||
"pkg.annotations.sb.in.package-info.java");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tree.packge = syms.unnamedPackage;
|
||||
}
|
||||
tree.packge.complete(); // Find all classes in package.
|
||||
Env<AttrContext> topEnv = topLevelEnv(tree);
|
||||
|
||||
// Save environment of package-info.java file.
|
||||
if (isPkgInfo) {
|
||||
Env<AttrContext> env0 = typeEnvs.get(tree.packge);
|
||||
if (env0 == null) {
|
||||
typeEnvs.put(tree.packge, topEnv);
|
||||
} else {
|
||||
JCCompilationUnit tree0 = env0.toplevel;
|
||||
if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
|
||||
log.warning(tree.pid != null ? tree.pid.pos()
|
||||
: null,
|
||||
"pkg-info.already.seen",
|
||||
tree.packge);
|
||||
if (addEnv || (tree0.packageAnnotations.isEmpty() &&
|
||||
tree.docComments != null &&
|
||||
tree.docComments.hasComment(tree))) {
|
||||
typeEnvs.put(tree.packge, topEnv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner)
|
||||
q.flags_field |= EXISTS;
|
||||
|
||||
Name name = names.package_info;
|
||||
ClassSymbol c = reader.enterClass(name, tree.packge);
|
||||
c.flatname = names.fromString(tree.packge + "." + name);
|
||||
c.sourcefile = tree.sourcefile;
|
||||
c.completer = null;
|
||||
c.members_field = new Scope(c);
|
||||
tree.packge.package_info = c;
|
||||
}
|
||||
classEnter(tree.defs, topEnv);
|
||||
if (addEnv) {
|
||||
todo.append(topEnv);
|
||||
}
|
||||
log.useSource(prev);
|
||||
result = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassDef(JCClassDecl tree) {
|
||||
Symbol owner = env.info.scope.owner;
|
||||
Scope enclScope = enterScope(env);
|
||||
ClassSymbol c;
|
||||
if (owner.kind == PCK) {
|
||||
// We are seeing a toplevel class.
|
||||
PackageSymbol packge = (PackageSymbol)owner;
|
||||
for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner)
|
||||
q.flags_field |= EXISTS;
|
||||
c = reader.enterClass(tree.name, packge);
|
||||
packge.members().enterIfAbsent(c);
|
||||
if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) {
|
||||
log.error(tree.pos(),
|
||||
"class.public.should.be.in.file", tree.name);
|
||||
}
|
||||
} else {
|
||||
if (!tree.name.isEmpty() &&
|
||||
!chk.checkUniqueClassName(tree.pos(), tree.name, enclScope)) {
|
||||
result = null;
|
||||
return;
|
||||
}
|
||||
if (owner.kind == TYP) {
|
||||
// We are seeing a member class.
|
||||
c = reader.enterClass(tree.name, (TypeSymbol)owner);
|
||||
if ((owner.flags_field & INTERFACE) != 0) {
|
||||
tree.mods.flags |= PUBLIC | STATIC;
|
||||
}
|
||||
} else {
|
||||
// We are seeing a local class.
|
||||
c = reader.defineClass(tree.name, owner);
|
||||
c.flatname = chk.localClassName(c);
|
||||
if (!c.name.isEmpty())
|
||||
chk.checkTransparentClass(tree.pos(), c, env.info.scope);
|
||||
}
|
||||
}
|
||||
tree.sym = c;
|
||||
|
||||
// Enter class into `compiled' table and enclosing scope.
|
||||
if (chk.compiled.get(c.flatname) != null) {
|
||||
duplicateClass(tree.pos(), c);
|
||||
result = types.createErrorType(tree.name, (TypeSymbol)owner, Type.noType);
|
||||
tree.sym = (ClassSymbol)result.tsym;
|
||||
return;
|
||||
}
|
||||
chk.compiled.put(c.flatname, c);
|
||||
enclScope.enter(c);
|
||||
|
||||
// Set up an environment for class block and store in `typeEnvs'
|
||||
// table, to be retrieved later in memberEnter and attribution.
|
||||
Env<AttrContext> localEnv = classEnv(tree, env);
|
||||
typeEnvs.put(c, localEnv);
|
||||
|
||||
// Fill out class fields.
|
||||
c.completer = memberEnter;
|
||||
c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
|
||||
c.sourcefile = env.toplevel.sourcefile;
|
||||
c.members_field = new Scope(c);
|
||||
|
||||
ClassType ct = (ClassType)c.type;
|
||||
if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
|
||||
// We are seeing a local or inner class.
|
||||
// Set outer_field of this class to closest enclosing class
|
||||
// which contains this class in a non-static context
|
||||
// (its "enclosing instance class"), provided such a class exists.
|
||||
Symbol owner1 = owner;
|
||||
while ((owner1.kind & (VAR | MTH)) != 0 &&
|
||||
(owner1.flags_field & STATIC) == 0) {
|
||||
owner1 = owner1.owner;
|
||||
}
|
||||
if (owner1.kind == TYP) {
|
||||
ct.setEnclosingType(owner1.type);
|
||||
}
|
||||
}
|
||||
|
||||
// Enter type parameters.
|
||||
ct.typarams_field = classEnter(tree.typarams, localEnv);
|
||||
|
||||
// Add non-local class to uncompleted, to make sure it will be
|
||||
// completed later.
|
||||
if (!c.isLocal() && uncompleted != null) uncompleted.append(c);
|
||||
// System.err.println("entering " + c.fullname + " in " + c.owner);//DEBUG
|
||||
|
||||
// Recursively enter all member classes.
|
||||
classEnter(tree.defs, localEnv);
|
||||
|
||||
result = c.type;
|
||||
}
|
||||
//where
|
||||
/** Does class have the same name as the file it appears in?
|
||||
*/
|
||||
private static boolean classNameMatchesFileName(ClassSymbol c,
|
||||
Env<AttrContext> env) {
|
||||
return env.toplevel.sourcefile.isNameCompatible(c.name.toString(),
|
||||
JavaFileObject.Kind.SOURCE);
|
||||
}
|
||||
|
||||
/** Complain about a duplicate class. */
|
||||
protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) {
|
||||
log.error(pos, "duplicate.class", c.fullname);
|
||||
}
|
||||
|
||||
/** Class enter visitor method for type parameters.
|
||||
* Enter a symbol for type parameter in local scope, after checking that it
|
||||
* is unique.
|
||||
*/
|
||||
@Override
|
||||
public void visitTypeParameter(JCTypeParameter tree) {
|
||||
TypeVar a = (tree.type != null)
|
||||
? (TypeVar)tree.type
|
||||
: new TypeVar(tree.name, env.info.scope.owner, syms.botType);
|
||||
tree.type = a;
|
||||
if (chk.checkUnique(tree.pos(), a.tsym, env.info.scope)) {
|
||||
env.info.scope.enter(a.tsym);
|
||||
}
|
||||
result = a;
|
||||
}
|
||||
|
||||
/** Default class enter visitor method: do nothing.
|
||||
*/
|
||||
@Override
|
||||
public void visitTree(JCTree tree) {
|
||||
result = null;
|
||||
}
|
||||
|
||||
/** Main method: enter all classes in a list of toplevel trees.
|
||||
* @param trees The list of trees to be processed.
|
||||
*/
|
||||
public void main(List<JCCompilationUnit> trees) {
|
||||
complete(trees, null);
|
||||
}
|
||||
|
||||
/** Main method: enter one class from a list of toplevel trees and
|
||||
* place the rest on uncompleted for later processing.
|
||||
* @param trees The list of trees to be processed.
|
||||
* @param c The class symbol to be processed.
|
||||
*/
|
||||
public void complete(List<JCCompilationUnit> trees, ClassSymbol c) {
|
||||
annotate.enterStart();
|
||||
ListBuffer<ClassSymbol> prevUncompleted = uncompleted;
|
||||
if (memberEnter.completionEnabled) uncompleted = new ListBuffer<ClassSymbol>();
|
||||
|
||||
try {
|
||||
// enter all classes, and construct uncompleted list
|
||||
classEnter(trees, null);
|
||||
|
||||
// complete all uncompleted classes in memberEnter
|
||||
if (memberEnter.completionEnabled) {
|
||||
while (uncompleted.nonEmpty()) {
|
||||
ClassSymbol clazz = uncompleted.next();
|
||||
if (c == null || c == clazz || prevUncompleted == null)
|
||||
clazz.complete();
|
||||
else
|
||||
// defer
|
||||
prevUncompleted.append(clazz);
|
||||
}
|
||||
|
||||
// if there remain any unimported toplevels (these must have
|
||||
// no classes at all), process their import statements as well.
|
||||
for (JCCompilationUnit tree : trees) {
|
||||
if (tree.starImportScope.elems == null) {
|
||||
JavaFileObject prev = log.useSource(tree.sourcefile);
|
||||
Env<AttrContext> topEnv = topLevelEnv(tree);
|
||||
memberEnter.memberEnter(tree, topEnv);
|
||||
log.useSource(prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
uncompleted = prevUncompleted;
|
||||
annotate.enterDone();
|
||||
}
|
||||
}
|
||||
}
|
||||
159
jdkSrc/jdk8/com/sun/tools/javac/comp/Env.java
Normal file
159
jdkSrc/jdk8/com/sun/tools/javac/comp/Env.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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.comp;
|
||||
|
||||
import com.sun.tools.javac.tree.*;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/** A class for environments, instances of which are passed as
|
||||
* arguments to tree visitors. Environments refer to important ancestors
|
||||
* of the subtree that's currently visited, such as the enclosing method,
|
||||
* the enclosing class, or the enclosing toplevel node. They also contain
|
||||
* a generic component, represented as a type parameter, to carry further
|
||||
* information specific to individual passes.
|
||||
*
|
||||
* <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 Env<A> implements Iterable<Env<A>> {
|
||||
|
||||
/** The next enclosing environment.
|
||||
*/
|
||||
public Env<A> next;
|
||||
|
||||
/** The environment enclosing the current class.
|
||||
*/
|
||||
public Env<A> outer;
|
||||
|
||||
/** The tree with which this environment is associated.
|
||||
*/
|
||||
public JCTree tree;
|
||||
|
||||
/** The enclosing toplevel tree.
|
||||
*/
|
||||
public JCTree.JCCompilationUnit toplevel;
|
||||
|
||||
/** The next enclosing class definition.
|
||||
*/
|
||||
public JCTree.JCClassDecl enclClass;
|
||||
|
||||
/** The next enclosing method definition.
|
||||
*/
|
||||
public JCTree.JCMethodDecl enclMethod;
|
||||
|
||||
/** A generic field for further information.
|
||||
*/
|
||||
public A info;
|
||||
|
||||
/** Is this an environment for evaluating a base clause?
|
||||
*/
|
||||
public boolean baseClause = false;
|
||||
|
||||
/** Create an outermost environment for a given (toplevel)tree,
|
||||
* with a given info field.
|
||||
*/
|
||||
public Env(JCTree tree, A info) {
|
||||
this.next = null;
|
||||
this.outer = null;
|
||||
this.tree = tree;
|
||||
this.toplevel = null;
|
||||
this.enclClass = null;
|
||||
this.enclMethod = null;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
/** Duplicate this environment, updating with given tree and info,
|
||||
* and copying all other fields.
|
||||
*/
|
||||
public Env<A> dup(JCTree tree, A info) {
|
||||
return dupto(new Env<A>(tree, info));
|
||||
}
|
||||
|
||||
/** Duplicate this environment into a given Environment,
|
||||
* using its tree and info, and copying all other fields.
|
||||
*/
|
||||
public Env<A> dupto(Env<A> that) {
|
||||
that.next = this;
|
||||
that.outer = this.outer;
|
||||
that.toplevel = this.toplevel;
|
||||
that.enclClass = this.enclClass;
|
||||
that.enclMethod = this.enclMethod;
|
||||
return that;
|
||||
}
|
||||
|
||||
/** Duplicate this environment, updating with given tree,
|
||||
* and copying all other fields.
|
||||
*/
|
||||
public Env<A> dup(JCTree tree) {
|
||||
return dup(tree, this.info);
|
||||
}
|
||||
|
||||
/** Return closest enclosing environment which points to a tree with given tag.
|
||||
*/
|
||||
public Env<A> enclosing(JCTree.Tag tag) {
|
||||
Env<A> env1 = this;
|
||||
while (env1 != null && !env1.tree.hasTag(tag)) env1 = env1.next;
|
||||
return env1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Env[").append(info);
|
||||
// if (enclMethod != null)
|
||||
// sb.append(",enclMethod=").append(Pretty.toSimpleString(enclMethod));
|
||||
// if (enclClass != null)
|
||||
// sb.append(",enclClass=").append(Pretty.toSimpleString(enclClass));
|
||||
if (outer != null)
|
||||
sb.append(",outer=").append(outer);
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Iterator<Env<A>> iterator() {
|
||||
return new Iterator<Env<A>>() {
|
||||
Env<A> next = Env.this;
|
||||
public boolean hasNext() {
|
||||
return next.outer != null;
|
||||
}
|
||||
public Env<A> next() {
|
||||
if (hasNext()) {
|
||||
Env<A> current = next;
|
||||
next = current.outer;
|
||||
return current;
|
||||
}
|
||||
throw new NoSuchElementException();
|
||||
|
||||
}
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
2622
jdkSrc/jdk8/com/sun/tools/javac/comp/Flow.java
Normal file
2622
jdkSrc/jdk8/com/sun/tools/javac/comp/Flow.java
Normal file
File diff suppressed because it is too large
Load Diff
2376
jdkSrc/jdk8/com/sun/tools/javac/comp/Infer.java
Normal file
2376
jdkSrc/jdk8/com/sun/tools/javac/comp/Infer.java
Normal file
File diff suppressed because it is too large
Load Diff
2337
jdkSrc/jdk8/com/sun/tools/javac/comp/LambdaToMethod.java
Normal file
2337
jdkSrc/jdk8/com/sun/tools/javac/comp/LambdaToMethod.java
Normal file
File diff suppressed because it is too large
Load Diff
3965
jdkSrc/jdk8/com/sun/tools/javac/comp/Lower.java
Normal file
3965
jdkSrc/jdk8/com/sun/tools/javac/comp/Lower.java
Normal file
File diff suppressed because it is too large
Load Diff
1678
jdkSrc/jdk8/com/sun/tools/javac/comp/MemberEnter.java
Normal file
1678
jdkSrc/jdk8/com/sun/tools/javac/comp/MemberEnter.java
Normal file
File diff suppressed because it is too large
Load Diff
4400
jdkSrc/jdk8/com/sun/tools/javac/comp/Resolve.java
Normal file
4400
jdkSrc/jdk8/com/sun/tools/javac/comp/Resolve.java
Normal file
File diff suppressed because it is too large
Load Diff
172
jdkSrc/jdk8/com/sun/tools/javac/comp/Todo.java
Normal file
172
jdkSrc/jdk8/com/sun/tools/javac/comp/Todo.java
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, 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.comp;
|
||||
|
||||
import java.util.AbstractQueue;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
/** A queue of all as yet unattributed 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 Todo extends AbstractQueue<Env<AttrContext>> {
|
||||
/** The context key for the todo list. */
|
||||
protected static final Context.Key<Todo> todoKey =
|
||||
new Context.Key<Todo>();
|
||||
|
||||
/** Get the Todo instance for this context. */
|
||||
public static Todo instance(Context context) {
|
||||
Todo instance = context.get(todoKey);
|
||||
if (instance == null)
|
||||
instance = new Todo(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
/** Create a new todo list. */
|
||||
protected Todo(Context context) {
|
||||
context.put(todoKey, this);
|
||||
}
|
||||
|
||||
public void append(Env<AttrContext> env) {
|
||||
add(env);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Env<AttrContext>> iterator() {
|
||||
return contents.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return contents.size();
|
||||
}
|
||||
|
||||
public boolean offer(Env<AttrContext> e) {
|
||||
if (contents.add(e)) {
|
||||
if (contentsByFile != null)
|
||||
addByFile(e);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Env<AttrContext> poll() {
|
||||
if (size() == 0)
|
||||
return null;
|
||||
Env<AttrContext> env = contents.remove(0);
|
||||
if (contentsByFile != null)
|
||||
removeByFile(env);
|
||||
return env;
|
||||
}
|
||||
|
||||
public Env<AttrContext> peek() {
|
||||
return (size() == 0 ? null : contents.get(0));
|
||||
}
|
||||
|
||||
public Queue<Queue<Env<AttrContext>>> groupByFile() {
|
||||
if (contentsByFile == null) {
|
||||
contentsByFile = new LinkedList<Queue<Env<AttrContext>>>();
|
||||
for (Env<AttrContext> env: contents) {
|
||||
addByFile(env);
|
||||
}
|
||||
}
|
||||
return contentsByFile;
|
||||
}
|
||||
|
||||
private void addByFile(Env<AttrContext> env) {
|
||||
JavaFileObject file = env.toplevel.sourcefile;
|
||||
if (fileMap == null)
|
||||
fileMap = new HashMap<JavaFileObject, FileQueue>();
|
||||
FileQueue fq = fileMap.get(file);
|
||||
if (fq == null) {
|
||||
fq = new FileQueue();
|
||||
fileMap.put(file, fq);
|
||||
contentsByFile.add(fq);
|
||||
}
|
||||
fq.fileContents.add(env);
|
||||
}
|
||||
|
||||
private void removeByFile(Env<AttrContext> env) {
|
||||
JavaFileObject file = env.toplevel.sourcefile;
|
||||
FileQueue fq = fileMap.get(file);
|
||||
if (fq == null)
|
||||
return;
|
||||
if (fq.fileContents.remove(env)) {
|
||||
if (fq.isEmpty()) {
|
||||
fileMap.remove(file);
|
||||
contentsByFile.remove(fq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LinkedList<Env<AttrContext>> contents = new LinkedList<Env<AttrContext>>();
|
||||
LinkedList<Queue<Env<AttrContext>>> contentsByFile;
|
||||
Map<JavaFileObject, FileQueue> fileMap;
|
||||
|
||||
class FileQueue extends AbstractQueue<Env<AttrContext>> {
|
||||
@Override
|
||||
public Iterator<Env<AttrContext>> iterator() {
|
||||
return fileContents.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return fileContents.size();
|
||||
}
|
||||
|
||||
public boolean offer(Env<AttrContext> e) {
|
||||
if (fileContents.offer(e)) {
|
||||
contents.add(e);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Env<AttrContext> poll() {
|
||||
if (fileContents.size() == 0)
|
||||
return null;
|
||||
Env<AttrContext> env = fileContents.remove(0);
|
||||
contents.remove(env);
|
||||
return env;
|
||||
}
|
||||
|
||||
public Env<AttrContext> peek() {
|
||||
return (fileContents.size() == 0 ? null : fileContents.get(0));
|
||||
}
|
||||
|
||||
LinkedList<Env<AttrContext>> fileContents = new LinkedList<Env<AttrContext>>();
|
||||
}
|
||||
}
|
||||
1037
jdkSrc/jdk8/com/sun/tools/javac/comp/TransTypes.java
Normal file
1037
jdkSrc/jdk8/com/sun/tools/javac/comp/TransTypes.java
Normal file
File diff suppressed because it is too large
Load Diff
63
jdkSrc/jdk8/com/sun/tools/javac/comp/TypeEnvs.java
Normal file
63
jdkSrc/jdk8/com/sun/tools/javac/comp/TypeEnvs.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 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.comp;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import com.sun.tools.javac.code.Symbol.TypeSymbol;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
|
||||
/** This class contains the type environments used by Enter, MemberEnter,
|
||||
* Attr, DeferredAttr, and Lower.
|
||||
*
|
||||
* <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>
|
||||
*/
|
||||
class TypeEnvs {
|
||||
private static final long serialVersionUID = 571524752489954631L;
|
||||
|
||||
protected static final Context.Key<TypeEnvs> typeEnvsKey = new Context.Key<>();
|
||||
public static TypeEnvs instance(Context context) {
|
||||
TypeEnvs instance = context.get(typeEnvsKey);
|
||||
if (instance == null)
|
||||
instance = new TypeEnvs(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
private HashMap<TypeSymbol,Env<AttrContext>> map;
|
||||
protected TypeEnvs(Context context) {
|
||||
map = new HashMap<>();
|
||||
context.put(typeEnvsKey, this);
|
||||
}
|
||||
|
||||
Env<AttrContext> get(TypeSymbol sym) { return map.get(sym); }
|
||||
Env<AttrContext> put(TypeSymbol sym, Env<AttrContext> env) { return map.put(sym, env); }
|
||||
Env<AttrContext> remove(TypeSymbol sym) { return map.remove(sym); }
|
||||
Collection<Env<AttrContext>> values() { return map.values(); }
|
||||
void clear() { map.clear(); }
|
||||
}
|
||||
Reference in New Issue
Block a user