/******************************************************************************* * Copyright (c) 2012 NumberFour AG * * 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: * NumberFour AG - initial API and Implementation (Alex Panchenko) *******************************************************************************/ package org.eclipse.dltk.javascript.internal.core; import java.util.List; import org.eclipse.dltk.internal.javascript.ti.IValue; import org.eclipse.dltk.javascript.typeinfo.IRMember; import org.eclipse.dltk.javascript.typeinfo.IRType; import org.eclipse.dltk.javascript.typeinfo.IRTypeDeclaration; import org.eclipse.dltk.javascript.typeinfo.ITypeSystem; import org.eclipse.dltk.javascript.typeinfo.TypeCompatibility; import org.eclipse.dltk.javascript.typeinfo.model.GenericType; import org.eclipse.dltk.javascript.typeinfo.model.Type; import org.eclipse.dltk.javascript.typeinfo.model.TypeVariable; import org.eclipse.emf.common.util.EList; public class RParameterizedTypeDeclaration extends RTypeDeclaration implements ITypeSystem { private final List<IRType> typeArguments; public RParameterizedTypeDeclaration(ITypeSystem typeSystem, GenericType type, List<IRType> typeArguments) { super(typeSystem, type); this.typeArguments = typeArguments; } @Override protected ITypeSystem getEffectiveTypeSystem() { return this; } @Override public boolean isGeneric() { return true; } @Override public boolean isParameterized() { return true; } @Override public List<IRType> getActualTypeArguments() { return typeArguments; } @Override public String getName() { final StringBuilder sb = new StringBuilder(); sb.append(getSource().getName()); sb.append('<'); for (IRType type : getActualTypeArguments()) { sb.append(type.getName()); } sb.append('>'); return sb.toString(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final RParameterizedTypeDeclaration other = (RParameterizedTypeDeclaration) obj; return type.equals(other.type) && typeArguments.equals(other.typeArguments); } @Override public TypeCompatibility isAssignableFrom(IRTypeDeclaration declaration) { if (declaration instanceof RParameterizedTypeDeclaration) { final RParameterizedTypeDeclaration other = (RParameterizedTypeDeclaration) declaration; if (type.equals(other.type)) { return isAssignableFrom(typeArguments, other.typeArguments) ? TypeCompatibility.TRUE : TypeCompatibility.UNPARAMETERIZED; } } return super.isAssignableFrom(declaration); } @Override protected boolean _equals(RTypeDeclaration other) { if (this.equals(other)) { return true; } else if (type.equals(other.type)) { if (other instanceof RParameterizedTypeDeclaration) { return isAssignableFrom(typeArguments, ((RParameterizedTypeDeclaration) other).typeArguments); } else { return true; } } else { return false; } } private static boolean isAssignableFrom(List<IRType> dest, List<IRType> src) { if (dest.size() == src.size()) { for (int i = 0; i < dest.size(); ++i) { if (dest.get(i).isAssignableFrom(src.get(i)) != TypeCompatibility.TRUE) { return false; } } return true; } return false; } // ITypeSystem methods public Type getKnownType(String typeName) { return typeSystem.getKnownType(typeName); } public Type resolveType(Type type) { return typeSystem.resolveType(type); } public IValue valueOf(IRMember member) { return typeSystem.valueOf(member); } public IRTypeDeclaration convert(Type type) { return typeSystem.convert(type); } public <E extends IRMember> E contextualize(E member, IRTypeDeclaration type) { return typeSystem.contextualize(member, type); } public IRTypeDeclaration parameterize(Type target, List<? extends IRType> parameters) { return typeSystem.parameterize(target, parameters); } public IRType getTypeVariable(TypeVariable variable) { final EList<TypeVariable> vars = ((GenericType) getSource()) .getTypeParameters(); for (int i = 0, size = vars.size(); i < size; ++i) { if (vars.get(i) == variable) { return typeArguments.get(i); } } return null; } public Object getValue(Object key) { return typeSystem.getValue(key); } public void setValue(Object key, Object value) { typeSystem.setValue(key, value); } public ITypeSystem getPrimary() { return typeSystem; } }