/*
*
* 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.tree.as;
import org.apache.flex.compiler.constants.IASLanguageConstants;
import org.apache.flex.compiler.definitions.references.IReference;
import org.apache.flex.compiler.definitions.references.ReferenceFactory;
import org.apache.flex.compiler.internal.definitions.DefinitionBase;
import org.apache.flex.compiler.internal.definitions.GetterDefinition;
import org.apache.flex.compiler.internal.definitions.ParameterDefinition;
import org.apache.flex.compiler.internal.definitions.SetterDefinition;
import org.apache.flex.compiler.internal.definitions.SyntheticBindableGetterDefinition;
import org.apache.flex.compiler.internal.definitions.SyntheticBindableSetterDefinition;
import org.apache.flex.compiler.internal.scopes.ASScope;
import org.apache.flex.compiler.internal.scopes.FunctionScope;
import org.apache.flex.compiler.parsing.IASToken;
import org.apache.flex.compiler.tree.as.IIdentifierNode;
import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
import org.apache.flex.compiler.tree.as.ITypedNode;
import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode.LanguageIdentifierKind;
/**
* Base class for definitions that have a type associated with them
*/
public abstract class BaseTypedDefinitionNode extends BaseDefinitionNode implements ITypedNode
{
/**
* Constructor.
*/
public BaseTypedDefinitionNode()
{
super();
}
/**
* Offset at which the type operator (":") starts
*/
protected int typeOperatorStart;
/**
* The type of the variable
*/
protected ExpressionNodeBase typeNode;
//
// BaseDefinitionNode overrides
//
@Override
protected void init(ExpressionNodeBase nameNode)
{
super.init(nameNode);
typeOperatorStart = -1;
typeNode = null;
}
//
// ITypedNode implementations
//
@Override
public ExpressionNodeBase getTypeNode()
{
return typeNode;
}
@Override
public boolean hasTypeOperator()
{
return typeOperatorStart != -1;
}
@Override
public int getTypeOperatorStart()
{
return typeOperatorStart;
}
@Override
public int getTypeOperatorEnd()
{
return typeOperatorStart + 1;
}
//
// Other methods
//
/**
* Determines if this typed definition has an explicit type specification
*
* @return true if we have an actual type
*/
public boolean hasExplicitType()
{
if (typeNode instanceof IdentifierNode)
return !((IdentifierNode)typeNode).isImplicit();
return typeNode != null;
}
/**
* Returns the type of this node in String form
*
* @return the types name, or an empty string
*/
public String getTypeName()
{
return hasExplicitType() ? ((IIdentifierNode)typeNode).getName() : "";
}
public boolean isVoidType()
{
return typeNode instanceof ILanguageIdentifierNode && ((ILanguageIdentifierNode)typeNode).getKind() == LanguageIdentifierKind.VOID;
}
public boolean isAnyType()
{
return typeNode instanceof ILanguageIdentifierNode && ((ILanguageIdentifierNode)typeNode).getKind() == LanguageIdentifierKind.ANY_TYPE;
}
/**
* Set the type node. Used during parsing.
*
* @param typeOperator ASToken containing the type operator (":")
* @param variableType node containing the variable type
*/
public void setType(IASToken typeOperator, ExpressionNodeBase variableType)
{
if (typeOperator != null)
typeOperatorStart = typeOperator.getStart();
typeNode = variableType;
}
/**
* Helper method to fill in a definition with appropriate metadata &
* namespace stuff. Used by both buildDefinition and
* buildBindableDefinitions
*
* @param definition the definition to "fill in"
*/
protected void fillinDefinition(DefinitionBase definition)
{
definition.setNode(this);
fillInNamespaceAndModifiers(definition);
fillInMetadata(definition);
// Set the variable's type. If a type annotation doesn't appear in the source,
// the variable type in the definition will be null.
IReference typeRef = hasExplicitType() ? typeNode.computeTypeReference() : null;
definition.setTypeReference(typeRef);
}
public DefinitionBase buildBindableGetter(String definitionName)
{
GetterDefinition getter = new SyntheticBindableGetterDefinition(definitionName);
fillinDefinition(getter);
// set up the return type for the getter
IReference typeRef = getter.getTypeReference();
getter.setReturnTypeReference(typeRef);
return getter;
}
public DefinitionBase buildBindableSetter(String definitionName, ASScope containingScope, IReference typeRef)
{
SetterDefinition setter = new SyntheticBindableSetterDefinition(definitionName);
fillinDefinition(setter);
// Set up the params for the setter
ParameterDefinition param = new ParameterDefinition("");
param.setTypeReference(typeRef);
setter.setParameters(new ParameterDefinition[] {param});
setter.setTypeReference(typeRef);
ASScope setterContainedScope = new FunctionScope(containingScope);
setter.setContainedScope(setterContainedScope);
setterContainedScope.addDefinition(param);
setter.setReturnTypeReference(ReferenceFactory.builtinReference(IASLanguageConstants.BuiltinType.VOID));
return setter;
}
/**
* Build the definitions for a bindable variable that needs a generated
* getter/setter.
*
* @return An Array with all of the definitions built for this Node.
*/
DefinitionBase[] buildBindableDefinitions(ASScope containingScope)
{
String definitionName = nameNode.computeSimpleReference();
DefinitionBase[] definitions = new DefinitionBase[2];
definitions[0] = buildBindableGetter(definitionName);
definitions[1] = buildBindableSetter(definitionName, containingScope, definitions[0].getTypeReference());
return definitions;
}
}