/* * * 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.references; import static org.apache.flex.abc.ABCConstants.CONSTANT_Multiname; import static org.apache.flex.abc.ABCConstants.CONSTANT_Qname; import java.util.ArrayList; import java.util.List; 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.DependencyType; import org.apache.flex.compiler.definitions.IDefinition; import org.apache.flex.compiler.definitions.INamespaceDefinition; import org.apache.flex.compiler.definitions.references.IReference; import org.apache.flex.compiler.definitions.references.IResolvedQualifiersReference; import org.apache.flex.compiler.internal.definitions.AmbiguousDefinition; import org.apache.flex.compiler.internal.definitions.NamespaceDefinition; import org.apache.flex.compiler.internal.projects.CompilerProject; import org.apache.flex.compiler.internal.scopes.ASScope; import org.apache.flex.compiler.projects.ICompilerProject; import org.apache.flex.compiler.units.ICompilationUnit; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; /** * Implementation of {@link IReference} representing a reference where all the * qualifiers have been resolved to namespace definitions. */ public class ResolvedQualifiersReference implements IResolvedQualifiersReference { /** * Constructor. */ public ResolvedQualifiersReference(ImmutableSet<INamespaceDefinition> qualifiers, String baseName) { assert baseName != null; this.qualifiers = qualifiers; this.baseName = baseName; } private final ImmutableSet<INamespaceDefinition> qualifiers; private final String baseName; @Override public String getName() { return baseName; } @Override public IDefinition resolve(ICompilerProject project, ASScope scope, DependencyType dependencyType, boolean canEscapeWith) { if (qualifiers.size() == 1) { INamespaceDefinition qualifier = Iterables.getOnlyElement(qualifiers); return scope.findPropertyQualified(project, qualifier, getName(), dependencyType, canEscapeWith); } return ((CompilerProject)project).getCacheForScope(scope).findPropertyMultiname(this, dependencyType); } @Override public String getDisplayString() { // Look through the multiname set for a package name. // Although most names in SWCs seem to have only // one namespace in their namespace set, interfaces seem // to have true multinames with multiple namespaces. // For code mode purposes, just look for the package namespace. String packageName = null; for (INamespaceDefinition namespace : qualifiers) { if (namespace.isPublicOrInternalNamespace()) { packageName = namespace.getURI(); if (packageName.length() > 0) break; } } return packageName != null && packageName.length() > 0 ? packageName + '.' + baseName : baseName; } @Override public Name getMName(ICompilerProject project, ASScope scope) { return getMName(); } private IDefinition resolveAmbiguities(ICompilerProject project, List<IDefinition> defs) { switch (defs.size()) { case 0: { return null; } case 1: { assert Iterables.getOnlyElement(defs).isInProject(project); return Iterables.getOnlyElement(defs); } default: { IDefinition d = AmbiguousDefinition.resolveAmbiguities(project, defs); if (d == null) return AmbiguousDefinition.get(); return d; } } } @Override public IDefinition resolve(ICompilerProject project, ICompilationUnit referencingCompilationUnit, DependencyType dt) { CompilerProject compilerProject = (CompilerProject)project; ArrayList<IDefinition> defs = new ArrayList<IDefinition>(2); compilerProject.getScope().findDefinitionByName(referencingCompilationUnit, defs, baseName, qualifiers, dt); return resolveAmbiguities(project, defs); } @Override public IDefinition resolve(ICompilerProject project) { CompilerProject compilerProject = (CompilerProject)project; ArrayList<IDefinition> defs = new ArrayList<IDefinition>(2); compilerProject.getScope().findDefinitionByName(defs, baseName, qualifiers); return resolveAmbiguities(project, defs); } @Override public Name getMName() { ArrayList<Namespace> ns_set = new ArrayList<Namespace>(qualifiers.size()); for (INamespaceDefinition namespace : qualifiers) ns_set.add(((NamespaceDefinition)namespace).getAETNamespace()); int nameType = ns_set.size() == 1 ? CONSTANT_Qname : CONSTANT_Multiname; return new Name(nameType, new Nsset(ns_set), baseName); } @Override public ImmutableSet<INamespaceDefinition> getQualifiers() { return qualifiers; } @Override public boolean matches(IResolvedQualifiersReference toMatch) { if (!baseName.equals(toMatch.getName())) return false; for (INamespaceDefinition qualifierToMatch : toMatch.getQualifiers()) { if (qualifiers.contains(qualifierToMatch)) return true; } return false; } }