📄 type.java
字号:
static Type makeCompoundType(List bounds, TypeSymbol tsym) {
Type supertype = (((Type) bounds.head).tsym.flags() & INTERFACE) != 0 ?
((Type) bounds.head).supertype() : null;
return makeCompoundType(bounds, tsym, supertype);
}
public Type constType(Object constValue) {
Type t = new ClassType(outer_field, typarams_field, tsym);
t.constValue = constValue;
return t;
}
public String toString() {
StringBuffer buf = new StringBuffer();
if (outer().tag == CLASS && tsym.owner.kind == TYP) {
buf.append(outer().toString());
buf.append(".");
buf.append(className(tsym, false));
} else {
buf.append(className(tsym, true));
}
if (typarams().nonEmpty()) {
buf.append('<');
buf.append(typarams().toString());
buf.append(">");
}
return buf.toString();
}
private String className(Symbol sym, boolean longform) {
if (sym.name.len == 0)
return "<anonymous " + (sym.type.interfaces().nonEmpty() ?
(Type) sym.type.interfaces().head :
sym.type.supertype()) + ">" +
(moreInfo ? String.valueOf(sym.hashCode()) : "");
else if (longform)
return sym.fullName().toString();
else
return sym.name.toString();
}
/**
* The Java source which this type represents. Use of this method
* will result in the loss of the plain-language description for
* the type.
*/
public String toJava() {
StringBuffer buf = new StringBuffer();
if (outer().tag == CLASS && tsym.owner.kind == TYP) {
buf.append(outer().toJava());
buf.append(".");
buf.append(javaClassName(tsym, false));
} else {
buf.append(javaClassName(tsym, true));
}
if (typarams().nonEmpty()) {
buf.append('<');
buf.append(typarams().toString());
buf.append(">");
}
return buf.toString();
}
private String javaClassName(Symbol sym, boolean longform) {
if (sym.name.len == 0) {
String s;
if (sym.type.interfaces().nonEmpty()) {
s = Log.getLocalizedString("anonymous.class",
((Type) sym.type.interfaces().head).toJava());
} else {
s = Log.getLocalizedString("anonymous.class",
sym.type.supertype().toJava());
}
if (moreInfo)
s += String.valueOf(sym.hashCode());
return s;
} else if (longform) {
return sym.fullName().toString();
} else {
return sym.name.toString();
}
}
public List typarams() {
if (typarams_field == null) {
complete();
typarams_field = tsym.type.typarams();
}
return typarams_field;
}
public Type outer() {
if (outer_field == null) {
complete();
outer_field = tsym.type.outer();
}
return outer_field;
}
public Type supertype() {
if (supertype_field == null) {
complete();
Type st = ((ClassType) tsym.type).supertype_field;
if (st == null) {
supertype_field = noType;
} else if (this == tsym.type) {
supertype_field = st;
} else {
List ownparams = classBound().allparams();
List symparams = tsym.type.allparams();
supertype_field = (ownparams.isEmpty()) ? st.erasure() :
st.subst(symparams, ownparams);
}
}
return supertype_field;
}
public List interfaces() {
if (interfaces_field == null) {
complete();
List is = ((ClassType) tsym.type).interfaces_field;
if (is == null) {
interfaces_field = Type.emptyList;
} else if (this == tsym.type) {
interfaces_field = is;
} else {
List ownparams = allparams();
List symparams = tsym.type.allparams();
if (ownparams.isEmpty())
interfaces_field = erasure(is);
else
interfaces_field = subst(is, symparams, ownparams);
}
}
return interfaces_field;
}
public List allparams() {
if (allparams_field == null) {
allparams_field = typarams().prependList(outer().allparams());
}
return allparams_field;
}
public Type asSuper(Symbol sym) {
if (tsym == sym) {
return this;
} else {
Type st = supertype();
if (st.tag == CLASS || st.tag == ERROR) {
Type t = st.asSuper(sym);
if (t != null)
return t;
}
if ((sym.flags() & INTERFACE) != 0) {
for (List l = interfaces(); l.nonEmpty(); l = l.tail) {
Type t = ((Type) l.head).asSuper(sym);
if (t != null)
return t;
}
}
return null;
}
}
public Type asOuterSuper(Symbol sym) {
Type t = this;
do {
Type s = t.asSuper(sym);
if (s != null)
return s;
t = t.outer();
} while (t.tag == CLASS)
;
return null;
}
public Type classBound() {
Type outer1 = outer().classBound();
if (outer1 != outer_field)
return new ClassType(outer1, typarams(), tsym);
else
return this;
}
public Type asSub(Symbol sym) {
if (tsym == sym) {
return this;
} else {
Type base = sym.type.asSuper(tsym);
if (base == null)
return null;
ListBuffer from = new ListBuffer();
ListBuffer to = new ListBuffer();
adapt(base, this, from, to);
Type res = sym.type.subst(from.toList(), to.toList());
if (!res.isSubType(this))
return null;
for (List l = sym.type.allparams(); l.nonEmpty(); l = l.tail)
if (res.contains((Type) l.head) && !this.contains((Type) l.head))
return res.erasure();
return res;
}
}
/**
* Adapt a type by computing a substitution which
* maps a source type to a target type.
* @param from the source type
* @param target the target type
* @param from the type variables of the computed substitution
* @param to the types of the computed substitution.
*/
private static void adapt(Type source, Type target, ListBuffer from,
ListBuffer to) {
if (source.tag == target.tag) {
switch (source.tag) {
case CLASS:
adapt(source.allparams(), target.allparams(), from, to);
break;
case ARRAY:
adapt(source.elemtype(), target.elemtype(), from, to);
}
}
}
/**
* Adapt a type by computing a substitution which
* maps a list of source types to a list of target types.
* @param source the source type
* @param target the target type
* @param from the type variables of the computed substitution
* @param to the types of the computed substitution.
*/
private static void adapt(List source, List target, ListBuffer from,
ListBuffer to) {
if (source.length() == target.length()) {
while (source.nonEmpty()) {
adapt((Type) source.head, (Type) target.head, from, to);
source = source.tail;
target = target.tail;
}
}
}
public Type memberType(Symbol sym) {
Symbol owner = sym.owner;
long flags = sym.flags();
if (((flags & STATIC) == 0) && owner.type.isParameterized()) {
Type base = this.asOuterSuper(owner);
if (base != null) {
List ownerParams = owner.type.allparams();
List baseParams = base.allparams();
if (ownerParams.nonEmpty()) {
if (baseParams.isEmpty()) {
return sym.type.erasure();
} else {
return sym.type.subst(ownerParams, baseParams);
}
}
}
}
return sym.type;
}
public Type subst(List from, List to) {
if (from.tail == null) {
return this;
} else if ((tsym.flags() & COMPOUND) == 0) {
Type outer = outer();
List typarams = typarams();
List typarams1 = subst(typarams, from, to);
Type outer1 = outer.subst(from, to);
if (typarams1 == typarams && outer1 == outer)
return this;
else
return new ClassType(outer1, typarams1, tsym);
} else {
Type st = supertype().subst(from, to);
List is = subst(interfaces(), from, to);
if (st == supertype() && is == interfaces())
return this;
else
return makeCompoundType(is.prepend(st), tsym);
}
}
public boolean isErroneous() {
return outer().isErroneous() || isErroneous(typarams()) ||
this != tsym.type && tsym.type.isErroneous();
}
public boolean isParameterized() {
return allparams().tail != null;
}
public Type erasure() {
return tsym.erasure();
}
public Type map(Mapping f) {
Type outer = outer();
Type outer1 = f.apply(outer);
List typarams = typarams();
List typarams1 = map(typarams, f);
if (outer1 == outer && typarams1 == typarams)
return this;
else
return new ClassType(outer1, typarams1, tsym);
}
public boolean contains(Type elem) {
return elem == this || (isParameterized() &&
(outer().contains(elem) || contains(typarams(), elem)));
}
public boolean isSameType(Type that) {
if (this == that)
return true;
if (that.tag >= firstPartialTag)
return that.isSameType(this);
return this.tsym == that.tsym && this.outer().isSameType(that.outer()) &&
isSameTypes(this.typarams(), that.typarams());
}
public boolean isSubType(Type that) {
if (this == that)
return true;
if (that.tag >= firstPartialTag)
return that.isSuperType(this);
if (this.tsym == that.tsym)
return (!that.isParameterized() ||
isSameTypes(this.typarams(), that.typarams())) &&
this.outer().isSubType(that.outer());
if ((that.tsym.flags() & INTERFACE) != 0)
for (List is = this.interfaces(); is.nonEmpty(); is = is.tail)
if (((Type) is.head).isSubType(that))
return true;
Type st = this.supertype();
if (st.tag == CLASS && st.isSubType(that))
return true;
return st.isErroneous();
}
/**
* The rules for castability are extended to parameterized types
* as follows:
* (1) One may always cast to a supertype
* (2) One may cast to a subtype C<...> provided there is only
* one type with the subtype's class part, C, that is a subtype
* of this type. (This is equivalent to: C<...> = this.asSub(C).
* (3) One may cast an interface to an unparameterized class.
* (4) One may cast a non-final class to an unparameterized interface.
*/
public boolean isCastable(Type that) {
return that.tag == ERROR || (that.tag == CLASS || that.tag == ARRAY) &&
(this.isSubType(that) || (that.isSubType(this) &&
(that.tag == ARRAY || that.tsym.type == that ||
(this.asSub(that.tsym) != null &&
that.isSameType(this.asSub(that.tsym))))) ||
that.tag == CLASS && that.allparams().isEmpty() &&
((that.tsym.flags() & INTERFACE) != 0 &&
(this.tsym.flags() & FINAL) == 0 ||
(this.tsym.flags() & INTERFACE) != 0 &&
(that.tsym.flags() & FINAL) == 0));
}
public void complete() {
if (tsym.completer != null)
tsym.complete();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -