blob: 1561d13e7363f139e05dc552360b5f334dd10dcd [file] [log] [blame]
/*
*
* 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.royale.compiler.internal.definitions.references;
import static org.apache.royale.abc.ABCConstants.CONSTANT_Multiname;
import static org.apache.royale.abc.ABCConstants.CONSTANT_Qname;
import java.util.ArrayList;
import java.util.List;
import org.apache.royale.abc.semantics.Name;
import org.apache.royale.abc.semantics.Namespace;
import org.apache.royale.abc.semantics.Nsset;
import org.apache.royale.compiler.common.DependencyType;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.INamespaceDefinition;
import org.apache.royale.compiler.definitions.references.IReferenceMName;
import org.apache.royale.compiler.definitions.references.IResolvedQualifiersReference;
import org.apache.royale.compiler.internal.definitions.AmbiguousDefinition;
import org.apache.royale.compiler.internal.definitions.NamespaceDefinition;
import org.apache.royale.compiler.internal.projects.CompilerProject;
import org.apache.royale.compiler.internal.scopes.ASScope;
import org.apache.royale.compiler.scopes.IASScope;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.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, IReferenceMName
{
/**
* 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, IASScope scope,
DependencyType dependencyType,
boolean canEscapeWith)
{
if (qualifiers.size() == 1)
{
INamespaceDefinition qualifier = Iterables.getOnlyElement(qualifiers);
return ((ASScope)scope).findPropertyQualified(project, qualifier, getName(), dependencyType, canEscapeWith);
}
return ((CompilerProject)project).getCacheForScope((ASScope)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, IASScope 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;
}
}