Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.google.gwt.dev.jjs.impl.ReferenceMapper Maven / Gradle / Ivy
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.dev.jjs.impl;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.jjs.ast.AccessModifier;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JConstructor;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JEnumType;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JNullType;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.util.StringInterner;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Creates unresolved references to types, fields, and methods.
*/
public class ReferenceMapper {
private final List argNames = new ArrayList();
private final Map fields = new HashMap();
private final Map methods = new HashMap();
private final Map sourceFields = new HashMap();
private final Map sourceMethods = new HashMap();
private final Map sourceTypes = new HashMap();
private final StringInterner stringInterner = StringInterner.get();
private final Map types = new HashMap();
{
put(JPrimitiveType.BOOLEAN, JPrimitiveType.BYTE, JPrimitiveType.CHAR, JPrimitiveType.DOUBLE,
JPrimitiveType.FLOAT, JPrimitiveType.INT, JPrimitiveType.LONG, JPrimitiveType.SHORT,
JPrimitiveType.VOID, JNullType.INSTANCE);
}
public void clearSource() {
sourceFields.clear();
sourceMethods.clear();
sourceTypes.clear();
}
public JField get(FieldBinding binding) {
binding = binding.original();
String key = signature(binding);
JField sourceField = sourceFields.get(key);
if (sourceField != null) {
assert !sourceField.isExternal();
return sourceField;
}
JField field = fields.get(key);
if (field == null) {
field = createField(binding);
assert field.isExternal();
fields.put(key, field);
}
return field;
}
public JMethod get(MethodBinding binding) {
binding = binding.original();
String key = signature(binding);
JMethod sourceMethod = sourceMethods.get(key);
if (sourceMethod != null) {
assert !sourceMethod.isExternal();
return sourceMethod;
}
JMethod method = methods.get(key);
if (method == null) {
if (binding.isConstructor()) {
method = createConstructor(SourceOrigin.UNKNOWN, binding);
} else {
method = createMethod(SourceOrigin.UNKNOWN, binding, null);
}
assert method.isExternal();
methods.put(key, method);
}
return method;
}
public JType get(TypeBinding binding) {
binding = binding.erasure();
String key = signature(binding);
JReferenceType sourceType = sourceTypes.get(key);
if (sourceType != null) {
assert !sourceType.isExternal();
return sourceType;
}
JType type = types.get(key);
if (type != null) {
assert type instanceof JPrimitiveType || type == JNullType.INSTANCE || type.isExternal();
return type;
}
assert !(binding instanceof BaseTypeBinding);
if (binding instanceof ArrayBinding) {
ArrayBinding arrayBinding = (ArrayBinding) binding;
JArrayType arrayType = new JArrayType(get(arrayBinding.elementsType()));
if (arrayType.isExternal()) {
types.put(key, arrayType);
} else {
sourceTypes.put(key, arrayType);
}
return arrayType;
} else {
ReferenceBinding refBinding = (ReferenceBinding) binding;
JDeclaredType declType = createType(refBinding);
try {
if (declType instanceof JClassType) {
ReferenceBinding superclass = refBinding.superclass();
if (superclass != null && superclass.isValidBinding()) {
((JClassType) declType).setSuperClass((JClassType) get(superclass));
}
}
ReferenceBinding[] superInterfaces = refBinding.superInterfaces();
if (superInterfaces != null) {
for (ReferenceBinding intf : superInterfaces) {
if (intf.isValidBinding()) {
declType.addImplements((JInterfaceType) get(intf));
}
}
}
} catch (AbortCompilation ignored) {
/*
* The currently-compiling unit has no errors; however, we're running
* into a case where it references something with a bad hierarchy. This
* doesn't cause an error in the current unit, but it does mean we run
* into a wall here trying to construct the hierarchy. Catch the error
* so that compilation can proceed; the error units themselves will
* eventually cause the full compile to error out.
*/
}
// Emulate clinit method for super clinit calls.
JMethod clinit =
new JMethod(SourceOrigin.UNKNOWN, "$clinit", declType, JPrimitiveType.VOID, false, true,
true, AccessModifier.PRIVATE);
clinit.freezeParamTypes();
clinit.setSynthetic();
declType.addMethod(clinit);
declType.setExternal(true);
types.put(key, declType);
return declType;
}
}
public void setField(FieldBinding binding, JField field) {
String key = signature(binding);
sourceFields.put(key, field);
}
public void setMethod(MethodBinding binding, JMethod method) {
String key = signature(binding);
sourceMethods.put(key, method);
}
public void setSourceType(SourceTypeBinding binding, JDeclaredType type) {
String key = signature(binding);
sourceTypes.put(key, type);
}
JMethod createConstructor(SourceInfo info, MethodBinding b) {
JDeclaredType enclosingType = (JDeclaredType) get(b.declaringClass);
JMethod method = new JConstructor(info, (JClassType) enclosingType);
enclosingType.addMethod(method);
/*
* Don't need to synthesize enum intrinsic args because enum ctors can only
* be called locally.
*/
int argPosition = 0;
ReferenceBinding declaringClass = b.declaringClass;
if (declaringClass.isNestedType() && !declaringClass.isStatic()) {
// add synthetic args for outer this
if (declaringClass.syntheticEnclosingInstanceTypes() != null) {
for (ReferenceBinding argType : declaringClass.syntheticEnclosingInstanceTypes()) {
createParameter(info, argType, method, argPosition++);
}
}
}
// User args.
argPosition = mapParameters(info, method, b, argPosition);
if (declaringClass.isNestedType() && !declaringClass.isStatic()) {
// add synthetic args for locals
if (declaringClass.syntheticOuterLocalVariables() != null) {
for (SyntheticArgumentBinding arg : declaringClass.syntheticOuterLocalVariables()) {
createParameter(info, arg.type, method, argPosition++);
}
}
}
mapExceptions(method, b);
if (b.isSynthetic()) {
method.setSynthetic();
}
return method;
}
JMethod createMethod(SourceInfo info, MethodBinding b, String[] paramNames) {
JDeclaredType enclosingType = (JDeclaredType) get(b.declaringClass);
JMethod method =
new JMethod(info, intern(b.selector), enclosingType, get(b.returnType), b.isAbstract(), b
.isStatic(), b.isFinal(), AccessModifier.fromMethodBinding(b));
enclosingType.addMethod(method);
if (paramNames == null) {
mapParameters(info, method, b, 0);
} else {
mapParameters(info, method, b, paramNames);
}
mapExceptions(method, b);
if (b.isSynthetic()) {
method.setSynthetic();
}
return method;
}
private JField createField(FieldBinding binding) {
JDeclaredType enclosingType = (JDeclaredType) get(binding.declaringClass);
JField field =
new JField(SourceOrigin.UNKNOWN, intern(binding.name), enclosingType, get(binding.type),
binding.isStatic(), GwtAstBuilder.getFieldDisposition(binding));
enclosingType.addField(field);
return field;
}
private JParameter createParameter(SourceInfo info, TypeBinding paramType,
JMethod enclosingMethod, int argPosition) {
JType type = get(paramType);
ensureArgNames(argPosition);
JParameter param =
new JParameter(info, argNames.get(argPosition), type, true, false, enclosingMethod);
enclosingMethod.addParam(param);
return param;
}
private JParameter createParameter(SourceInfo info, TypeBinding paramType,
JMethod enclosingMethod, String name) {
JParameter param = new JParameter(info, name, get(paramType), true, false, enclosingMethod);
enclosingMethod.addParam(param);
return param;
}
private JDeclaredType createType(ReferenceBinding binding) {
String name = GwtAstBuilder.dotify(binding.compoundName);
SourceInfo info = SourceOrigin.UNKNOWN;
if (binding.isClass()) {
return new JClassType(info, name, binding.isAbstract(), binding.isFinal());
} else if (binding.isInterface() || binding.isAnnotationType()) {
return new JInterfaceType(info, name);
} else if (binding.isEnum()) {
if (binding.isAnonymousType()) {
// Don't model an enum subclass as a JEnumType.
return new JClassType(info, name, false, true);
} else {
return new JEnumType(info, name, binding.isAbstract());
}
} else {
throw new InternalCompilerException("ReferenceBinding is not a class, interface, or enum.");
}
}
private void ensureArgNames(int required) {
for (int i = argNames.size(); i <= required; ++i) {
argNames.add(intern("arg" + i));
}
}
private String intern(char[] cs) {
return intern(String.valueOf(cs));
}
private String intern(String s) {
return stringInterner.intern(s);
}
private void mapExceptions(JMethod method, MethodBinding binding) {
for (ReferenceBinding thrownBinding : binding.thrownExceptions) {
JClassType type = (JClassType) get(thrownBinding);
method.addThrownException(type);
}
}
private int mapParameters(SourceInfo info, JMethod method, MethodBinding binding, int argPosition) {
if (binding.parameters != null) {
ensureArgNames(argPosition + binding.parameters.length);
for (TypeBinding argType : binding.parameters) {
createParameter(info, argType, method, argNames.get(argPosition++));
}
}
method.freezeParamTypes();
return argPosition;
}
private void mapParameters(SourceInfo info, JMethod method, MethodBinding binding,
String[] paramNames) {
if (binding.parameters != null) {
int i = 0;
for (TypeBinding argType : binding.parameters) {
createParameter(info, argType, method, paramNames[i++]);
}
}
method.freezeParamTypes();
}
private void put(JType... baseTypes) {
for (JType type : baseTypes) {
types.put(type.getName(), type);
}
}
private String signature(FieldBinding binding) {
StringBuilder sb = new StringBuilder();
sb.append(binding.declaringClass.constantPoolName());
sb.append('.');
sb.append(binding.name);
sb.append(':');
sb.append(binding.type.signature());
return sb.toString();
}
private String signature(MethodBinding binding) {
StringBuilder sb = new StringBuilder();
sb.append(binding.declaringClass.constantPoolName());
sb.append('.');
sb.append(binding.selector);
sb.append('(');
for (TypeBinding paramType : binding.parameters) {
sb.append(paramType.signature());
}
sb.append(')');
sb.append(binding.returnType.signature());
return sb.toString();
}
private String signature(TypeBinding binding) {
if (binding.isBaseType()) {
return String.valueOf(binding.sourceName());
} else {
return String.valueOf(binding.constantPoolName());
}
}
}