/*
*
* 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.definitions.references;
import java.util.Set;
import org.apache.flex.compiler.constants.IASLanguageConstants;
import org.apache.flex.compiler.definitions.IDefinition;
import org.apache.flex.compiler.definitions.INamespaceDefinition;
import org.apache.flex.compiler.internal.definitions.references.BuiltinReference;
import org.apache.flex.compiler.internal.definitions.references.LexicalReference;
import org.apache.flex.compiler.internal.definitions.references.NotATypeReference;
import org.apache.flex.compiler.internal.definitions.references.ParameterizedReference;
import org.apache.flex.compiler.internal.definitions.references.ResolvedQualifiersReference;
import org.apache.flex.compiler.internal.definitions.references.ResolvedReference;
import org.apache.flex.compiler.internal.workspaces.Workspace;
import org.apache.flex.compiler.workspaces.IWorkspace;
import com.google.common.collect.ImmutableSet;
/**
* A factory class to create instances of type {@link IReference}.
*/
public class ReferenceFactory
{
// Constant IReferences returned by builtinReference().
private static final IReference REFERENCE_ANY_TYPE = new BuiltinReference(IASLanguageConstants.BuiltinType.ANY_TYPE);
private static final IReference REFERENCE_Array = new BuiltinReference(IASLanguageConstants.BuiltinType.ARRAY);
private static final IReference REFERENCE_Boolean = new BuiltinReference(IASLanguageConstants.BuiltinType.BOOLEAN);
private static final IReference REFERENCE_Class = new BuiltinReference(IASLanguageConstants.BuiltinType.CLASS);
private static final IReference REFERENCE_Function = new BuiltinReference(IASLanguageConstants.BuiltinType.FUNCTION);
private static final IReference REFERENCE_int = new BuiltinReference(IASLanguageConstants.BuiltinType.INT);
private static final IReference REFERENCE_null = new BuiltinReference(IASLanguageConstants.BuiltinType.NULL);
private static final IReference REFERENCE_Number = new BuiltinReference(IASLanguageConstants.BuiltinType.NUMBER);
private static final IReference REFERENCE_Object = new BuiltinReference(IASLanguageConstants.BuiltinType.OBJECT);
private static final IReference REFERENCE_QName = new BuiltinReference(IASLanguageConstants.BuiltinType.QNAME);
private static final IReference REFERENCE_RegExp = new BuiltinReference(IASLanguageConstants.BuiltinType.REGEXP);
private static final IReference REFERENCE_String = new BuiltinReference(IASLanguageConstants.BuiltinType.STRING);
private static final IReference REFERENCE_undefined = new BuiltinReference(IASLanguageConstants.BuiltinType.Undefined);
private static final IReference REFERENCE_uint = new BuiltinReference(IASLanguageConstants.BuiltinType.UINT);
private static final IReference REFERENCE_Vector = new BuiltinReference(IASLanguageConstants.BuiltinType.VECTOR);
private static final IReference REFERENCE_void = new BuiltinReference(IASLanguageConstants.BuiltinType.VOID);
private static final IReference REFERENCE_XML = new BuiltinReference(IASLanguageConstants.BuiltinType.XML);
private static final IReference REFERENCE_XMLList = new BuiltinReference(IASLanguageConstants.BuiltinType.XMLLIST);
/**
* Gets an {@link IReference} for one of the builtin types such as
* <code>Object</code>, <code>String</code>, or <code>Array</code>.
*
* @param type The {@code IASLanguageConstants.BuiltinType} you want the
* reference for.
* @return A {@link BuiltinReference}.
*/
public static IReference builtinReference(IASLanguageConstants.BuiltinType type)
{
switch (type)
{
case ANY_TYPE:
return REFERENCE_ANY_TYPE;
case ARRAY:
return REFERENCE_Array;
case BOOLEAN:
return REFERENCE_Boolean;
case CLASS:
return REFERENCE_Class;
case FUNCTION:
return REFERENCE_Function;
case INT:
return REFERENCE_int;
case NULL:
return REFERENCE_null;
case NUMBER:
return REFERENCE_Number;
case OBJECT:
return REFERENCE_Object;
case QNAME:
return REFERENCE_QName;
case REGEXP:
return REFERENCE_RegExp;
case STRING:
return REFERENCE_String;
case Undefined:
return REFERENCE_undefined;
case UINT:
return REFERENCE_uint;
case VECTOR:
return REFERENCE_Vector;
case VOID:
return REFERENCE_void;
case XML:
return REFERENCE_XML;
case XMLLIST:
return REFERENCE_XMLList;
default:
assert false : "Unknown builtin type " + type;
return new BuiltinReference(type);
}
}
/**
* Generates an {@link IReference} for an unqualified base name.
*
* @param workspace The workspace.
* @param baseName The base name you want a reference to.
* @return A {@link LexicalReference}.
*/
public static IReference lexicalReference(IWorkspace workspace, String baseName)
{
if (workspace instanceof Workspace)
return ((Workspace)workspace).getReferenceCache().getLexicalReference(baseName);
return new LexicalReference(baseName);
}
/**
* Generates an {@link IReference} for a base name qualified by an
* {@link INamespaceDefinition}.
*
* @param workspace The workspace.
* @param namespace The {@link INamespaceDefinition} to use as the qualifier.
* @param baseName The base name you want to reference to.
* @return A {@link ResolvedQualifiersReference}.
*/
public static IResolvedQualifiersReference resolvedQualifierQualifiedReference(
IWorkspace workspace, INamespaceDefinition namespace, String baseName)
{
ImmutableSet<INamespaceDefinition> qualifiers =
new ImmutableSet.Builder<INamespaceDefinition>().add(namespace).build();
return new ResolvedQualifiersReference(qualifiers, baseName);
}
/**
* Generates an {@link IReference} for a base name qualified by a package
* name.
*
* @param workspace The workspace.
* @param packageName The package name to use as the qualifier.
* @param baseName The base name you want a reference to.
* @param includeInternal Indicates whether or not the reference should
* resolve to package internal definitions.
* @return A {@link ResolvedQualifiersReference}.
*/
public static IResolvedQualifiersReference packageQualifiedReference(
IWorkspace workspace, String packageName, String baseName, boolean includeInternal)
{
INamespaceDefinition packagePublicNS =
((Workspace)workspace).getPackageNamespaceDefinitionCache().get(packageName, false);
ImmutableSet.Builder<INamespaceDefinition> namespaceSetBuilder =
new ImmutableSet.Builder<INamespaceDefinition>().add(packagePublicNS);
if (includeInternal)
{
INamespaceDefinition packageInternalNS =
((Workspace)workspace).getPackageNamespaceDefinitionCache().get(packageName, true);
namespaceSetBuilder.add(packageInternalNS);
}
ImmutableSet<INamespaceDefinition> namespaceSet = namespaceSetBuilder.build();
return new ResolvedQualifiersReference(namespaceSet, baseName);
}
/**
* Generates an {@link IReference} for a fully qualified name.
* <p>
* It is expected that the string will be of the form
* <code>my.package.name.Foo</code>. This will be used to generate a
* reference to <code>Foo</code> in the package <code>my.package.name</code>.
*
* @param workspace The workspace.
* @param qname A <code>String</code> representing a fully qualified name.
* @return A {@link ResolvedQualifiersReference}.
*/
public static IResolvedQualifiersReference packageQualifiedReference(IWorkspace workspace, String qname)
{
return packageQualifiedReference(workspace, qname, false);
}
/**
* Generates an {@link IReference} for a fully qualified name.
* <p>
* It is expected that the string will be of the form
* <code>my.package.name.Foo</code>. This will be used to generate a
* reference to <code>Foo</code> in the package <code>my.package.name</code>.
*
* @param workspace The workspace.
* @param qname A <code>String</code> representing a fully qualified name.
* @param includeInternal Indicates whether or not the reference should
* resolve to package internal definitions.
* @return A {@link ResolvedQualifiersReference}.
*/
public static IResolvedQualifiersReference packageQualifiedReference(
IWorkspace workspace, String qname, boolean includeInternal)
{
int lastIndexOfDot = qname.lastIndexOf('.');
if (lastIndexOfDot != -1)
{
String unqualifiedName = qname.substring(lastIndexOfDot + 1);
String packageName = qname.substring(0, lastIndexOfDot);
return ReferenceFactory.packageQualifiedReference(workspace, packageName, unqualifiedName, includeInternal);
}
else
{
return ReferenceFactory.packageQualifiedReference(workspace, "", qname, includeInternal);
}
}
/**
* Generates an {@link IReference} for a multiname coming from an ABC.
*
* @param workspace The workspace.
* @param namespaces The set of {@link INamespaceDefinition}s to use as the
* namespace set.
* @param baseName The base name you want a reference to.
* @return A {@link ResolvedQualifiersReference}.n
*/
public static IResolvedQualifiersReference multinameReference(IWorkspace workspace, Set<INamespaceDefinition> namespaces, String baseName)
{
return new ResolvedQualifiersReference(ImmutableSet.copyOf(namespaces), baseName);
}
/**
* Generates an {@link IReference} for a parameterized type, such as
* {@code Vector.<Foo>}.
* <p>
* This currently only supports one type parameter, as Vector is the only
* parameterized type, and it only takes 1 type parameter.
*
* @param workspace The workspace.
* @param base The base reference, such as <code>Vector</code> in
* {@code Vector.<Foo>}.
* @param param The type parameter reference, such as <code>Foo</code> in
* {@code Vector.<Foo>}.
* @return A {@link ParameterizedReference}.
*/
public static IReference parameterizedReference(IWorkspace workspace, IReference base, IReference param)
{
return new ParameterizedReference(base, param);
}
/**
* Generates an {@link IReference} that always resolves to the
* {@link IDefinition} passed in.
* <p>
* This is useful for <code>Vector</code> methods, where the return type is
* the type parameter for the <code>Vector</code> (i.e., <code>T</code> in
* {@code Vector.<T>}).
*
* @param definition The {@link IDefinition} to generate a reference to.
* @return A {@link ResolvedReference} that resolves to <code>d</code>.
*/
public static IReference resolvedReference(IDefinition definition)
{
return new ResolvedReference(definition);
}
/**
* Generates an {@link IReference} for a type reference that will always be
* an error. An example would be: class C extends a.b.c.d.Foo{} If a.b.c.d
* was not a package name then this class would be used to represent the
* reference. This is because a property access will be an error, but we
* have to remember that something was specified for the base class so we
* can report the correct error when we try and resolve it.
*
* @param workspace The workspace.
* @param baseName The base name you want a reference to.
* @return A {@link NotATypeReference}.
*/
public static IReference notATypeReference(IWorkspace workspace, String baseName)
{
return new NotATypeReference(baseName);
}
// This is an all-static class and no instances of it can be created.
private ReferenceFactory()
{
}
}