Return-Path: X-Original-To: apmail-flex-commits-archive@www.apache.org Delivered-To: apmail-flex-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id D7287113B6 for ; Tue, 22 Jul 2014 13:35:27 +0000 (UTC) Received: (qmail 44673 invoked by uid 500); 22 Jul 2014 13:35:27 -0000 Delivered-To: apmail-flex-commits-archive@flex.apache.org Received: (qmail 44515 invoked by uid 500); 22 Jul 2014 13:35:27 -0000 Mailing-List: contact commits-help@flex.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@flex.apache.org Delivered-To: mailing list commits@flex.apache.org Received: (qmail 44493 invoked by uid 99); 22 Jul 2014 13:35:27 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 22 Jul 2014 13:35:27 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 3CD799AF1ED; Tue, 22 Jul 2014 13:35:27 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: cdutz@apache.org To: commits@flex.apache.org Date: Tue, 22 Jul 2014 13:35:28 -0000 Message-Id: In-Reply-To: <9b4488ac636245f08eb096463c80c652@git.apache.org> References: <9b4488ac636245f08eb096463c80c652@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [02/51] [partial] - Migrated the directory structure to a more Maven style structure. - Started migrating the Parser from Antlr2+3 and JFlex to Antlr4. http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AmbiguousDefinition.java ---------------------------------------------------------------------- diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AmbiguousDefinition.java b/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AmbiguousDefinition.java new file mode 100644 index 0000000..d6b3022 --- /dev/null +++ b/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AmbiguousDefinition.java @@ -0,0 +1,335 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.flex.compiler.internal.definitions; + +import java.util.List; + +import org.apache.flex.compiler.constants.IASLanguageConstants; +import org.apache.flex.compiler.definitions.IDefinition; +import org.apache.flex.compiler.definitions.IScopedDefinition; +import org.apache.flex.compiler.definitions.ITypeDefinition; +import org.apache.flex.compiler.projects.ICompilerProject; +import org.apache.flex.compiler.scopes.IASScope; + +import org.apache.flex.compiler.internal.scopes.ASFileScope; +import org.apache.flex.compiler.internal.scopes.ASScope; +import org.apache.flex.compiler.internal.semantics.SemanticUtils; + +/** + * IDefinition marker to represent ambiguous results. TODO: Can modify to keep + * track of what the ambiguous results were. This would be an improvement over + * TODO: ASC, which only reported that a reference was ambiguous, but didn't + * tell you which symbols it matched. + */ +public final class AmbiguousDefinition extends DefinitionBase implements IDefinition +{ + + private static AmbiguousDefinition def = new AmbiguousDefinition(); + + /** + * Is the definition passed in an AmbiguousDefinition. + * + * @param d the definition to check + * @return true if d is an AmbiguousDefinition + */ + public static boolean isAmbiguous(IDefinition d) + { + return d == def; + } + + /** + * Get the AmbiguousDefinition instance - currently there is only 1 + * AmbiguousDefinition instance, but we may modify that if each + * AmbiguousDefinition needs to keep track of it's ambiguous results + */ + public static AmbiguousDefinition get() + { + return def; + } + + /** + * Constructor. + */ + private AmbiguousDefinition() + { + super(""); + } + + /** + * Helper method to resolve apparently ambiguous results - there are 2 cases + * where we what looks like an ambiguity is not - getter/setter pairs, and + * legally re-declared local variables If we have a getter and a setter, we + * will end up with 2 resulting definitions, but we don't want to report + * them as ambiguous if they are a getter & setter for the same property. in + * this case, this method arbitrarily returns the first definition passed in + * - this should be ok because getter and setter definitions have methods to + * access the other one (resolveCorrespondingAccessor), so callers can use + * that to get at the one they want. If we have the same variable declared + * multiple times, then we don't want to report access to that variable as + * ambiguous. A variable can be legally re-declared when: 1. It is declared + * at global scope (outside a package), or it is a local var in a function. + * 2. All of the declarations of that variable are declared with the same + * type, or '*'. One of the VariableDefinitions with the specific type will + * be returned so that the correct type is used by the compiler e.g. if a + * Variable is declared twice, once as * and once as String, the result of + * this method will be the VariableDefinition typed as String. If all the + * VariableDefinitions are declared with the same type, then one will be + * arbitrarily returned. + * + * @param project The Project to use to resolve things + * @param defs an Array of definitions to compare + * @return the definition to use as the result of the lookup, if the + * ambiguity was successfully resolved, otherwise null + */ + public static IDefinition resolveAmbiguities(ICompilerProject project, List defs) + { + IDefinition resolvedDef = null; + + assert defs.size() > 1 : "This method should only be called when there is an ambiguity to resolve!"; + + // If we have exactly two definition to choose from, the + // two definitions might be a getter/setter pair. + if (SemanticUtils.isGetterSetterPair(defs, project)) + { + resolvedDef = defs.get(0); + } + + if (resolvedDef == null) + { + // check for redeclared variables and functions + + resolvedDef = defs.get(0); + assert resolvedDef.isInProject(project); + + List defsAfterFirst = defs.subList(1, defs.size()); + // The result of this loop will either be the VariableDefinition to return if all the ambiguities were + // resolved, or null if the ambiguities could not be resolved. + for (IDefinition d : defsAfterFirst) + { + assert d.isInProject(project); + if ( resolvedDef instanceof VariableDefinition ) + { + if( d instanceof VariableDefinition ) + resolvedDef = resolveAmbiguousVariableDefinitions(project, resolvedDef, d); + else if( d instanceof FunctionDefinition ) + resolvedDef = resolveAmbiguousFunctionVariableDefinitions(project, resolvedDef, d); + else + resolvedDef = null; + } + else if( resolvedDef instanceof FunctionDefinition ) + { + if( d instanceof FunctionDefinition ) + resolvedDef = resolveAmbiguousFunctionDefinitions(project, resolvedDef, d); + else if( d instanceof VariableDefinition ) + resolvedDef = resolveAmbiguousFunctionVariableDefinitions(project, resolvedDef, d); + else + resolvedDef = null; + } + else + { + resolvedDef = null; // At least one definition was not a variable definition, so just bail + } + + if (resolvedDef == null) + break; + } + } + return resolvedDef; + } + + /** + * Determine if two definitions have the same name, namespace qualifier, and + * containing scope. + * + * @param project {@link ICompilerProject} used to resolve namespace + * references. + * @param d1 first {@link IDefinition} to compare. + * @param d2 second {@link IDefinition} to compare. + * @return true if both of the specified {@link IDefinition}'s have the same + * name, namespace qualifier, and containing scope, false otherwise. + */ + private static boolean namesAndContainingScopeMatch(ICompilerProject project, IDefinition d1, IDefinition d2) + { + if (!d1.getBaseName().equals(d2.getBaseName())) + return false; + + if (!d1.resolveNamespace(project).equals(d2.resolveNamespace(project))) + return false; + + if (d1.getContainingScope() != d2.getContainingScope()) + return false; + return true; + } + + /** + * Helper method to try and resolve 2 potentially ambiguous + * VariableDefinitions. If the definitions are not actually ambiguous, then + * the Definition with the more specific type will be returned. For more + * detail see the comments for resolveAmbiguities above + */ + private static IDefinition resolveAmbiguousVariableDefinitions(ICompilerProject project, IDefinition v1, IDefinition v2) + { + assert (v1 instanceof VariableDefinition) && (v2 instanceof VariableDefinition); + + // Make sure they have the same name, and namespace, otherwise they can't possible be a re-decl + if (!namesAndContainingScopeMatch(project, v1, v2)) + return null; + + // const definitions always conflict. + if (v1 instanceof ConstantDefinition || v2 instanceof ConstantDefinition) + return null; + + IASScope containingScope = v1.getContainingScope(); + IScopedDefinition containingDef = v1.getContainingScope().getDefinition(); + if (containingDef instanceof FunctionDefinition || containingScope instanceof ASFileScope) + { + // Only global (outside a package) or function locals can be redeclared. + + VariableDefinition var1 = (VariableDefinition)v1; + VariableDefinition var2 = (VariableDefinition)v2; + + ITypeDefinition thisType = var1.resolveType(project); + ITypeDefinition thatType = var2.resolveType(project); + + // If the types match, doesn't matter which one we return + if (thisType == thatType) + { + return v1; + } + else + { + // If the types don't match, the re-decl is only allowed if one of them is '*' and the other + // one is a specific type. In this case, return the def with the more specific type, as that + // type will be the type of the var throughout the function + IDefinition anyType = project.getBuiltinType(IASLanguageConstants.BuiltinType.ANY_TYPE); + if (thisType == anyType) + return v2; + if (thatType == anyType) + return v1; + } + } + + return null; + } + + /** + * Helper method to try and resolve 2 potentially ambiguous + * FunctionDefinitions. If the definitions are not actually ambiguous, then + * the Definition with the more specific type will be returned. For more + * detail see the comments for resolveAmbiguities above + */ + private static IDefinition resolveAmbiguousFunctionDefinitions(ICompilerProject project, IDefinition f1, IDefinition f2) + { + assert (f1 instanceof FunctionDefinition) && (f2 instanceof FunctionDefinition); + + // Make sure they have the same name, and namespace, otherwise they can't possible be a re-decl + if (!namesAndContainingScopeMatch(project, f1, f2)) + return null; + + ASScope containingScope = (ASScope)f1.getContainingScope(); + if ((containingScope instanceof ASFileScope) || (containingScope.getContainingDefinition() instanceof FunctionDefinition)) + { + // All function declarations match, because functions + // declared outside of a package are really variables of + // type * that are initialized to function closures. + + int thisStartAbsoluteOffset = f1.getAbsoluteStart(); + int thatStartAbsoluteOffset = f2.getAbsoluteStart(); + // We'll pretend last definition wins, because that is more like JavaScript. + if (thisStartAbsoluteOffset >= thatStartAbsoluteOffset) + return f1; + else + return f2; + } + + return null; + } + + /** + * Helper method to try and resolve 2 potentially ambiguous Function and Variable definitions. If the definitions + * are not actually ambiguous, the Function definition will be returned, as it will always have the most specific type ('Function'). + * + * This method must be called with 1 variable definition, and 1 function definition - the order is not important. + * + * @param project The project to resolve things in + * @param f1 The first definition + * @param f2 The second definition + * @return The Function definition if the ambiguity can be resolve, otherwise null + */ + private static IDefinition resolveAmbiguousFunctionVariableDefinitions(ICompilerProject project, IDefinition f1, IDefinition f2) + { + VariableDefinition varDef = null; + FunctionDefinition funcDef = null; + if(f1 instanceof VariableDefinition ) + { + assert f2 instanceof FunctionDefinition; + varDef = (VariableDefinition)f1; + funcDef = (FunctionDefinition)f2; + } + else + { + assert f1 instanceof FunctionDefinition && f2 instanceof VariableDefinition; + varDef = (VariableDefinition)f2; + funcDef = (FunctionDefinition)f1; + } + + // Make sure they have the same name, and namespace, otherwise they can't possible be a re-decl + if (!namesAndContainingScopeMatch(project, varDef, funcDef)) + return null; + + // const definitions always conflict. + // getters/setters always conlflict with vars + if (varDef instanceof ConstantDefinition || funcDef instanceof AccessorDefinition) + return null; + + IASScope containingScope = varDef.getContainingScope(); + IScopedDefinition containingDef = varDef.getContainingScope().getDefinition(); + if (containingDef instanceof FunctionDefinition || containingScope instanceof ASFileScope) + { + // Only global (outside a package) or function locals can be redeclared. + + ITypeDefinition varType = varDef.resolveType(project); + IDefinition funcType = project.getBuiltinType(IASLanguageConstants.BuiltinType.FUNCTION); + + // If the types match, doesn't matter which one we return + if (varType == funcType) + { + return funcDef; + } + else + { + // If the types don't match, the re-decl is only allowed if the var type is '*' (the Function type is 'Function'). + // In this case, return the def with the more specific type, which will be the function + IDefinition anyType = project.getBuiltinType(IASLanguageConstants.BuiltinType.ANY_TYPE); + if (varType == anyType) + return funcDef; + } + } + + return null; + } + + @Override + public boolean isInProject(ICompilerProject project) + { + // The ambiguous definition singleton is logically in all projects. + return true; + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AppliedVectorDefinition.java ---------------------------------------------------------------------- diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AppliedVectorDefinition.java b/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AppliedVectorDefinition.java new file mode 100644 index 0000000..43749c7 --- /dev/null +++ b/compiler/src/main/java/org/apache/flex/compiler/internal/definitions/AppliedVectorDefinition.java @@ -0,0 +1,625 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.flex.compiler.internal.definitions; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import org.apache.flex.abc.ABCConstants; +import org.apache.flex.abc.semantics.Name; +import org.apache.flex.abc.semantics.Namespace; +import org.apache.flex.abc.semantics.Nsset; +import org.apache.flex.compiler.common.ASModifier; +import org.apache.flex.compiler.common.DependencyType; +import org.apache.flex.compiler.constants.IASLanguageConstants; +import org.apache.flex.compiler.definitions.IClassDefinition; +import org.apache.flex.compiler.definitions.IDefinition; +import org.apache.flex.compiler.definitions.IEffectDefinition; +import org.apache.flex.compiler.definitions.IEventDefinition; +import org.apache.flex.compiler.definitions.IFunctionDefinition; +import org.apache.flex.compiler.definitions.INamespaceDefinition; +import org.apache.flex.compiler.definitions.IStyleDefinition; +import org.apache.flex.compiler.definitions.ITypeDefinition; +import org.apache.flex.compiler.definitions.IAppliedVectorDefinition; +import org.apache.flex.compiler.definitions.metadata.IMetaTag; +import org.apache.flex.compiler.definitions.references.IReference; +import org.apache.flex.compiler.definitions.references.IResolvedQualifiersReference; +import org.apache.flex.compiler.definitions.references.ReferenceFactory; +import org.apache.flex.compiler.internal.projects.CompilerProject; +import org.apache.flex.compiler.internal.scopes.ASScope; +import org.apache.flex.compiler.internal.scopes.FunctionScope; +import org.apache.flex.compiler.internal.scopes.TypeScope; +import org.apache.flex.compiler.internal.tree.as.ExpressionNodeBase; +import org.apache.flex.compiler.internal.tree.as.IdentifierNode; +import org.apache.flex.compiler.internal.tree.as.TypedExpressionNode; +import org.apache.flex.compiler.problems.ICompilerProblem; +import org.apache.flex.compiler.projects.ICompilerProject; +import org.apache.flex.compiler.scopes.IASScope; +import org.apache.flex.compiler.tree.as.IExpressionNode; +import org.apache.flex.compiler.workspaces.IWorkspace; + +/** + * Definition representing a Vectorized type. It is built from a specific type, + * and gains the properties and functions of Array. + */ +public final class AppliedVectorDefinition extends ClassDefinitionBase implements IAppliedVectorDefinition +{ + /** + * A Name representing the base __AS3__.vec.Vector class. + */ + private static final Name VECTOR_NAME; + + static + { + Nsset nsSet = new Nsset(new Namespace(ABCConstants.CONSTANT_PackageNs, IASLanguageConstants.Vector_impl_package)); + VECTOR_NAME = new Name(ABCConstants.CONSTANT_Qname, nsSet, IASLanguageConstants.Vector); + } + + /* + * Builds a string of the form "Vector." or "Vector.", + * depending on the useFullyQualifiedNotation flag. + */ + private static String getName(ITypeDefinition elementType, boolean useFullyQualifiedNotation) + { + StringBuilder builder = new StringBuilder(); + builder.append(IASLanguageConstants.Vector); + builder.append(".<"); + if (useFullyQualifiedNotation) + builder.append(elementType.getQualifiedName()); + else + builder.append(elementType.getBaseName()); + builder.append(">"); + return builder.toString(); + } + + /** + * Helper method to copy a parameter - will use the name from the info + * argument if provided, otherwise the name will be whatever the original + * parameters name was - this lets us give more descriptive names to some of + * the Vector parameters than they have in the .abc file. + */ + private static ParameterDefinition copyParameter(ICompilerProject project, ParameterDefinition orig, VectorInformation.ArgumentInfo info) + { + ParameterDefinition newParam = new ParameterDefinition(info != null ? info.getName() : orig.getBaseName()); + newParam.setNamespaceReference(orig.getNamespaceReference()); + newParam.setTypeReference(orig.getTypeReference()); + if (orig.isRest()) + newParam.setRest(); + if (orig.hasDefaultValue()) + newParam.setDefaultValue(orig.resolveDefaultValue(project)); + return newParam; + } + + /** + * Constructor. + *

+ * Don't call this constructor from anywhere other than the ASProjectScope. + * + * @param project The compiler project + * @param baseClass The base class for the vector type, such as {@code Vector$int}. + * @param elementType The definition for the element type. + */ + public AppliedVectorDefinition(ICompilerProject project, IClassDefinition baseClass, + ITypeDefinition elementType) + { + // Set the 'storageName' field to a String like "Vector.". + super(AppliedVectorDefinition.getName(elementType, false)); + + this.project = project; + this.baseClass = baseClass; + this.elementType = elementType; + + setContainedScope(new TypeScope(null, this)); + setModifier(ASModifier.FINAL); + setImplicit(); + setNamespaceReference(NamespaceDefinition.getPublicNamespaceDefinition()); + } + + private ICompilerProject project; + + /* + * The base class will be Vector$int, Vector$uint, Vector$Number, or Vector$Object. + */ + private IClassDefinition baseClass; + + /* + * The element type can be any class or interface, including another vector type + * in a nested case like Vector.>. + */ + private ITypeDefinition elementType; + + @Override + protected String toStorageName(String name) + { + return name; + } + + @Override + public IReference getBaseClassReference() + { + return null; + } + + @Override + protected TypeDefinitionBase resolveType(String typeName, + ICompilerProject project, DependencyType dt) + { + return resolveType((DefinitionBase)baseClass, typeName, project, dt); + } + + @Override + public final String getQualifiedName() + { + return AppliedVectorDefinition.getName(elementType, true); + } + + @Override + public final String getBaseName() + { + return AppliedVectorDefinition.getName(elementType, false); + } + + @Override + public final String getPackageName() + { + // Base class version of this method relies + // on this definition having a namespace reference + // which we don't have. So we just overload this + // method to return the empty string which is the package + // name clients of CM want for instances of Vector.<>. + return ""; + } + + @Override + public boolean isImplicit() + { + return true; + } + + @Override + public IClassDefinition[] resolveAncestry(ICompilerProject project) + { + return new IClassDefinition[] {baseClass}; + } + + public String getBaseClassName() + { + return baseClass.getBaseName(); + } + + @Override + public ClassClassification getClassClassification() + { + return ClassClassification.PARAMETERIZED_CLASS_INSTANCE; + } + + @Override + public String[] getImplementedInterfacesAsDisplayStrings() + { + return new String[0]; + } + + @Override + public IReference[] getImplementedInterfaceReferences() + { + return new IReference[0]; + } + + public IExpressionNode[] getImplementedInterfaceNodes() + { + return new IExpressionNode[0]; + } + + @Override + public IMetaTag[] getMetaTagsByName(String name) + { + return new IMetaTag[0]; + } + + @Override + public ITypeDefinition resolveElementType(ICompilerProject project) + { + return elementType; + } + + /** + * Returns the expression that represents the value of this vector + * + * @return an expression that represents the value of this vector + */ + public ExpressionNodeBase toExpression() + { + if (elementType instanceof AppliedVectorDefinition) + { + return new TypedExpressionNode(new IdentifierNode(IASLanguageConstants.Vector), ((AppliedVectorDefinition)elementType).toExpression()); + } + return new IdentifierNode(elementType.getBaseName()); + } + + /** + * Returns a typed expression that represents the signature of this Vector + * + * @return a {@link TypedExpressionNode} + */ + public TypedExpressionNode toTypedExpression() + { + if (elementType instanceof AppliedVectorDefinition) + { + return new TypedExpressionNode(new IdentifierNode(IASLanguageConstants.Vector), ((AppliedVectorDefinition)elementType).toTypedExpression()); + } + return new TypedExpressionNode(new IdentifierNode(IASLanguageConstants.Vector), new IdentifierNode(elementType.getBaseName())); + } + + @Override + public String getBaseClassAsDisplayString() + { + return baseClass.getQualifiedName(); + } + + @Override + public IClassDefinition resolveBaseClass(ICompilerProject project) + { + return baseClass; + } + + public String getDefaultPropertyName() + { + return null; + } + + @Override + public INamespaceDefinition getProtectedNamespaceReference() + { + return null; + } + + @Override + public INamespaceDefinition getStaticProtectedNamespaceReference() + { + return null; + } + + @Override + public IEventDefinition getEventDefinition(IWorkspace w, String name) + { + return null; + } + + @Override + public IEventDefinition[] getEventDefinitions(IWorkspace w) + { + return new IEventDefinition[0]; + } + + @Override + public IEventDefinition[] findEventDefinitions(ICompilerProject project) + { + return new IEventDefinition[0]; + } + + @Override + public IStyleDefinition getStyleDefinition(IWorkspace w, String name) + { + return null; + } + + @Override + public IStyleDefinition[] getStyleDefinitions(IWorkspace w) + { + return new IStyleDefinition[0]; + } + + @Override + public IStyleDefinition[] findStyleDefinitions(ICompilerProject project) + { + return new IStyleDefinition[0]; + } + + @Override + public IEffectDefinition getEffectDefinition(IWorkspace w, String name) + { + return null; + } + + @Override + public IEffectDefinition[] getEffectDefinitions(IWorkspace w) + { + return new IEffectDefinition[0]; + } + + @Override + public IEffectDefinition[] findEffectDefinitions(ICompilerProject project) + { + return new IEffectDefinition[0]; + } + + @Override + public String[] getSkinStates(Collection problems) + { + return new String[0]; + } + + @Override + public String[] findSkinStates(ICompilerProject project, Collection problems) + { + return getSkinStates(problems); + } + + @Override + public IMetaTag[] getSkinParts(Collection problems) + { + return new IMetaTag[0]; + } + + @Override + public IMetaTag[] findSkinParts(ICompilerProject project, Collection problems) + { + return getSkinParts(problems); + } + + @Override + public Set getStateNames() + { + return Collections.emptySet(); + } + + @Override + public Set findStateNames(ICompilerProject project) + { + return getStateNames(); + } + + @Override + public Name getMName(ICompilerProject project) + { + // The Name for a type such as Vector. has kind CONSTANT_TypeName. + // It gets constructed by passing two Names, the first representing + //the __AS3__.vec.Vector base type and the second representing the T type. + Name typeName = ((DefinitionBase)elementType).getMName(project); + return new Name(VECTOR_NAME, typeName); + } + + /** + * Copy down definitions from Vector$object into the instantiated class as + * we go, modify to the parameter and return types to match what is actually + * expected (Vector$object becomes Vector., etc). + * + * @param project Project we are in + */ + public void adjustVectorMethods(ICompilerProject project) + { + VectorInformation vecInfo = VectorInformation.getInformation(); + ASScope scope = getContainedScope(); + + // Copy the methods from the base class, so they report themselves as belonging + // to the instantiated Vector class instead of Vector$object, etc. + IASScope baseClassScope = baseClass.getContainedScope(); + for (IDefinition defaultDef : baseClassScope.getAllLocalDefinitions()) + { + String name = defaultDef.getBaseName(); + VectorInformation.FunctionInfo info = vecInfo.getFunctionInfo(name); + if (defaultDef instanceof FunctionDefinition) + { + FunctionDefinition defaultFunc = (FunctionDefinition)defaultDef; + // Override the base class definition with one that has the correct signature + + FunctionDefinition newDef; + if (defaultDef instanceof GetterDefinition) + { + newDef = new GetterDefinition(name); + newDef.setReturnTypeReference(defaultFunc.getReturnTypeReference()); + newDef.setTypeReference(defaultFunc.getTypeReference()); + } + else if (defaultDef instanceof SetterDefinition) + { + newDef = new SetterDefinition(name); + newDef.setReturnTypeReference(defaultFunc.getReturnTypeReference()); + newDef.setTypeReference(defaultFunc.getTypeReference()); + } + else + { + newDef = new FunctionDefinition(name); + newDef.setReturnTypeReference(defaultFunc.getReturnTypeReference()); + } + + ASScope newScope = new FunctionScope(scope); + newDef.setContainedScope(newScope); + + newDef.setNamespaceReference(defaultDef.getNamespaceReference()); + + if (info != null) + { + if (info.returnIsTypeOfCollection()) + newDef.setReturnTypeReference(ReferenceFactory.resolvedReference(elementType)); + else if (info.returnIsVector()) + newDef.setReturnTypeReference(ReferenceFactory.resolvedReference(this)); + } + ParameterDefinition[] params = defaultFunc.getParameters(); + + if (params != null) + { + VectorInformation.ArgumentInfo[] args = info != null ? info.getArgumentInfo() : null; + ParameterDefinition[] newParams = new ParameterDefinition[params.length]; + for (int i = 0, l = params.length; i < l; ++i) + { + if (args != null && i < args.length) + { + newParams[i] = copyParameter(project, params[i], args[i]); + if (args[i].returnIsVector()) + newParams[i].setTypeReference(ReferenceFactory.resolvedReference(this)); + else if (args[i].returnIsTypeOfCollection()) + newParams[i].setTypeReference(ReferenceFactory.resolvedReference(elementType)); + } + else + { + newParams[i] = copyParameter(project, params[i], null); + } + newScope.addDefinition(newParams[i]); + + } + newDef.setParameters(newParams); + } + scope.addDefinition(newDef); + } + } + } + + /** + * Gets the {@link ICompilerProject} that this + * {@link AppliedVectorDefinition} was created for. + * + * @return The {@link ICompilerProject} that this + * {@link AppliedVectorDefinition} was created for + */ + public ICompilerProject getProject() + { + return project; + } + + @Override + public String getDefaultPropertyName(ICompilerProject project) + { + // TODO Eliminate this method stub. AppliedVectorDefinition should not be implementing IAppliedVectorDefinition. + return null; + } + + private static AppliedVectorDefinition toVectorNodeOrContainingVectorNode(IDefinition def) + { + assert def != null; + if (def instanceof AppliedVectorDefinition) + return (AppliedVectorDefinition)def; + + ASScope containingScope = (ASScope)def.getContainingScope(); + if (containingScope == null) + return null; + IDefinition containingDefinition = containingScope.getDefinition(); + if (containingDefinition instanceof AppliedVectorDefinition) + return (AppliedVectorDefinition)containingDefinition; + IDefinition containingClassDefiniton = containingScope.getContainingClass(); + if (containingClassDefiniton instanceof AppliedVectorDefinition) + return (AppliedVectorDefinition)containingClassDefiniton; + return null; + } + + /** + * Determines if the specified definition is a vector instantiation or a + * contained by a vector instantiation. + * + * @param def {@link IDefinition} to check. + * @return true if the specified definition is a vector instantiation or is + * contained by a vector instantiation. + */ + public static ICompilerProject getProjectIfVectorInsantiation(IDefinition def) + { + AppliedVectorDefinition vectorNode = toVectorNodeOrContainingVectorNode(def); + if (vectorNode != null) + return vectorNode.getProject(); + return null; + } + + public static boolean isVectorScope(ASScope scope) + { + // Check if this scope is a Vector scope, or if it is contained in a Vector scope + // this is possible because we now copy the methods down to the insantiated vector + // instead of finding them in the Vector$object baseclass. + return scope.getDefinition() instanceof AppliedVectorDefinition + || scope.getContainingClass() instanceof AppliedVectorDefinition; + } + + @Override + public IFunctionDefinition getConstructor() + { + assert false : "This should never get called."; + return null; + } + + + @Override + public IClassDefinition resolveHostComponent(ICompilerProject project) + { + return null; + } + + /** + * Helper method that implements special instanceOf checks for Vector types. + *

+ * This method aliases the Vector$XXXX where XXXX is double, uint, or int to + * Vector.. + * + * @param base {@link ITypeDefinition} for the base type in the instanceOf + * check. + * @param derived {@link ITypeDefinition} for the dervied type in the + * instanceOf check. + * @return true if the derived type should be considered and instance of the + * base type. + */ + public static boolean vectorInstanceOfCheck(ITypeDefinition base, ITypeDefinition derived) + { + if (!(base instanceof AppliedVectorDefinition)) + return false; + + final AppliedVectorDefinition vectorInstance = (AppliedVectorDefinition)base; + if (vectorInstance.baseClass != derived) + return false; + assert ((INamespaceDefinition)vectorInstance.baseClass.getNamespaceReference()).getURI().equals(IASLanguageConstants.Vector_impl_package); + return !(IASLanguageConstants.Vector_object.equals(derived.getBaseName())); + } + + @Override + public boolean isInProject(ICompilerProject project) + { + return project == this.project; + } + + /** + * Returns the class definition for Vector$object, Vector$int, Vector$uint, or Vector$double. + */ + public static IClassDefinition lookupVectorImplClass(ICompilerProject project, String baseName) + { + // Only the base name (e.g., "Vector$object") is passed in. + // But the developer may have also defined something with the same + // base name, so we need to make sure that the definition we find + // also has the correct package, namely "__AS3__.vec". + + INamespaceDefinition vectorImplPackage = ((CompilerProject)project).getWorkspace().getPackageNamespaceDefinitionCache().get(IASLanguageConstants.Vector_impl_package, true); + + IResolvedQualifiersReference vectorReference = ReferenceFactory.resolvedQualifierQualifiedReference(project.getWorkspace(), vectorImplPackage, baseName); + IDefinition vectorIDefinition = vectorReference.resolve(project); + assert vectorIDefinition instanceof IClassDefinition : + "Unable to find: " + vectorReference.getDisplayString(); + return (IClassDefinition) vectorIDefinition; + } + + /** + * Updates the base class of this {@link AppliedVectorDefinition} if the + * vector base name of the base class matches the base name of the vector + * implementation class that has changed. + * + * @param changedVectorImplClass base name of the vector implementation + * class that has changed. + */ + public void updateBaseClass(String changedVectorImplClass) + { + final String baseClassBaseName = baseClass.getBaseName(); + if (baseClassBaseName.equals(changedVectorImplClass)) + baseClass = lookupVectorImplClass(project, baseClassBaseName); + } +}