blob: a4cc77896197bb0b02c64a9a40ea18e67443235f [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2006 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute for Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
* $Id: TypeValueParameter.java 23401 2010-02-02 23:56:05Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
* Fraunhofer FIRST - Initial API and implementation
* Technical University Berlin - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otdt.internal.core.compiler.ast;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.AnchorUsageRanksAttribute;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.FieldModel;
/**
* This class models type parameters of the for MyClass<SomeType someName>.
* Such parameters represent values instead of types.
*
* The effect of this syntax is as follows:
* + The type 'MyClass' has a field 'public final SomeType someName'
* + Each constructor of 'MyClass' has an implicit (invisible) additional argument
* of type 'SomeType'. The final field is automatically initialized from this argument.
*
* Life-cycle of a type with value parameters:
* <ul>
* <li>Parser creates the TypeValueParameter
* <li>ClassScope.buildFields() calls TypeValueParameter.resolveValueParamters(..)
* in order to create FieldBindings for these parameters
* <li>ClassScope.buildFieldsAndMethods() creates and connects a SyntheticArgumentBinding
* for each field created in the previous step.
* <li>ClassScope.filterTypeValueParameters() filters all TypeValueParameters from typeParameters.
* <li>TypeDeclaration.resolve() updates the field count (updateMaxFieldCount)
* <li>TypeDeclaration.internalAnalyzeCode() triggers analysis of TypeValueParameters in order
* to mark these as definitely assigned.
* <li>ConstructorDeclaration generates synthetic arguments and initializes fields from those args:
* see internalGenerateCode() and generateSyntheticFieldInitializationsIfNecessary()
* </ul>
*
* For applications of classes with TypeValueParameters see TypeAnchorReference.
*
*
* @author stephan
* @version $Id: TypeValueParameter.java 23401 2010-02-02 23:56:05Z stephan $
*/
public class TypeValueParameter extends TypeParameter {
/** The field representing this parameter. */
public FieldBinding fieldBinding;
public TypeValueParameter(char[] name, long position)
{
this.name = name;
this.sourceStart = (int)(position>>>32);
this.sourceEnd = (int)position;
this.declarationSourceEnd = this.sourceEnd;
this.declarationEnd = this.sourceEnd;
}
/**
* @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
*/
@Override
public int getKind() {
return TYPE_VALUE_PARAMETER;
}
public static FlowInfo analyseCode(TypeParameter[] parameters, BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
for (int i = 0; i < parameters.length; i++) {
flowInfo = parameters[i].analyseCode(currentScope, flowContext, flowInfo);
}
return flowInfo;
}
@Override
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
// type value parameters are assigned by construction.
flowInfo.markAsDefinitelyAssigned(this.fieldBinding);
return flowInfo;
}
@Override
public void resolve(ClassScope scope) {
// noop;
}
/** Resolve a list of type parameters, searching for type value parameters.
* @param typeParameters parameters to investigate
* @param scope
* @param bindings array of field bindings with enough space to hold all natural fields
* plus all fields generated from type value parameters
* @param knownFieldNames used for storing generated fields, too.
*/
public static void resolveValueParameters(
TypeParameter[] typeParameters,
ClassScope scope,
FieldBinding[] bindings,
HashtableOfObject knownFieldNames)
{
int count = 0;
for (int i = 0; i < typeParameters.length; i++) {
if (typeParameters[i] instanceof TypeValueParameter) {
FieldBinding resolvedField = ((TypeValueParameter) typeParameters[i]).resolveAsValueParameter(scope);
knownFieldNames.put(typeParameters[i].name, resolvedField);
bindings[count++] = resolvedField;
}
}
}
/** Resolve this parameter to a (resolved) field binding. */
private FieldBinding resolveAsValueParameter(ClassScope scope) {
this.type.resolveType(scope);
this.fieldBinding = new FieldBinding(
this.name,
this.type.resolvedType,
ClassFileConstants.AccFinal | ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccValueParam,
scope.enclosingSourceType(),
Constant.NotAConstant);
FieldModel.getModel(this.fieldBinding).addAttribute(new AnchorUsageRanksAttribute(this.fieldBinding));
return this.fieldBinding;
}
@Override
public StringBuffer printStatement(int indent, StringBuffer output) {
return printAsExpression(indent, output);
}
/** Count all TypeValuaParameters of declaration into the number of its fields. */
public static void updateMaxFieldCount(TypeDeclaration declaration) {
TypeParameter[] typeParameters = declaration.typeParameters;
for (int i = 0; i < typeParameters.length; i++) {
if (typeParameters[i] instanceof TypeValueParameter)
declaration.maxFieldCount++;
}
}
}