| /******************************************************************************* |
| * Copyright (c) 2005, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.jdt.internal.corext.refactoring.generics; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Stack; |
| |
| import org.eclipse.core.runtime.Assert; |
| |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.GenericType; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CollectionElementVariable2; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ConstraintVariable2; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.SubTypeConstraint2; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeEquivalenceSet; |
| |
| |
| public class ParametricStructureComputer { |
| public static class ParametricStructure { |
| |
| public static final ParametricStructure NONE= new ParametricStructure(); |
| |
| private final GenericType fBase; |
| private final ParametricStructure[] fParameters; |
| |
| public ParametricStructure(GenericType base) { |
| if (base == null) |
| throw new NullPointerException(); |
| fBase= base; |
| fParameters= new ParametricStructure[base.getTypeParameters().length]; |
| } |
| |
| private ParametricStructure() { |
| fBase= null; |
| fParameters= new ParametricStructure[0]; |
| } |
| |
| public ParametricStructure[] getParameters() { |
| return fParameters; |
| } |
| |
| public GenericType getBase() { |
| return fBase; |
| } |
| |
| public String toString() { |
| if (this == NONE) |
| return "NONE"; //$NON-NLS-1$ |
| else |
| return "ParamStructure " + fBase.toString() + '<' + Arrays.asList(fParameters) + '>'; //$NON-NLS-1$ |
| } |
| } |
| |
| |
| private static final boolean DEBUG_INITIALIZATION= false; |
| |
| /** |
| * Maps each ConstraintVariable2 onto an IType that is either an instance |
| * of AbstractTypeParameter, if the ConstraintVariable2 cannot possibly |
| * refer to a parametric type, or an instance of ParametricStructure with |
| * the appropriate sub-structure (if any) if it can. |
| */ |
| private final ElementStructureEnvironment fElemStructureEnv= new ElementStructureEnvironment(); |
| private final ConstraintVariable2[] fAllConstraintVariables; |
| private InferTypeArgumentsTCModel fTCModel; |
| |
| public ParametricStructureComputer(ConstraintVariable2[] allConstraintVariables, InferTypeArgumentsTCModel tcModel) { |
| fAllConstraintVariables= allConstraintVariables; |
| fTCModel= tcModel; |
| } |
| |
| public ElementStructureEnvironment getElemStructureEnv() { |
| return fElemStructureEnv; |
| } |
| |
| private void dumpContainerStructure() { |
| System.out.println("\n*** Container Structure: ***\n"); //$NON-NLS-1$ |
| for (int i= 0; i < fAllConstraintVariables.length; i++) { |
| ConstraintVariable2 v= fAllConstraintVariables[i]; |
| if (elemStructure(v) != null && !(elemStructure(v) == ParametricStructure.NONE)) |
| System.out.println("elemStructure(" + v.toString() + ") = " + elemStructure(v)); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| System.out.println(); |
| } |
| |
| |
| private Stack/*<ConstraintVariable2>*/ fWorkList2= new Stack(); |
| |
| |
| private void setStructureAndPush(ConstraintVariable2 v, ParametricStructure structure) { |
| setElemStructure(v, structure); |
| fWorkList2.push(v); |
| } |
| |
| //TODO hard-wired to collections |
| private void initializeContainerStructure(){ |
| if (DEBUG_INITIALIZATION) |
| System.out.println(" *** Seeding container structure ***"); //$NON-NLS-1$ |
| for (int i= 0; i < fAllConstraintVariables.length; i++) { |
| ConstraintVariable2 v= fAllConstraintVariables[i]; |
| TType varType= declaredTypeOf(v); |
| |
| if (varType != null) { |
| // rmf 11/30/2004 - Added isUnmodifiableFieldOrMethod() test to |
| // avoid unifying element types of container actual arguments |
| // with formal arguments of binary methods, to permit passing |
| // List<String> to a binary method taking a raw List. |
| if (isParametricType(varType) && !isUnmodifiableFieldOrMethod(v)) { |
| if (DEBUG_INITIALIZATION) System.out.println("Entity has container structure: " + v); //$NON-NLS-1$ |
| setStructureAndPush(v, newParametricType(varType)); |
| } else if (varType != null && !mightBeParametric(varType)) { |
| // Not a supertype of any container type - can't have container structure |
| if (DEBUG_INITIALIZATION) System.out.println("Entity DOES NOT have container structure: " + v); //$NON-NLS-1$ |
| setStructureAndPush(v, ParametricStructure.NONE); |
| } |
| // else we're not sure yet whether this has container structure |
| } else { |
| // TType exprType= v.getType(); // TODO: always null! |
| // |
| // if (isArrayAccess(v)) { |
| // if (DEBUG_INITIALIZATION) System.out.println("Entity DOES NOT have container structure: " + v); |
| // setStructureAndPush(v, NO_STRUCTURE); // definitely not container structure, Java 1.5 says no generics inside arrays |
| // } else if (isParametricType(exprType)) { |
| // if (DEBUG_INITIALIZATION) System.out.println("Entity has container structure: " + v); |
| // setStructureAndPush(v, newParametricType(exprType)); |
| // } else if (exprType != null && !mightBeParametric(exprType)) { |
| // // Not a supertype of any container type - can't have container structure |
| // if (DEBUG_INITIALIZATION) System.out.println("Entity DOES NOT have container structure: " + v); |
| // setStructureAndPush(v, NO_STRUCTURE); |
| // } |
| |
| // TODO Markus: the following just updates the set of child element variables of the parent variable of 'v'. |
| // You already maintain this information automatically, so the code below is not needed... |
| // if (v instanceof CollectionElementVariable2) { |
| // CollectionElementVariable2 ev= (CollectionElementVariable2) v; |
| // int idx= ev.getDeclarationTypeVariableIndex(); //TODO : INDEX IS -1 IF THE TYPE VARIABLE COMES FROM A SUPERTYPE!!! |
| // |
| // Collection/*<ConstraintVariable2>*/ vars= fTCModel.getElementVariables(ev).values(); |
| // |
| // if (vars == null) vars= new ConstraintVariable2[ev.getNumContainerTypeParams()]; |
| // vars[idx]= ev; |
| // fVariableElementEnv.setElementVariables(ev.getParentConstraintVariable(), vars); |
| // } |
| // else we're not sure yet whether this has container structure |
| } |
| } |
| // Every variable v in fAllVariables is now in one of 3 states: |
| // - elemStructure(v) == some parametric type: definitely container structure, but we may not know the sub-structure yet |
| // - elemStructure(v) == some AbstractTypeParameter: definitely not container structure |
| // - elemStructure(v) == null: we know nothing yet about its structure |
| } |
| |
| protected static TType declaredTypeOf(ConstraintVariable2 cv) { |
| //TODO: record original type of CollectionElementVariable2 iff source already had type parameter |
| return cv.getType(); |
| |
| // if (v instanceof ContextualExpressionVariable) { |
| // ContextualExpressionVariable ev= (ContextualExpressionVariable) v; |
| // |
| // return ev.getBinding(); |
| // } else if (v instanceof ReturnTypeVariable) { |
| // ReturnTypeVariable rv= (ReturnTypeVariable) v; |
| // |
| // return rv.getBinding(); |
| // } else if (v instanceof RawBindingVariable) { |
| // RawBindingVariable rv= (RawBindingVariable) v; |
| // |
| // return rv.getBinding(); |
| // } else if (v instanceof ParameterTypeVariable) { |
| // ParameterTypeVariable pv= (ParameterTypeVariable) v; |
| // |
| // return pv.getBinding(); |
| // } else |
| // return null; |
| } |
| |
| private boolean mightBeParametric(TType type) { |
| return isParametricType(type);//TODO check this is the only case? |
| } |
| |
| private void computeContainerStructure() { |
| if (DEBUG_INITIALIZATION) |
| System.out.println("\n*** Computing Container Structure ***\n"); //$NON-NLS-1$ |
| |
| initializeContainerStructure(); |
| |
| if (DEBUG_INITIALIZATION) |
| dumpContainerStructure(); |
| |
| while (!fWorkList2.isEmpty()) { |
| ConstraintVariable2 v= (ConstraintVariable2) fWorkList2.pop(); |
| List/*<ITypeConstraint>*/ usedIn= fTCModel.getUsedIn(v); |
| |
| for(Iterator/*<ITypeConstraint>*/ iter= usedIn.iterator(); iter.hasNext(); ) { |
| SubTypeConstraint2 stc= (SubTypeConstraint2) iter.next(); |
| |
| ConstraintVariable2 lhs= stc.getLeft(); |
| ConstraintVariable2 rhs= stc.getRight(); |
| |
| unifyContainerStructure(lhs, rhs); |
| } |
| |
| TypeEquivalenceSet typeEquivalenceSet= v.getTypeEquivalenceSet(); |
| if (typeEquivalenceSet != null) { |
| ConstraintVariable2[] contributingVariables= typeEquivalenceSet.getContributingVariables(); |
| for (int i= 0; i + 1 < contributingVariables.length; i++) { |
| ConstraintVariable2 first= contributingVariables[i]; |
| ConstraintVariable2 second= contributingVariables[i + 1]; |
| |
| unifyContainerStructure(first, second); |
| } |
| } |
| } |
| if (DEBUG_INITIALIZATION) |
| dumpContainerStructure(); |
| } |
| |
| private void unifyContainerStructure(ConstraintVariable2 lhs, ConstraintVariable2 rhs) { |
| // RMF 8/19/2004 - exclude propagation through unmodifiable fields/methods |
| if (isUnmodifiableFieldOrMethod(lhs) || isUnmodifiableFieldOrMethod(rhs)) |
| return; |
| |
| if (DEBUG_INITIALIZATION) |
| System.out.println("Examining constraint " + lhs + " {" + elemStructure(lhs) + "} <= " + rhs + " {" + elemStructure(rhs) + "}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ |
| |
| if (updateStructureOfVar(lhs, elemStructure(rhs), TypeOperator.SubType)) { |
| if (lhs instanceof CollectionElementVariable2) |
| updateParentContainerStructureFrom((CollectionElementVariable2) lhs, rhs); |
| updateElementVarStructureFromParent(lhs); |
| } |
| if (updateStructureOfVar(rhs, elemStructure(lhs), TypeOperator.SuperType)) { |
| if (rhs instanceof CollectionElementVariable2) |
| updateParentContainerStructureFrom((CollectionElementVariable2) rhs, lhs); |
| updateElementVarStructureFromParent(rhs); |
| } |
| } |
| |
| private ParametricStructure newParametricType(TType varType) { |
| //TODO: create CollectionElementVariable2s if necessary? |
| GenericType genericType= (GenericType) varType.getTypeDeclaration(); |
| return new ParametricStructure(genericType); |
| } |
| |
| private boolean isUnmodifiableFieldOrMethod(ConstraintVariable2 v) { |
| return false; //TODO: find out whether it's declared in a binary type |
| } |
| |
| private boolean isParametricType(TType type) { |
| return type.isParameterizedType() || type.isRawType() || type.isGenericType(); |
| } |
| |
| /** |
| * Updates the structure of the i'th type parameter of the given ParametricStructure |
| * to be consistent with that of 'otherStructure'. |
| */ |
| private boolean updateStructureOfIthParamFrom(ParametricStructure structure1, int i, ParametricStructure otherStructure) { |
| if ((otherStructure == null)) // no structure info to use to update 'structure1' |
| return false; |
| |
| Assert.isTrue(structure1 != otherStructure, "updateStructureOfIthParamFrom(): attempt to unify ith param of a parametric type with itself!"); //$NON-NLS-1$ |
| |
| ParametricStructure param1= structure1.getParameters()[i]; |
| boolean param1Unknown= (param1 == null); |
| |
| if (param1Unknown) { |
| if (DEBUG_INITIALIZATION) |
| System.out.println(" setting param " + i + " of " + structure1 + " to " + otherStructure); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| structure1.getParameters()[i]= otherStructure; |
| return true; |
| } |
| |
| boolean paramStructured= !(param1 == ParametricStructure.NONE); |
| boolean otherStructured= !(otherStructure == ParametricStructure.NONE); |
| |
| if (paramStructured && otherStructured) { // both parametric |
| // rmf 12/15/2004 - handle cases where different parametric types (e.g. |
| // List and Map) flow into the same place. If base types are different, |
| // conservatively make the type param of structure1 unstructured. |
| if (param1.getBase().equals(otherStructure.getBase())) |
| return updateStructureOfType(param1, otherStructure); |
| else { |
| structure1.getParameters()[i]= ParametricStructure.NONE; |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Updates the structure of any subsidiary element variables (if any) for |
| * the given ConstraintVariable2 (if it is in fact a container). |
| */ |
| private void updateElementVarStructureFromParent(ConstraintVariable2 v) { |
| // Propagate structure from container variable to any subsidiary element variables |
| if (elemStructure(v) != ParametricStructure.NONE && fTCModel.getElementVariables(v).size() > 0) { |
| ParametricStructure t= elemStructure(v); |
| for(Iterator iterator=fTCModel.getElementVariables(v).values().iterator(); iterator.hasNext(); ) { |
| CollectionElementVariable2 typeVar= (CollectionElementVariable2) iterator.next(); |
| int declarationTypeVariableIndex= typeVar.getDeclarationTypeVariableIndex(); |
| |
| if (declarationTypeVariableIndex != CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX) |
| updateStructureOfVar(typeVar, t.getParameters()[declarationTypeVariableIndex], TypeOperator.Equals); |
| } |
| } |
| } |
| |
| /** |
| * Updates the structure of the parent container variable of the given |
| * CollectionElementVariable2 from the structure of 'v1'. |
| * @param elemVar |
| * @param v1 |
| */ |
| private void updateParentContainerStructureFrom(CollectionElementVariable2 elemVar, ConstraintVariable2 v1) { |
| ConstraintVariable2 elemContainer= elemVar.getParentConstraintVariable(); |
| |
| // This could be something that appears like it should have container |
| // structure, but doesn't, e.g., an array access for an array of containers |
| // (JDK 1.5 disallows arrays of parametric types). So if it doesn't have |
| // container structure, ignore it. |
| ParametricStructure elemContainerStructure= elemStructure(elemContainer); |
| if (elemContainerStructure == ParametricStructure.NONE) |
| return; |
| |
| if (false) { |
| if (v1 instanceof CollectionElementVariable2) { |
| // if v1's container no longer has structure, remove structure from elemContainer |
| CollectionElementVariable2 ev1= (CollectionElementVariable2) v1; |
| ConstraintVariable2 v1Container= ev1.getParentConstraintVariable(); |
| |
| if (elemStructure(v1Container) == ParametricStructure.NONE) |
| setStructureAndPush(elemContainer, ParametricStructure.NONE); |
| return; |
| } |
| } |
| |
| if (elemContainerStructure == null) { // handle clone() |
| elemContainerStructure= newParametricType(elemContainer.getType()); |
| setStructureAndPush(elemContainer, elemContainerStructure); |
| } |
| ParametricStructure v1Structure= elemStructure(v1); |
| int parmIdx= elemVar.getDeclarationTypeVariableIndex(); //TODO: index is NOT_DECLARED_TYPE_VARIABLE_INDEX if the type variable comes from a supertype!!! |
| if (parmIdx == CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX) |
| return; //TODO: ParametricStructure should use type variable keys instead of index |
| |
| if (elemContainerStructure == v1Structure || containsSubStructure(v1Structure, elemContainerStructure)) { // avoid creating cyclic structure |
| if (!(elemStructure(elemVar) == ParametricStructure.NONE)) |
| setStructureAndPush(elemVar, ParametricStructure.NONE); |
| if (elemContainerStructure.getParameters()[parmIdx] == null) { |
| elemContainerStructure.getParameters()[parmIdx]= ParametricStructure.NONE; |
| fWorkList2.push(elemContainer); |
| } |
| } else if (updateStructureOfIthParamFrom(elemContainerStructure, parmIdx, v1Structure)) { |
| setStructureAndPush(elemVar, elemContainerStructure.getParameters()[parmIdx]); |
| fWorkList2.push(elemContainer); |
| if (DEBUG_INITIALIZATION) |
| System.out.println(" updated structure of " + elemContainer + " to " + elemContainerStructure); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| private boolean containsSubStructure(ParametricStructure containingStructure, ParametricStructure subStructure) { |
| if (containingStructure == null) |
| return false; |
| |
| ParametricStructure[] parameters= containingStructure.getParameters(); |
| for (int i= 0; i < parameters.length; i++) { |
| ParametricStructure parameter= parameters[i]; |
| if (parameter == subStructure) |
| return true; |
| else if (containsSubStructure(parameter, subStructure)) |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Make type1's sub-structure at least as detailed as that of type2 by |
| * copying the structure of type2's parameters (or its parameters' parameters) |
| * into type1's parameters. |
| */ |
| private boolean updateStructureOfType(ParametricStructure type1, ParametricStructure type2) { |
| if (type1 == null || type2 == null) |
| return false; |
| |
| ParametricStructure[] parms1= type1.getParameters(); |
| ParametricStructure[] parms2= type2.getParameters(); |
| boolean someChange= false; |
| |
| Assert.isTrue(parms1.length == parms2.length); |
| |
| for(int i=0; i < parms1.length; i++) { |
| if (type1 == parms2[i]) { // avoid creating cyclic structures! |
| if (parms1[i] != ParametricStructure.NONE) { |
| parms1[i]= ParametricStructure.NONE; |
| someChange= true; |
| } |
| } else if (updateStructureOfIthParamFrom(type1, i, parms2[i])) |
| someChange= true; |
| } |
| return someChange; |
| } |
| |
| static class TypeOperator { |
| // This could be a ConstraintOperator, if that had supertype |
| private final String fOp; |
| private TypeOperator(String op) { |
| fOp= op; |
| } |
| static public TypeOperator Equals= new TypeOperator("=^="); //$NON-NLS-1$ |
| static public TypeOperator SubType= new TypeOperator("<="); //$NON-NLS-1$ |
| static public TypeOperator SuperType= new TypeOperator("=>"); //$NON-NLS-1$ |
| public String toString() { |
| return fOp; |
| } |
| } |
| |
| /** |
| * Updates the structure of the given ConstraintVariable to be consistent |
| * with the structure of 'type2', in accordance with the given TypeOperator. |
| * If any changes are made, pushes the variable onto fWorkList2. |
| */ |
| private boolean updateStructureOfVar(ConstraintVariable2 v, ParametricStructure type2, TypeOperator op) { |
| if ((type2 == null)) // no structure info to use to update 'v' |
| return false ; |
| |
| ParametricStructure vStructure= elemStructure(v); |
| boolean vStructureUnknown= (vStructure == null); |
| boolean type2Structured= type2 != ParametricStructure.NONE; |
| |
| if (vStructureUnknown) { |
| if (DEBUG_INITIALIZATION) |
| System.out.println(" setting structure of " + v + " to " + type2); //$NON-NLS-1$ //$NON-NLS-2$ |
| setStructureAndPush(v, type2); |
| return true; |
| } |
| |
| boolean vStructured= vStructure != ParametricStructure.NONE; |
| |
| if (vStructured && !type2Structured) { |
| // If the relation is <=, then it's ok for v to have structure while |
| // type2 doesn't. On the other hand, if the relation is >= or ==, 'v' |
| // must be made unstructured, since it cannot be structured and be a |
| // supertype (or equal to) something unstructured. |
| if (op == TypeOperator.Equals || op == TypeOperator.SuperType) { |
| setStructureAndPush(v, type2); |
| return true; |
| } |
| } else if (vStructured && type2Structured) { // both are structured (parametric types) |
| // rmf 12/15/2004 - handle cases where different parametric types (e.g. |
| // List and Map) flow into the same place. If base types are different, |
| // conservatively make v unstructured. |
| if (!vStructure.getBase().equals(type2.getBase())) { // different parametric types? |
| if (op == TypeOperator.SuperType) { // if (v >= other), v can't have parametric structure |
| setStructureAndPush(v, ParametricStructure.NONE); |
| return true; |
| } |
| } else if (updateStructureOfType(vStructure, type2)) { |
| fWorkList2.push(v); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private void setElemStructure(ConstraintVariable2 v, ParametricStructure t) { |
| fElemStructureEnv.setElemStructure(v, t); |
| } |
| |
| private ParametricStructure elemStructure(ConstraintVariable2 v) { |
| return fElemStructureEnv.elemStructure(v); |
| } |
| |
| public Collection/*<CollectionElementVariable2>*/ createElemConstraintVariables() { |
| Collection newVars= new HashSet(); |
| |
| computeContainerStructure(); |
| |
| if (DEBUG_INITIALIZATION) |
| System.out.println("\n*** Creating Element Variables: ***\n"); //$NON-NLS-1$ |
| |
| for(int i= 0; i < fAllConstraintVariables.length; i++) { |
| newVars.addAll(createVariablesFor(fAllConstraintVariables[i])); |
| } |
| |
| // // rmf 12/1/2004 - Add all the non-binary created vars to candidates for |
| // // rewriting; handles the case where a derived class overrides nothing |
| // // and therefore no constraint explicitly ties that class' type parameters |
| // // to anything else. Without what follows, the only variables that go into |
| // // the candidate list are those that appear in constraints. |
| // for(Iterator iter= newVars.iterator(); iter.hasNext(); ) { |
| // CollectionElementVariable2 v= (CollectionElementVariable2) iter.next(); |
| // |
| // if (!isUnmodifiableFieldOrMethod(v.getParentConstraintVariable())) |
| // fCandidateVariables.add(v); |
| // } |
| // |
| // fAllConstraintVariables.addAll(newVars); |
| return newVars; |
| } |
| |
| private Collection/*ConstraintVariable2*/ createVariablesFor(ConstraintVariable2 v) { |
| ParametricStructure t= elemStructure(v); |
| |
| if (t == null || t == ParametricStructure.NONE) |
| return Collections.EMPTY_LIST; |
| |
| ParametricStructure parmType= t; |
| TType base = parmType.getBase(); |
| if (isParametricType(base)) { |
| return createAndInitVars(v, parmType); |
| } |
| throw new IllegalStateException("Attempt to create element variables for parametric variable of unknown type: " + parmType); //$NON-NLS-1$ |
| } |
| |
| private Collection/*<ConstraintVariable2>*/ getElementVariables(GenericType base, ConstraintVariable2 parent) { |
| fTCModel.makeElementVariables(parent, base); |
| return fTCModel.getElementVariables(parent).values(); |
| } |
| |
| private Collection/*ConstraintVariable2*/ createAndInitVars(ConstraintVariable2 v, ParametricStructure parmType) { |
| //TODO (->): in InferTypeArgumentsConstraintsSolver#createInitialEstimate(..) |
| //-> fTypeEstimates.setEstimateOf(v, SubTypesOfSingleton.create(ParametricStructure.getBaseContainerType(parmType.getBase(), sHierarchy))); |
| Collection/*<ConstraintVariable2>*/ elementVars= getElementVariables(parmType.getBase(), v); |
| //-> setNewTypeParamEstimateForEach(elementVars); |
| Collection result= createVars(elementVars, parmType.getParameters()); |
| return result; |
| } |
| |
| private Collection/*ConstraintVariable2*/ createVars(Collection/*ConstraintVariable2>*/ cvs, ParametricStructure[] parms) { |
| if (parms.length > 0) { // happens, e.g., for Properties (non-parametric) |
| // Assert.isTrue(cvs.size() == parms.length, "cvs.length==" + cvs.size() + " parms.length=" + parms.length); //assumption is wrong in presence of NOT_DECLARED_TYPE_VARIABLE_INDEX |
| for (Iterator iter= cvs.iterator(); iter.hasNext(); ) { |
| CollectionElementVariable2 childVar= (CollectionElementVariable2) iter.next(); |
| int declarationTypeVariableIndex= childVar.getDeclarationTypeVariableIndex(); |
| |
| if (declarationTypeVariableIndex != CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX) |
| setElemStructure(childVar, parms[declarationTypeVariableIndex]); |
| } |
| } else { |
| for (Iterator iter= cvs.iterator(); iter.hasNext(); ) { |
| CollectionElementVariable2 childVar= (CollectionElementVariable2) iter.next(); |
| int declarationTypeVariableIndex= childVar.getDeclarationTypeVariableIndex(); |
| |
| if (declarationTypeVariableIndex != CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX) |
| setElemStructure(childVar, ParametricStructure.NONE); |
| } |
| } |
| List result= new ArrayList(cvs.size() * 2);//roughly |
| for (Iterator iter= cvs.iterator(); iter.hasNext(); ) { |
| CollectionElementVariable2 childVar= (CollectionElementVariable2) iter.next(); |
| int declarationTypeVariableIndex= childVar.getDeclarationTypeVariableIndex(); |
| |
| if (declarationTypeVariableIndex != CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX) { |
| result.add(childVar); |
| result.addAll(createVariablesFor(childVar)); |
| } |
| } |
| return result; |
| } |
| } |