|
Lines 25-30
Link Here
|
| 25 |
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; |
25 |
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; |
| 26 |
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; |
26 |
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; |
| 27 |
import org.eclipse.jdt.internal.compiler.util.ObjectVector; |
27 |
import org.eclipse.jdt.internal.compiler.util.ObjectVector; |
|
|
28 |
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; |
| 28 |
import org.eclipse.jdt.internal.compiler.util.SimpleSet; |
29 |
import org.eclipse.jdt.internal.compiler.util.SimpleSet; |
| 29 |
|
30 |
|
| 30 |
public abstract class Scope { |
31 |
public abstract class Scope { |
|
Lines 4023-4026
Link Here
|
| 4023 |
int startIndex() { |
4024 |
int startIndex() { |
| 4024 |
return 0; |
4025 |
return 0; |
| 4025 |
} |
4026 |
} |
|
|
4027 |
/* Given an allocation type and arguments at the allocation site, answer a synthetic generic static factory method |
| 4028 |
that could instead be invoked with identical results. Return null if no compatible, visible, most specific method |
| 4029 |
could be found. This method is modeled after Scope.getConstructor and Scope.getMethod. |
| 4030 |
*/ |
| 4031 |
public MethodBinding getStaticFactory (ReferenceBinding allocationType, TypeBinding[] argumentTypes, final InvocationSite allocationSite) { |
| 4032 |
TypeVariableBinding[] classTypeVariables = allocationType.typeVariables(); |
| 4033 |
int classTypeVariablesArity = classTypeVariables.length; |
| 4034 |
MethodBinding[] methods = allocationType.getMethods(TypeConstants.INIT, argumentTypes.length); |
| 4035 |
MethodBinding [] staticFactories = new MethodBinding[methods.length]; |
| 4036 |
int sfi = 0; |
| 4037 |
for (int i = 0, length = methods.length; i < length; i++) { |
| 4038 |
MethodBinding method = methods[i]; |
| 4039 |
|
| 4040 |
TypeVariableBinding[] methodTypeVariables = method.typeVariables(); |
| 4041 |
int methodTypeVariablesArity = methodTypeVariables.length; |
| 4042 |
|
| 4043 |
final TypeBinding[] genericTypeArguments = allocationSite.genericTypeArguments(); |
| 4044 |
if (genericTypeArguments != null && genericTypeArguments.length < methodTypeVariablesArity) |
| 4045 |
continue; // wrong tree, don't bark. |
| 4046 |
MethodBinding staticFactory = new MethodBinding(method.modifiers | ClassFileConstants.AccStatic, TypeConstants.SYNTHETIC_STATIC_FACTORY, |
| 4047 |
null, null, null, method.declaringClass); |
| 4048 |
staticFactory.typeVariables = new TypeVariableBinding[classTypeVariablesArity + (genericTypeArguments == null ? methodTypeVariablesArity : 0)]; |
| 4049 |
final SimpleLookupTable map = new SimpleLookupTable(classTypeVariablesArity + methodTypeVariablesArity); |
| 4050 |
// Rename each type variable T of the type to T' |
| 4051 |
final LookupEnvironment environment = environment(); |
| 4052 |
for (int j = 0; j < classTypeVariablesArity; j++) { |
| 4053 |
map.put(classTypeVariables[j], staticFactory.typeVariables[j] = new TypeVariableBinding(CharOperation.concat(classTypeVariables[j].sourceName, "'".toCharArray()), //$NON-NLS-1$ |
| 4054 |
staticFactory, j, environment)); |
| 4055 |
} |
| 4056 |
// Rename each type variable U of method U to U'' if not explicitly parameterized. Otherwise use the parameterizing type. |
| 4057 |
for (int j = classTypeVariablesArity, max = classTypeVariablesArity + methodTypeVariablesArity; j < max; j++) { |
| 4058 |
map.put(methodTypeVariables[j - classTypeVariablesArity], |
| 4059 |
genericTypeArguments != null ? genericTypeArguments[j - classTypeVariablesArity] : |
| 4060 |
(staticFactory.typeVariables[j] = new TypeVariableBinding(CharOperation.concat(methodTypeVariables[j - classTypeVariablesArity].sourceName, "''".toCharArray()), //$NON-NLS-1$ |
| 4061 |
staticFactory, j, environment))); |
| 4062 |
} |
| 4063 |
final Scope scope = this; |
| 4064 |
Substitution substitution = new Substitution() { |
| 4065 |
public LookupEnvironment environment() { |
| 4066 |
return scope.environment(); |
| 4067 |
} |
| 4068 |
public boolean isRawSubstitution() { |
| 4069 |
return false; |
| 4070 |
} |
| 4071 |
public TypeBinding substitute(TypeVariableBinding typeVariable) { |
| 4072 |
return (TypeBinding) map.get(typeVariable); |
| 4073 |
} |
| 4074 |
}; |
| 4075 |
|
| 4076 |
// initialize new variable bounds |
| 4077 |
for (int j = 0, max = classTypeVariablesArity + methodTypeVariablesArity; j < max; j++) { |
| 4078 |
TypeVariableBinding originalVariable = j < classTypeVariablesArity ? classTypeVariables[j] : methodTypeVariables[j - classTypeVariablesArity]; |
| 4079 |
TypeBinding substitutedType = (TypeBinding) map.get(originalVariable); |
| 4080 |
if (substitutedType instanceof TypeVariableBinding) { |
| 4081 |
TypeVariableBinding substitutedVariable = (TypeVariableBinding) substitutedType; |
| 4082 |
TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass); |
| 4083 |
ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces); |
| 4084 |
if (originalVariable.firstBound != null) { |
| 4085 |
substitutedVariable.firstBound = originalVariable.firstBound == originalVariable.superclass |
| 4086 |
? substitutedSuperclass // could be array type or interface |
| 4087 |
: substitutedInterfaces[0]; |
| 4088 |
} |
| 4089 |
switch (substitutedSuperclass.kind()) { |
| 4090 |
case Binding.ARRAY_TYPE : |
| 4091 |
substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); |
| 4092 |
substitutedVariable.superInterfaces = substitutedInterfaces; |
| 4093 |
break; |
| 4094 |
default: |
| 4095 |
if (substitutedSuperclass.isInterface()) { |
| 4096 |
substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); |
| 4097 |
int interfaceCount = substitutedInterfaces.length; |
| 4098 |
System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount); |
| 4099 |
substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass; |
| 4100 |
substitutedVariable.superInterfaces = substitutedInterfaces; |
| 4101 |
} else { |
| 4102 |
substitutedVariable.superclass = (ReferenceBinding) substitutedSuperclass; // typeVar was extending other typeVar which got substituted with interface |
| 4103 |
substitutedVariable.superInterfaces = substitutedInterfaces; |
| 4104 |
} |
| 4105 |
} |
| 4106 |
} |
| 4107 |
} |
| 4108 |
TypeVariableBinding[] returnTypeParameters = new TypeVariableBinding[classTypeVariablesArity]; |
| 4109 |
for (int j = 0; j < classTypeVariablesArity; j++) { |
| 4110 |
returnTypeParameters[j] = (TypeVariableBinding) map.get(classTypeVariables[j]); |
| 4111 |
} |
| 4112 |
staticFactory.returnType = environment.createParameterizedType(allocationType, returnTypeParameters, allocationType.enclosingType()); |
| 4113 |
staticFactory.parameters = Scope.substitute(substitution, method.parameters); |
| 4114 |
staticFactory.thrownExceptions = Scope.substitute(substitution, method.thrownExceptions); |
| 4115 |
if (staticFactory.thrownExceptions == null) { |
| 4116 |
staticFactory.thrownExceptions = Binding.NO_EXCEPTIONS; |
| 4117 |
} |
| 4118 |
staticFactories[sfi++] = new ParameterizedMethodBinding((ParameterizedTypeBinding) environment.convertToParameterizedType(staticFactory.declaringClass), |
| 4119 |
staticFactory); |
| 4120 |
} |
| 4121 |
if (sfi != methods.length) { |
| 4122 |
System.arraycopy(staticFactories, 0, staticFactories = new MethodBinding[sfi], 0, sfi); |
| 4123 |
} |
| 4124 |
InvocationSite site = new InvocationSite() { // Alternate site to not expose the generic type arguments as they have already been substituted. |
| 4125 |
public int sourceStart() { return allocationSite.sourceStart(); } |
| 4126 |
public int sourceEnd() { return allocationSite.sourceEnd(); } |
| 4127 |
public void setFieldIndex(int depth) { allocationSite.setFieldIndex(depth); } |
| 4128 |
public void setDepth(int depth) { allocationSite.setDepth(depth);} |
| 4129 |
public void setActualReceiverType(ReferenceBinding receiverType) { allocationSite.setActualReceiverType(receiverType);} |
| 4130 |
public boolean isTypeAccess() { return allocationSite.isTypeAccess(); } |
| 4131 |
public boolean isSuperAccess() { return allocationSite.isSuperAccess(); } |
| 4132 |
public TypeBinding[] genericTypeArguments() { return null; } |
| 4133 |
public TypeBinding expectedType() { return allocationSite.expectedType(); } |
| 4134 |
}; |
| 4135 |
MethodBinding[] compatible = new MethodBinding[sfi]; |
| 4136 |
int compatibleIndex = 0; |
| 4137 |
for (int i = 0; i < sfi; i++) { |
| 4138 |
MethodBinding compatibleMethod = computeCompatibleMethod(staticFactories[i], argumentTypes, site); |
| 4139 |
if (compatibleMethod != null) { |
| 4140 |
if (compatibleMethod.isValidBinding()) |
| 4141 |
compatible[compatibleIndex++] = compatibleMethod; |
| 4142 |
} |
| 4143 |
} |
| 4144 |
|
| 4145 |
if (compatibleIndex == 0) { |
| 4146 |
return null; |
| 4147 |
} |
| 4148 |
MethodBinding[] visible = new MethodBinding[compatibleIndex]; |
| 4149 |
int visibleIndex = 0; |
| 4150 |
for (int i = 0; i < compatibleIndex; i++) { |
| 4151 |
MethodBinding method = compatible[i]; |
| 4152 |
if (method.canBeSeenBy(allocationSite, this)) |
| 4153 |
visible[visibleIndex++] = method; |
| 4154 |
} |
| 4155 |
if (visibleIndex == 0) { |
| 4156 |
return null; |
| 4157 |
} |
| 4158 |
return visibleIndex == 1 ? visible[0] : mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, allocationSite, allocationType); |
| 4159 |
} |
| 4026 |
} |
4160 |
} |