blob: f599af11b4b2c98bff1f48282488072664021f5e [file] [log] [blame]
/*
* Copyright (c) 2010-2020 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 static java.util.Collections.emptyList;
import java.util.List;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.Javadoc;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.scout.sdk.core.model.api.IField;
import org.eclipse.scout.sdk.core.model.api.IMetaValue;
import org.eclipse.scout.sdk.core.model.api.ISourceRange;
import org.eclipse.scout.sdk.core.model.api.internal.FieldImplementor;
import org.eclipse.scout.sdk.core.model.spi.CompilationUnitSpi;
import org.eclipse.scout.sdk.core.model.spi.FieldSpi;
import org.eclipse.scout.sdk.core.model.spi.JavaElementSpi;
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;
public class DeclarationFieldWithEcj extends AbstractMemberWithEcj<IField> implements FieldSpi {
private final DeclarationTypeWithEcj m_declaringType;
private final FieldDeclaration m_astNode;
private final char[] m_name;
private final FinalValue<String> m_nameAsString;
private final FinalValue<TypeSpi> m_type;
private final FinalValue<List<DeclarationAnnotationWithEcj>> m_annotations;
private final FinalValue<IMetaValue> m_constRef;
private final FinalValue<ISourceRange> m_source;
private final FinalValue<ISourceRange> m_initSource;
private final FinalValue<ISourceRange> m_javaDocSource;
private int m_flags;
protected DeclarationFieldWithEcj(JavaEnvironmentWithEcj env, DeclarationTypeWithEcj declaringType, FieldDeclaration astNode) {
super(env);
m_declaringType = Ensure.notNull(declaringType);
m_astNode = Ensure.notNull(astNode);
m_name = astNode.name != null ? astNode.name : CharOperation.NO_CHAR;//static { } has name =""
m_flags = -1;
m_nameAsString = new FinalValue<>();
m_type = new FinalValue<>();
m_annotations = new FinalValue<>();
m_constRef = new FinalValue<>();
m_source = new FinalValue<>();
m_initSource = new FinalValue<>();
m_javaDocSource = new FinalValue<>();
}
@Override
public JavaElementSpi internalFindNewElement() {
TypeSpi newType = (TypeSpi) getDeclaringType().internalFindNewElement();
if (newType != null) {
for (FieldSpi newF : newType.getFields()) {
if (getElementName().equals(newF.getElementName())) {
return newF;
}
}
}
return null;
}
@Override
protected IField internalCreateApi() {
return new FieldImplementor(this);
}
public FieldDeclaration getInternalFieldDeclaration() {
return m_astNode;
}
@Override
public DeclarationTypeWithEcj getDeclaringType() {
return m_declaringType;
}
@Override
public IMetaValue getConstantValue() {
return m_constRef.computeIfAbsentAndGet(() -> {
Object compiledValue = SpiWithEcjUtils.compileExpression(m_astNode.initialization, null, javaEnvWithEcj());
return SpiWithEcjUtils.resolveCompiledValue(javaEnvWithEcj(), this, compiledValue);
});
}
@Override
public TypeSpi getDataType() {
return m_type.computeIfAbsentAndGet(() -> {
if (m_astNode.type == null) {
//static{ } section
return javaEnvWithEcj().createVoidType();
}
TypeBinding tb = m_astNode.type.resolvedType;
if (tb == null) {
synchronized (javaEnvWithEcj().lock()) {
tb = m_astNode.type.resolveType(SpiWithEcjUtils.classScopeOf(this));
}
}
return SpiWithEcjUtils.bindingToType(javaEnvWithEcj(), tb);
});
}
@Override
public List<DeclarationAnnotationWithEcj> getAnnotations() {
return m_annotations.computeIfAbsentAndGet(() -> SpiWithEcjUtils.createDeclarationAnnotations(javaEnvWithEcj(), this, m_astNode.annotations));
}
@Override
public int getFlags() {
if (m_flags < 0) {
m_flags = SpiWithEcjUtils.getTypeFlags(m_astNode.modifiers, null, SpiWithEcjUtils.hasDeprecatedAnnotation(getAnnotations()));
}
return m_flags;
}
@Override
public String getElementName() {
return m_nameAsString.computeIfAbsentAndGet(() -> new String(m_name));
}
@Override
public List<TypeParameterSpi> getTypeParameters() {
return emptyList();
}
@Override
public boolean hasTypeParameters() {
return false;
}
@Override
public ISourceRange getSource() {
return m_source.computeIfAbsentAndGet(() -> {
CompilationUnitSpi cu = m_declaringType.getCompilationUnit();
FieldDeclaration decl = m_astNode;
return javaEnvWithEcj().getSource(cu, decl.declarationSourceStart, decl.declarationSourceEnd);
});
}
@Override
public ISourceRange getSourceOfInitializer() {
return m_initSource.computeIfAbsentAndGet(() -> {
CompilationUnitSpi cu = m_declaringType.getCompilationUnit();
if (m_astNode instanceof Initializer) {
// static initializer
return javaEnvWithEcj().getSource(cu, m_astNode.declarationSourceStart, m_astNode.declarationSourceEnd);
}
Expression decl = m_astNode.initialization;
if (decl == null) {
return null;
}
return javaEnvWithEcj().getSource(cu, decl.sourceStart, decl.sourceEnd);
});
}
@Override
public ISourceRange getJavaDoc() {
return m_javaDocSource.computeIfAbsentAndGet(() -> {
Javadoc doc = m_astNode.javadoc;
if (doc == null) {
return null;
}
CompilationUnitSpi cu = m_declaringType.getCompilationUnit();
return javaEnvWithEcj().getSource(cu, doc.sourceStart, doc.sourceEnd);
});
}
}