/* * Copyright (c) 2013, the Dart project authors. * * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html * * 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.dart.engine.element; import com.google.dart.engine.ast.Identifier; import com.google.dart.engine.context.AnalysisContext; import com.google.dart.engine.internal.constant.EvaluationResultImpl; import com.google.dart.engine.internal.element.ClassElementImpl; import com.google.dart.engine.internal.element.CompilationUnitElementImpl; import com.google.dart.engine.internal.element.ConstFieldElementImpl; import com.google.dart.engine.internal.element.ConstructorElementImpl; import com.google.dart.engine.internal.element.ExportElementImpl; import com.google.dart.engine.internal.element.FieldElementImpl; import com.google.dart.engine.internal.element.FieldFormalParameterElementImpl; import com.google.dart.engine.internal.element.FunctionElementImpl; import com.google.dart.engine.internal.element.HtmlElementImpl; import com.google.dart.engine.internal.element.ImportElementImpl; import com.google.dart.engine.internal.element.LibraryElementImpl; import com.google.dart.engine.internal.element.LocalVariableElementImpl; import com.google.dart.engine.internal.element.MethodElementImpl; import com.google.dart.engine.internal.element.ParameterElementImpl; import com.google.dart.engine.internal.element.PrefixElementImpl; import com.google.dart.engine.internal.element.PropertyAccessorElementImpl; import com.google.dart.engine.internal.element.TopLevelVariableElementImpl; import com.google.dart.engine.internal.element.TypeParameterElementImpl; import com.google.dart.engine.internal.object.DartObjectImpl; import com.google.dart.engine.internal.object.GenericState; import com.google.dart.engine.internal.object.IntState; import com.google.dart.engine.internal.object.StringState; import com.google.dart.engine.internal.resolver.TypeProvider; import com.google.dart.engine.internal.type.FunctionTypeImpl; import com.google.dart.engine.internal.type.InterfaceTypeImpl; import com.google.dart.engine.internal.type.TypeParameterTypeImpl; import com.google.dart.engine.internal.type.VoidTypeImpl; import com.google.dart.engine.source.NonExistingSource; import com.google.dart.engine.source.Source; import com.google.dart.engine.source.UriKind; import com.google.dart.engine.type.InterfaceType; import com.google.dart.engine.type.Type; import com.google.dart.engine.utilities.dart.ParameterKind; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; /** * The class {@code ElementFactory} defines utility methods used to create elements for testing * purposes. The elements that are created are complete in the sense that as much of the element * model as can be created, given the provided information, has been created. */ public final class ElementFactory { /** * The element representing the class 'Object'. */ private static ClassElementImpl objectElement; public static ClassElementImpl classElement(String typeName, InterfaceType superclassType, String... parameterNames) { ClassElementImpl element = new ClassElementImpl(typeName, 0); element.setSupertype(superclassType); InterfaceTypeImpl type = new InterfaceTypeImpl(element); element.setType(type); int count = parameterNames.length; if (count > 0) { TypeParameterElementImpl[] typeParameters = new TypeParameterElementImpl[count]; TypeParameterTypeImpl[] typeParameterTypes = new TypeParameterTypeImpl[count]; for (int i = 0; i < count; i++) { TypeParameterElementImpl typeParameter = new TypeParameterElementImpl(parameterNames[i], 0); typeParameters[i] = typeParameter; typeParameterTypes[i] = new TypeParameterTypeImpl(typeParameter); typeParameter.setType(typeParameterTypes[i]); } element.setTypeParameters(typeParameters); type.setTypeArguments(typeParameterTypes); } return element; } public static ClassElementImpl classElement(String typeName, String... parameterNames) { return classElement(typeName, getObjectType(), parameterNames); } public static CompilationUnitElementImpl compilationUnit(String fileName) { Source source = new NonExistingSource(fileName, UriKind.FILE_URI); CompilationUnitElementImpl unit = new CompilationUnitElementImpl(fileName); unit.setSource(source); return unit; } public static ConstructorElementImpl constructorElement(ClassElement definingClass, String name, boolean isConst, Type... argumentTypes) { Type type = definingClass.getType(); ConstructorElementImpl constructor = name == null ? new ConstructorElementImpl("", -1) : new ConstructorElementImpl(name, 0); constructor.setConst(isConst); int count = argumentTypes.length; ParameterElement[] parameters = new ParameterElement[count]; for (int i = 0; i < count; i++) { ParameterElementImpl parameter = new ParameterElementImpl("a" + i, i); parameter.setType(argumentTypes[i]); parameter.setParameterKind(ParameterKind.REQUIRED); parameters[i] = parameter; } constructor.setParameters(parameters); constructor.setReturnType(type); FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor); constructor.setType(constructorType); return constructor; } public static ConstructorElementImpl constructorElement(ClassElement definingClass, String name, Type... argumentTypes) { return constructorElement(definingClass, name, false, argumentTypes); } public static ClassElementImpl enumElement(TypeProvider typeProvider, String enumName, String... constantNames) { // // Build the enum. // ClassElementImpl enumElement = new ClassElementImpl(enumName, -1); InterfaceTypeImpl enumType = new InterfaceTypeImpl(enumElement); enumElement.setType(enumType); enumElement.setSupertype(getObjectType()); enumElement.setEnum(true); // // Populate the fields. // ArrayList<FieldElement> fields = new ArrayList<FieldElement>(); InterfaceType intType = typeProvider.getIntType(); InterfaceType stringType = typeProvider.getStringType(); String indexFieldName = "index"; FieldElementImpl indexField = new FieldElementImpl(indexFieldName, -1); indexField.setFinal(true); indexField.setType(intType); fields.add(indexField); String nameFieldName = "_name"; FieldElementImpl nameField = new FieldElementImpl(nameFieldName, -1); nameField.setFinal(true); nameField.setType(stringType); fields.add(nameField); FieldElementImpl valuesField = new FieldElementImpl("values", -1); valuesField.setStatic(true); valuesField.setConst(true); valuesField.setType(typeProvider.getListType().substitute(new Type[] {enumType})); fields.add(valuesField); // // Build the enum constants. // int constantCount = constantNames.length; for (int i = 0; i < constantCount; i++) { String constantName = constantNames[i]; FieldElementImpl constantElement = new ConstFieldElementImpl(constantName, -1); constantElement.setStatic(true); constantElement.setConst(true); constantElement.setType(enumType); HashMap<String, DartObjectImpl> fieldMap = new HashMap<String, DartObjectImpl>(); fieldMap.put(indexFieldName, new DartObjectImpl(intType, new IntState(BigInteger.valueOf(i)))); fieldMap.put(nameFieldName, new DartObjectImpl(stringType, new StringState(constantName))); DartObjectImpl value = new DartObjectImpl(enumType, new GenericState(fieldMap)); constantElement.setEvaluationResult(new EvaluationResultImpl(value)); fields.add(constantElement); } // // Finish building the enum. // enumElement.setFields(fields.toArray(new FieldElement[fields.size()])); // Client code isn't allowed to invoke the constructor, so we do not model it. return enumElement; } public static ExportElementImpl exportFor(LibraryElement exportedLibrary, NamespaceCombinator... combinators) { ExportElementImpl spec = new ExportElementImpl(); spec.setExportedLibrary(exportedLibrary); spec.setCombinators(combinators); return spec; } public static FieldElementImpl fieldElement(String name, boolean isStatic, boolean isFinal, boolean isConst, Type type) { FieldElementImpl field = new FieldElementImpl(name, 0); field.setConst(isConst); field.setFinal(isFinal); field.setStatic(isStatic); field.setType(type); PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl(field); getter.setGetter(true); getter.setSynthetic(true); getter.setVariable(field); getter.setReturnType(type); field.setGetter(getter); FunctionTypeImpl getterType = new FunctionTypeImpl(getter); getter.setType(getterType); if (!isConst && !isFinal) { PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl(field); setter.setSetter(true); setter.setSynthetic(true); setter.setVariable(field); setter.setParameters(new ParameterElement[] {requiredParameter("_" + name, type)}); setter.setReturnType(VoidTypeImpl.getInstance()); setter.setType(new FunctionTypeImpl(setter)); field.setSetter(setter); } return field; } public static FieldFormalParameterElementImpl fieldFormalParameter(Identifier name) { return new FieldFormalParameterElementImpl(name); } public static FunctionElementImpl functionElement(String functionName) { return functionElement(functionName, null, null, null, null); } public static FunctionElementImpl functionElement(String functionName, ClassElement returnElement) { return functionElement(functionName, returnElement, null, null); } public static FunctionElementImpl functionElement(String functionName, ClassElement returnElement, ClassElement[] normalParameters, ClassElement[] optionalParameters) { // We don't create parameter elements because we don't have parameter names FunctionElementImpl functionElement = new FunctionElementImpl(functionName, 0); FunctionTypeImpl functionType = new FunctionTypeImpl(functionElement); functionElement.setType(functionType); // return type if (returnElement == null) { functionElement.setReturnType(VoidTypeImpl.getInstance()); } else { functionElement.setReturnType(returnElement.getType()); } // parameters int normalCount = normalParameters == null ? 0 : normalParameters.length; int optionalCount = optionalParameters == null ? 0 : optionalParameters.length; int totalCount = normalCount + optionalCount; ParameterElement[] parameters = new ParameterElement[totalCount]; for (int i = 0; i < totalCount; i++) { ParameterElementImpl parameter = new ParameterElementImpl("a" + i, i); if (i < normalCount) { parameter.setType(normalParameters[i].getType()); parameter.setParameterKind(ParameterKind.REQUIRED); } else { parameter.setType(optionalParameters[i - normalCount].getType()); parameter.setParameterKind(ParameterKind.POSITIONAL); } parameters[i] = parameter; } functionElement.setParameters(parameters); // done return functionElement; } public static FunctionElementImpl functionElement(String functionName, ClassElement returnElement, ClassElement[] normalParameters, String[] names, ClassElement[] namedParameters) { FunctionElementImpl functionElement = new FunctionElementImpl(functionName, 0); FunctionTypeImpl functionType = new FunctionTypeImpl(functionElement); functionElement.setType(functionType); // parameters int normalCount = normalParameters == null ? 0 : normalParameters.length; int nameCount = names == null ? 0 : names.length; int typeCount = namedParameters == null ? 0 : namedParameters.length; if (names != null && nameCount != typeCount) { throw new IllegalStateException( "The passed String[] and ClassElement[] arrays had different lengths."); } int totalCount = normalCount + nameCount; ParameterElement[] parameters = new ParameterElement[totalCount]; for (int i = 0; i < totalCount; i++) { if (i < normalCount) { ParameterElementImpl parameter = new ParameterElementImpl("a" + i, i); parameter.setType(normalParameters[i].getType()); parameter.setParameterKind(ParameterKind.REQUIRED); parameters[i] = parameter; } else { ParameterElementImpl parameter = new ParameterElementImpl(names[i - normalCount], i); parameter.setType(namedParameters[i - normalCount].getType()); parameter.setParameterKind(ParameterKind.NAMED); parameters[i] = parameter; } } functionElement.setParameters(parameters); // return type if (returnElement == null) { functionElement.setReturnType(VoidTypeImpl.getInstance()); } else { functionElement.setReturnType(returnElement.getType()); } return functionElement; } public static FunctionElementImpl functionElement(String functionName, ClassElement[] normalParameters) { return functionElement(functionName, null, normalParameters, null); } public static FunctionElementImpl functionElement(String functionName, ClassElement[] normalParameters, ClassElement[] optionalParameters) { return functionElement(functionName, null, normalParameters, optionalParameters); } public static FunctionElementImpl functionElement(String functionName, ClassElement[] normalParameters, String[] names, ClassElement[] namedParameters) { return functionElement(functionName, null, normalParameters, names, namedParameters); } public static FunctionElementImpl functionElementWithParameters(String functionName, Type returnType, ParameterElement... parameters) { FunctionElementImpl functionElement = new FunctionElementImpl(functionName, 0); functionElement.setReturnType(returnType == null ? VoidTypeImpl.getInstance() : returnType); functionElement.setParameters(parameters); FunctionTypeImpl functionType = new FunctionTypeImpl(functionElement); functionElement.setType(functionType); return functionElement; } public static ClassElementImpl getObject() { if (objectElement == null) { objectElement = classElement("Object", (InterfaceType) null); } return objectElement; } public static InterfaceType getObjectType() { return getObject().getType(); } public static PropertyAccessorElementImpl getterElement(String name, boolean isStatic, Type type) { FieldElementImpl field = new FieldElementImpl(name, -1); field.setStatic(isStatic); field.setSynthetic(true); field.setType(type); PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl(field); getter.setGetter(true); getter.setVariable(field); getter.setReturnType(type); field.setGetter(getter); FunctionTypeImpl getterType = new FunctionTypeImpl(getter); getter.setType(getterType); return getter; } public static HtmlElementImpl htmlUnit(AnalysisContext context, String fileName) { Source source = new NonExistingSource(fileName, UriKind.FILE_URI); HtmlElementImpl unit = new HtmlElementImpl(context, fileName); unit.setSource(source); return unit; } public static ImportElementImpl importFor(LibraryElement importedLibrary, PrefixElement prefix, NamespaceCombinator... combinators) { ImportElementImpl spec = new ImportElementImpl(0); spec.setImportedLibrary(importedLibrary); spec.setPrefix(prefix); spec.setCombinators(combinators); return spec; } public static LibraryElementImpl library(AnalysisContext context, String libraryName) { String fileName = "/" + libraryName + ".dart"; CompilationUnitElementImpl unit = compilationUnit(fileName); LibraryElementImpl library = new LibraryElementImpl(context, libraryName, 0); library.setDefiningCompilationUnit(unit); return library; } public static LocalVariableElementImpl localVariableElement(Identifier name) { return new LocalVariableElementImpl(name); } public static LocalVariableElementImpl localVariableElement(String name) { return new LocalVariableElementImpl(name, 0); } public static MethodElementImpl methodElement(String methodName, Type returnType, Type... argumentTypes) { MethodElementImpl method = new MethodElementImpl(methodName, 0); int count = argumentTypes.length; ParameterElement[] parameters = new ParameterElement[count]; for (int i = 0; i < count; i++) { ParameterElementImpl parameter = new ParameterElementImpl("a" + i, i); parameter.setType(argumentTypes[i]); parameter.setParameterKind(ParameterKind.REQUIRED); parameters[i] = parameter; } method.setParameters(parameters); method.setReturnType(returnType); FunctionTypeImpl methodType = new FunctionTypeImpl(method); method.setType(methodType); return method; } public static MethodElementImpl methodElementWithParameters(String methodName, Type[] typeArguments, Type returnType, ParameterElement... parameters) { MethodElementImpl method = new MethodElementImpl(methodName, 0); method.setParameters(parameters); method.setReturnType(returnType); FunctionTypeImpl methodType = new FunctionTypeImpl(method); methodType.setTypeArguments(typeArguments); method.setType(methodType); return method; } public static ParameterElementImpl namedParameter(String name) { ParameterElementImpl parameter = new ParameterElementImpl(name, 0); parameter.setParameterKind(ParameterKind.NAMED); return parameter; } public static ParameterElementImpl namedParameter(String name, Type type) { ParameterElementImpl parameter = new ParameterElementImpl(name, 0); parameter.setParameterKind(ParameterKind.NAMED); parameter.setType(type); return parameter; } public static ParameterElementImpl positionalParameter(String name) { ParameterElementImpl parameter = new ParameterElementImpl(name, 0); parameter.setParameterKind(ParameterKind.POSITIONAL); return parameter; } public static ParameterElementImpl positionalParameter(String name, Type type) { ParameterElementImpl parameter = new ParameterElementImpl(name, 0); parameter.setParameterKind(ParameterKind.POSITIONAL); parameter.setType(type); return parameter; } public static PrefixElementImpl prefix(String name) { return new PrefixElementImpl(name, 0); } public static ParameterElementImpl requiredParameter(String name) { ParameterElementImpl parameter = new ParameterElementImpl(name, 0); parameter.setParameterKind(ParameterKind.REQUIRED); return parameter; } public static ParameterElementImpl requiredParameter(String name, Type type) { ParameterElementImpl parameter = new ParameterElementImpl(name, 0); parameter.setParameterKind(ParameterKind.REQUIRED); parameter.setType(type); return parameter; } public static PropertyAccessorElementImpl setterElement(String name, boolean isStatic, Type type) { FieldElementImpl field = new FieldElementImpl(name, -1); field.setStatic(isStatic); field.setSynthetic(true); field.setType(type); PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl(field); getter.setGetter(true); getter.setVariable(field); getter.setReturnType(type); field.setGetter(getter); FunctionTypeImpl getterType = new FunctionTypeImpl(getter); getter.setType(getterType); ParameterElementImpl parameter = requiredParameter("a", type); PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl(field); setter.setSetter(true); setter.setSynthetic(true); setter.setVariable(field); setter.setParameters(new ParameterElement[] {parameter}); setter.setReturnType(VoidTypeImpl.getInstance()); setter.setType(new FunctionTypeImpl(setter)); field.setSetter(setter); return setter; } public static TopLevelVariableElementImpl topLevelVariableElement(Identifier name) { return new TopLevelVariableElementImpl(name); } public static TopLevelVariableElementImpl topLevelVariableElement(String name) { return topLevelVariableElement(name, false, false, null); } public static TopLevelVariableElementImpl topLevelVariableElement(String name, boolean isConst, boolean isFinal, Type type) { TopLevelVariableElementImpl variable = new TopLevelVariableElementImpl(name, -1); variable.setConst(isConst); variable.setFinal(isFinal); variable.setSynthetic(true); PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl(variable); getter.setGetter(true); getter.setSynthetic(true); getter.setVariable(variable); getter.setReturnType(type); variable.setGetter(getter); FunctionTypeImpl getterType = new FunctionTypeImpl(getter); getter.setType(getterType); if (!isFinal) { PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl(variable); setter.setSetter(true); setter.setStatic(true); setter.setSynthetic(true); setter.setVariable(variable); setter.setParameters(new ParameterElement[] {requiredParameter("_" + name, type)}); setter.setReturnType(VoidTypeImpl.getInstance()); setter.setType(new FunctionTypeImpl(setter)); variable.setSetter(setter); } return variable; } /** * Prevent the creation of instances of this class. */ private ElementFactory() { } }