blob: 1521911409369db6a5e09bec7a470a5a9bb85631 [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.flex.compiler.internal.legacy;
import java.lang.ref.WeakReference;
import java.util.Set;
import org.apache.flex.compiler.common.ASModifier;
import org.apache.flex.compiler.definitions.INamespaceDefinition;
import org.apache.flex.compiler.internal.scopes.ASScope;
import org.apache.flex.compiler.internal.tree.as.FunctionNode;
import org.apache.flex.compiler.internal.tree.as.LanguageIdentifierNode;
import org.apache.flex.compiler.projects.ICompilerProject;
import org.apache.flex.compiler.scopes.IASScope;
import org.apache.flex.compiler.tree.as.IASNode;
import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
import org.apache.flex.compiler.tree.as.IScopedDefinitionNode;
import org.apache.flex.compiler.tree.as.IScopedNode;
/**
* An IFilterContext implementation based on an IASNode. Provided for backwards
* compatibility of ASDefinitionFilter methods which expect to operate on
* IASNodes
*/
public class NodeFilterContext extends ScopeFilterContext implements IFilterContext
{
private WeakReference<IASNode> nodeContext;
/**
* Find the scope that will determine the namespaces in effect for a node
* example: for a ClassNode, we will get the block scope that is a direct
* child of the class node. Other types of nodes may need to walk up the
* tree...
*
* @param node is the node whose scope we care about. may be null
* @return the scope for the node. may be null. Note: I *think* the return
* is only null if a null node is passed in.
*/
private static ASScope getScopeOfNamespaceSetForNode(IASNode node)
{
ASScope ret = null;
IScopedNode scopedNode = null;
// search up the node tree until we find someone who can give us a scope,
// either IScopedNode or IScopedDefinition
// When loop is done, scopedNode should be set to the node we found
while ((scopedNode == null) && (node != null))
{
if (node instanceof IScopedNode)
{
scopedNode = (IScopedNode)node;
}
else if (node instanceof IScopedDefinitionNode)
{
IScopedDefinitionNode scopedDefinitionNode = (IScopedDefinitionNode)node;
scopedNode = scopedDefinitionNode.getScopedNode();
}
if (scopedNode == null)
{
node = node.getParent();
}
}
// if we found a scoped node, get the scope out of it
if (scopedNode != null)
{
IASScope scope = scopedNode.getScope();
assert (scope instanceof ASScope);
if (scope instanceof ASScope)
{
ret = (ASScope)scope;
}
}
return ret;
}
public NodeFilterContext(IASNode context)
{
super(getScopeOfNamespaceSetForNode(context));
this.nodeContext = new WeakReference<IASNode>(context);
}
/**
* Determine whether this lookup is from a static context (e.g. somewhere
* within a static method)
*
* @return true if the lookup is being performed in a static context
*/
@Override
public boolean isInStaticContext()
{
IASNode node = nodeContext.get();
if (node != null)
{
return isInStaticContext(node);
}
return false;
}
/**
* Determine whether this node is in a static context (e.g. somewhere within
* a static method)
*
* @return true if the node is in a static context
*/
public static boolean isInStaticContext(IASNode node)
{
IASNode current = node.getParent();
while (current != null && !(current instanceof FunctionNode))
current = current.getParent();
if (current instanceof FunctionNode && ((FunctionNode)current).hasModifier(ASModifier.STATIC))
return true;
return false;
}
@Override
public Set<INamespaceDefinition> getNamespaceSet(ICompilerProject project)
{
Set<INamespaceDefinition> nsset = super.getNamespaceSet(project);
IASNode n = nodeContext.get();
if (isSuper(n))
{
// If our node is 'super' then we need to adjust the namespace set to account for the super
// classes protected namespace
nsset = getScope().adjustNamespaceSetForSuper(((LanguageIdentifierNode)n).resolveType(project), nsset);
}
return nsset;
}
@Override
public Set<INamespaceDefinition> getNamespaceSet(ICompilerProject project, String name)
{
Set<INamespaceDefinition> nsset = super.getNamespaceSet(project, name);
IASNode n = nodeContext.get();
if (isSuper(n))
{
// If our node is 'super' then we need to adjust the namespace set to account for the super
// classes protected namespace
nsset = getScope().adjustNamespaceSetForSuper(((LanguageIdentifierNode)n).resolveType(project), nsset);
}
return nsset;
}
/**
* @return true if the node passed in is 'super'
*/
private boolean isSuper(IASNode n)
{
boolean isSuper = false;
if (n != null)
{
if (n instanceof LanguageIdentifierNode && ((LanguageIdentifierNode)n).getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.SUPER)
isSuper = true;
}
return isSuper;
}
}