blob: 33d139cc839ebd98de6d4b2cca97eea97b59ed57 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2017 1C-Soft LLC.
* 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:
* Vladimir Piskarev (1C) - initial API and implementation
*******************************************************************************/
package org.eclipse.handly.internal.examples.javamodel;
import java.util.List;
import java.util.Map;
import org.eclipse.handly.examples.javamodel.IJavaElement;
import org.eclipse.handly.examples.javamodel.IJavaSourceConstruct;
import org.eclipse.handly.model.IElement;
import org.eclipse.handly.model.impl.SourceElementBody;
import org.eclipse.handly.model.impl.StructureHelper;
import org.eclipse.handly.util.TextRange;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
/**
* Builds the inner structure for a compilation unit.
*/
class CompilatonUnitStructureBuilder
{
private static final IJavaSourceConstruct[] NO_CHILDREN =
new IJavaSourceConstruct[0];
private final Map<IElement, Object> newElements;
private final StructureHelper helper = new StructureHelper();
/**
* Constructs a new compilation unit structure builder.
*
* @param newElements the map to populate with structure elements
* (not <code>null</code>)
*/
CompilatonUnitStructureBuilder(Map<IElement, Object> newElements)
{
if (newElements == null)
throw new IllegalArgumentException();
this.newElements = newElements;
}
/**
* Builds the structure for the given compilation unit based on its AST.
*
* @param handle the handle to a compilation unit (not <code>null</code>)
* @param cu the AST of the compilation unit (not <code>null</code>)
*/
void buildStructure(CompilationUnit handle,
org.eclipse.jdt.core.dom.CompilationUnit cu)
{
SourceElementBody body = new SourceElementBody();
org.eclipse.jdt.core.dom.PackageDeclaration pkg = cu.getPackage();
if (pkg != null)
buildStructure(handle, body, pkg);
@SuppressWarnings("unchecked")
List<org.eclipse.jdt.core.dom.ImportDeclaration> imports = cu.imports();
if (!imports.isEmpty())
buildStructure(handle, body, imports);
@SuppressWarnings("unchecked")
List<? extends AbstractTypeDeclaration> types = cu.types();
for (AbstractTypeDeclaration type : types)
buildStructure(handle, body, type);
body.setChildren(helper.popChildren(body).toArray(
CompilationUnit.NO_CHILDREN));
newElements.put(handle, body);
}
private void buildStructure(CompilationUnit parent, Object parentBody,
org.eclipse.jdt.core.dom.PackageDeclaration pkg)
{
PackageDeclaration handle = new PackageDeclaration(parent,
pkg.getName().getFullyQualifiedName());
helper.resolveDuplicates(handle);
SourceElementBody body = new SourceElementBody();
body.setFullRange(getTextRange(pkg));
body.setIdentifyingRange(getTextRange(pkg.getName()));
body.setChildren(NO_CHILDREN);
newElements.put(handle, body);
helper.pushChild(parentBody, handle);
}
private void buildStructure(CompilationUnit parent, Object parentBody,
List<org.eclipse.jdt.core.dom.ImportDeclaration> imports)
{
ImportContainer handle = new ImportContainer(parent);
SourceElementBody body = new SourceElementBody();
org.eclipse.jdt.core.dom.ImportDeclaration firstImport = imports.get(0);
org.eclipse.jdt.core.dom.ImportDeclaration lastImport = imports.get(
imports.size() - 1);
body.setFullRange(new TextRange(firstImport.getStartPosition(),
lastImport.getStartPosition() + lastImport.getLength()
- firstImport.getStartPosition()));
for (org.eclipse.jdt.core.dom.ImportDeclaration importDecl : imports)
buildStructure(handle, body, importDecl);
body.setChildren(helper.popChildren(body).toArray(
ImportContainer.NO_CHILDREN));
newElements.put(handle, body);
helper.pushChild(parentBody, handle);
}
private void buildStructure(ImportContainer parent, Object parentBody,
org.eclipse.jdt.core.dom.ImportDeclaration importDecl)
{
String name = importDecl.getName().getFullyQualifiedName();
if (importDecl.isOnDemand())
name += ".*"; //$NON-NLS-1$
ImportDeclaration handle = new ImportDeclaration(parent, name);
helper.resolveDuplicates(handle);
SourceElementBody body = new SourceElementBody();
body.setFullRange(getTextRange(importDecl));
body.setIdentifyingRange(getTextRange(importDecl.getName()));
body.setChildren(NO_CHILDREN);
newElements.put(handle, body);
helper.pushChild(parentBody, handle);
}
private void buildStructure(IJavaElement parent, Object parentBody,
AbstractTypeDeclaration type)
{
Type handle = new Type(parent, type.getName().getIdentifier());
helper.resolveDuplicates(handle);
SourceElementBody body = new SourceElementBody();
body.setFullRange(getTextRange(type));
body.setIdentifyingRange(getTextRange(type.getName()));
int flags = type.getModifiers();
if (type instanceof TypeDeclaration)
{
TypeDeclaration typeDeclaration = (TypeDeclaration)type;
if (typeDeclaration.isInterface())
flags |= Flags.AccInterface;
org.eclipse.jdt.core.dom.Type superclassType =
typeDeclaration.getSuperclassType();
if (superclassType != null)
body.set(Type.SUPERCLASS_TYPE, AstUtil.getSignature(
superclassType));
@SuppressWarnings("unchecked")
List<? extends org.eclipse.jdt.core.dom.Type> superInterfaceTypes =
typeDeclaration.superInterfaceTypes();
body.set(Type.SUPER_INTERFACE_TYPES, AstUtil.getSignatures(
superInterfaceTypes));
}
else if (type instanceof EnumDeclaration)
{
EnumDeclaration enumDeclaration = (EnumDeclaration)type;
flags |= Flags.AccEnum;
@SuppressWarnings("unchecked")
List<? extends org.eclipse.jdt.core.dom.Type> superInterfaceTypes =
enumDeclaration.superInterfaceTypes();
body.set(Type.SUPER_INTERFACE_TYPES, AstUtil.getSignatures(
superInterfaceTypes));
@SuppressWarnings("unchecked")
List<EnumConstantDeclaration> enumConstants =
enumDeclaration.enumConstants();
for (EnumConstantDeclaration enumConstant : enumConstants)
buildStructure(handle, body, enumDeclaration, enumConstant);
}
else if (type instanceof AnnotationTypeDeclaration)
{
flags |= Flags.AccInterface | Flags.AccAnnotation;
}
body.set(Type.FLAGS, flags);
@SuppressWarnings("unchecked")
List<? extends BodyDeclaration> bodyDeclarations =
type.bodyDeclarations();
for (BodyDeclaration bd : bodyDeclarations)
{
if (bd instanceof FieldDeclaration)
buildStructure(handle, body, (FieldDeclaration)bd);
else if (bd instanceof MethodDeclaration)
buildStructure(handle, body, (MethodDeclaration)bd);
else if (bd instanceof AbstractTypeDeclaration)
buildStructure(handle, body, (AbstractTypeDeclaration)bd);
else if (bd instanceof AnnotationTypeMemberDeclaration)
buildStructure(handle, body,
(AnnotationTypeMemberDeclaration)bd);
}
body.setChildren(helper.popChildren(body).toArray(Type.NO_CHILDREN));
newElements.put(handle, body);
helper.pushChild(parentBody, handle);
}
private void buildStructure(Type parent, Object parentBody,
FieldDeclaration field)
{
@SuppressWarnings("unchecked")
List<VariableDeclarationFragment> fragments = field.fragments();
for (VariableDeclarationFragment fragment : fragments)
buildStructure(parent, parentBody, field, fragment);
}
private void buildStructure(Type parent, Object parentBody,
FieldDeclaration field, VariableDeclarationFragment fragment)
{
Field handle = new Field(parent, fragment.getName().getIdentifier());
helper.resolveDuplicates(handle);
SourceElementBody body = new SourceElementBody();
body.setFullRange(getTextRange(field));
body.setIdentifyingRange(getTextRange(fragment.getName()));
body.set(Field.FLAGS, field.getModifiers());
body.set(Field.TYPE, Signature.createArraySignature(
AstUtil.getSignature(field.getType()),
fragment.getExtraDimensions()));
body.setChildren(NO_CHILDREN);
newElements.put(handle, body);
helper.pushChild(parentBody, handle);
}
private void buildStructure(Type parent, Object parentBody,
EnumDeclaration enumDeclaration, EnumConstantDeclaration enumConstant)
{
Field handle = new Field(parent,
enumConstant.getName().getIdentifier());
helper.resolveDuplicates(handle);
SourceElementBody body = new SourceElementBody();
body.setFullRange(getTextRange(enumConstant));
body.setIdentifyingRange(getTextRange(enumConstant.getName()));
body.set(Field.FLAGS, enumConstant.getModifiers() | Flags.AccEnum);
body.set(Field.TYPE, Signature.createTypeSignature(
enumDeclaration.getName().getIdentifier(), false));
body.setChildren(NO_CHILDREN);
newElements.put(handle, body);
helper.pushChild(parentBody, handle);
}
private void buildStructure(Type parent, Object parentBody,
MethodDeclaration method)
{
@SuppressWarnings("unchecked")
List<SingleVariableDeclaration> parameters = method.parameters();
int numberOfParameters = parameters.size();
String[] parameterTypes = new String[numberOfParameters];
String[] parameterNames = new String[numberOfParameters];
int i = 0;
for (SingleVariableDeclaration parameter : parameters)
{
parameterTypes[i] = Signature.createArraySignature(
AstUtil.getSignature(parameter.getType()),
parameter.getExtraDimensions());
parameterNames[i] = parameter.getName().getIdentifier();
i++;
}
Method handle = new Method(parent, method.getName().getIdentifier(),
parameterTypes);
helper.resolveDuplicates(handle);
SourceElementBody body = new SourceElementBody();
body.setFullRange(getTextRange(method));
body.setIdentifyingRange(getTextRange(method.getName()));
body.set(Method.FLAGS, method.getModifiers());
body.set(Method.PARAMETER_NAMES, parameterNames);
org.eclipse.jdt.core.dom.Type returnType = method.getReturnType2();
if (returnType != null)
{
body.set(Method.RETURN_TYPE, Signature.createArraySignature(
AstUtil.getSignature(returnType), method.getExtraDimensions()));
}
@SuppressWarnings("unchecked")
List<? extends org.eclipse.jdt.core.dom.Type> thrownExceptions =
method.thrownExceptionTypes();
body.set(Method.EXCEPTION_TYPES, AstUtil.getSignatures(
thrownExceptions));
if (method.isConstructor())
body.set(Method.IS_CONSTRUCTOR, Boolean.TRUE);
body.setChildren(NO_CHILDREN);
newElements.put(handle, body);
helper.pushChild(parentBody, handle);
}
private void buildStructure(Type parent, Object parentBody,
AnnotationTypeMemberDeclaration annotationTypeMember)
{
Method handle = new Method(parent,
annotationTypeMember.getName().getIdentifier(), Method.NO_STRINGS);
helper.resolveDuplicates(handle);
SourceElementBody body = new SourceElementBody();
body.setFullRange(getTextRange(annotationTypeMember));
body.setIdentifyingRange(getTextRange(annotationTypeMember.getName()));
body.set(Method.FLAGS, annotationTypeMember.getModifiers());
body.set(Method.RETURN_TYPE, AstUtil.getSignature(
annotationTypeMember.getType()));
body.setChildren(NO_CHILDREN);
newElements.put(handle, body);
helper.pushChild(parentBody, handle);
}
private static TextRange getTextRange(ASTNode node)
{
int startPosition = node.getStartPosition();
if (startPosition == -1)
return null;
return new TextRange(startPosition, node.getLength());
}
}