blob: e2ddaa1291f3977e67b8a9557f90ddc76e20de52 [file] [log] [blame]
/*
* Copyright (c) 2015 BSI Business Systems Integration 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:
* BSI Business Systems Integration AG - initial API and implementation
*/
package org.eclipse.scout.sdk.core.model.ecj;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.scout.sdk.core.model.api.ISourceRange;
import org.eclipse.scout.sdk.core.model.api.ITypeParameter;
import org.eclipse.scout.sdk.core.model.api.internal.TypeParameterImplementor;
import org.eclipse.scout.sdk.core.model.spi.AbstractJavaEnvironment;
import org.eclipse.scout.sdk.core.model.spi.CompilationUnitSpi;
import org.eclipse.scout.sdk.core.model.spi.JavaElementSpi;
import org.eclipse.scout.sdk.core.model.spi.MemberSpi;
import org.eclipse.scout.sdk.core.model.spi.TypeParameterSpi;
import org.eclipse.scout.sdk.core.model.spi.TypeSpi;
import org.eclipse.scout.sdk.core.util.Ensure;
import org.eclipse.scout.sdk.core.util.FinalValue;
/**
* <h3>{@link DeclarationTypeParameterWithEcj}</h3>
*
* @since 5.1.0
*/
public class DeclarationTypeParameterWithEcj extends AbstractJavaElementWithEcj<ITypeParameter> implements TypeParameterSpi {
private final AbstractMemberWithEcj<?> m_declaringMember;
private final TypeParameter m_astNode;
private final int m_index;
private final String m_name;
private final FinalValue<List<TypeSpi>> m_bounds;
private final FinalValue<ISourceRange> m_source;
protected DeclarationTypeParameterWithEcj(AbstractJavaEnvironment env, AbstractMemberWithEcj<?> declaringMember, TypeParameter astNode, int index) {
super(env);
m_declaringMember = Ensure.notNull(declaringMember);
m_astNode = Ensure.notNull(astNode);
m_index = index;
m_name = new String(m_astNode.name);
m_bounds = new FinalValue<>();
m_source = new FinalValue<>();
}
protected static TypeBinding ensureResolvedType(Scope scope, Expression r) {
TypeBinding resolvedType = r.resolvedType;
if (resolvedType != null) {
return resolvedType;
}
if (scope instanceof ClassScope) {
r.resolveType((ClassScope) scope);
}
else {
r.resolveType((BlockScope) scope);
}
return r.resolvedType;
}
@Override
public JavaElementSpi internalFindNewElement() {
MemberSpi newMember = (MemberSpi) getDeclaringMember().internalFindNewElement();
if (newMember != null && newMember.getTypeParameters().size() > m_index) {
return newMember.getTypeParameters().get(m_index);
}
return null;
}
@Override
protected ITypeParameter internalCreateApi() {
return new TypeParameterImplementor(this);
}
public TypeParameter getInternalTypeParameter() {
return m_astNode;
}
@Override
public List<TypeSpi> getBounds() {
return m_bounds.computeIfAbsentAndGet(() -> {
boolean hasType = m_astNode.type != null;
boolean hasBounds = m_astNode.bounds != null && m_astNode.bounds.length > 0;
int size = 0;
if (hasType) {
size++;
}
if (hasBounds) {
size += m_astNode.bounds.length;
}
List<TypeSpi> result = new ArrayList<>(size);
Scope scope = SpiWithEcjUtils.memberScopeOf(this);
if (hasType) {
TypeSpi t = SpiWithEcjUtils.bindingToType(javaEnvWithEcj(), ensureResolvedType(scope, m_astNode.type));
if (t != null) {
result.add(t);
}
}
if (hasBounds) {
for (TypeReference r : m_astNode.bounds) {
TypeSpi t = SpiWithEcjUtils.bindingToType(javaEnvWithEcj(), ensureResolvedType(scope, r));
if (t != null) {
result.add(t);
}
}
}
return result;
});
}
@Override
public AbstractMemberWithEcj<?> getDeclaringMember() {
return m_declaringMember;
}
@Override
public String getElementName() {
return m_name;
}
@Override
public ISourceRange getSource() {
return m_source.computeIfAbsentAndGet(() -> {
CompilationUnitSpi cu = SpiWithEcjUtils.declaringTypeOf(this).getCompilationUnit();
TypeParameter decl = m_astNode;
return javaEnvWithEcj().getSource(cu, decl.declarationSourceStart, decl.declarationSourceEnd);
});
}
}