/******************************************************************************* * Copyright (c) 2012-2015 Codenvy, S.A. * 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: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.ext.java.worker; import org.eclipse.che.ide.collections.Array; import org.eclipse.che.ide.collections.js.JsoArray; import org.eclipse.che.ide.ext.java.jdt.core.dom.ASTNode; import org.eclipse.che.ide.ext.java.jdt.core.dom.ASTVisitor; import org.eclipse.che.ide.ext.java.jdt.core.dom.AbstractTypeDeclaration; import org.eclipse.che.ide.ext.java.jdt.core.dom.AnnotationTypeDeclaration; import org.eclipse.che.ide.ext.java.jdt.core.dom.AnonymousClassDeclaration; import org.eclipse.che.ide.ext.java.jdt.core.dom.ClassInstanceCreation; import org.eclipse.che.ide.ext.java.jdt.core.dom.CompilationUnit; import org.eclipse.che.ide.ext.java.jdt.core.dom.EnumDeclaration; import org.eclipse.che.ide.ext.java.jdt.core.dom.FieldDeclaration; import org.eclipse.che.ide.ext.java.jdt.core.dom.ImportDeclaration; import org.eclipse.che.ide.ext.java.jdt.core.dom.MethodDeclaration; import org.eclipse.che.ide.ext.java.jdt.core.dom.PackageDeclaration; import org.eclipse.che.ide.ext.java.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.che.ide.ext.java.jdt.core.dom.Type; import org.eclipse.che.ide.ext.java.jdt.core.dom.TypeDeclaration; import org.eclipse.che.ide.ext.java.jdt.core.dom.VariableDeclarationFragment; import org.eclipse.che.ide.ext.java.jdt.internal.corext.dom.ASTNodes; import org.eclipse.che.ide.ext.java.messages.BlockTypes; import org.eclipse.che.ide.ext.java.messages.impl.OutlineUpdateMessage; import org.eclipse.che.ide.ext.java.messages.impl.WorkerCodeBlock; import java.util.Iterator; /** * Worker Outline updater * * @author Evgen Vidolob */ public class WorkerOutlineModelUpdater { private WorkerCodeBlock root; private JavaParserWorker worker; public WorkerOutlineModelUpdater(JavaParserWorker worker) { this.worker = worker; } public void onCompilationUnitChanged(CompilationUnit cUnit, String path) { if (this.root == null) { root = WorkerCodeBlock.make(); // root.setType(CodeBlock.ROOT_TYPE); root.setOffset(0); root.setChildren(JsoArray.<WorkerCodeBlock>create()); } OutlineAstVisitor v = new OutlineAstVisitor(root, cUnit); cUnit.accept(v); OutlineUpdateMessage message = OutlineUpdateMessage.make(); message.setFilePath(path).setBlocks(v.childrens); worker.sendMessage(message.serialize()); } class OutlineAstVisitor extends ASTVisitor { private final ASTNode astParent; WorkerCodeBlock parent; Array<WorkerCodeBlock> childrens = JsoArray.create(); private WorkerCodeBlock imports; /** @param parent */ public OutlineAstVisitor(WorkerCodeBlock parent, ASTNode astParent) { super(); this.parent = parent; this.astParent = astParent; } /** {@inheritDoc} */ @Override public boolean visit(PackageDeclaration node) { WorkerCodeBlock i = createCodeBlock(BlockTypes.PACKAGE.getType(), node.getStartPosition(), node.getLength()); i.setName(node.getName().getFullyQualifiedName()); childrens.add(i); return false; } /** {@inheritDoc} */ @Override public boolean visit(ImportDeclaration node) { if (imports == null) { imports = WorkerCodeBlock.make(); imports.setChildren(JsoArray.<WorkerCodeBlock>create()); imports.setType(BlockTypes.IMPORTS.getType()); imports.setName("import declarations"); imports.setOffset(node.getStartPosition()); imports.setLength(0); childrens.add(imports); } WorkerCodeBlock c = createCodeBlock(BlockTypes.IMPORT.getType(), node.getStartPosition(), node.getLength()); c.setName(node.getName().getFullyQualifiedName()); imports.getChildren().add(c); return false; } /** {@inheritDoc} */ @Override public boolean visit(TypeDeclaration node) { if (node == astParent) return true; WorkerCodeBlock type = addJavaType(node, node.isInterface() ? BlockTypes.INTERFACE : BlockTypes.CLASS); addChildrens(node, type); return false; } /** {@inheritDoc} */ @Override public boolean visit(AnnotationTypeDeclaration node) { if (node == astParent) return true; WorkerCodeBlock type = addJavaType(node, BlockTypes.ANNOTATION); addChildrens(node, type); return false; } private void addChildrens(ASTNode node, WorkerCodeBlock type) { OutlineAstVisitor typeVisitor = new OutlineAstVisitor(type, node); node.accept(typeVisitor); type.setChildren(typeVisitor.childrens); } /** {@inheritDoc} */ @Override public boolean visit(EnumDeclaration node) { if (node == astParent) return true; WorkerCodeBlock type = addJavaType(node, BlockTypes.ENUM); addChildrens(node, type); return false; } private WorkerCodeBlock addJavaType(AbstractTypeDeclaration node, BlockTypes type) { WorkerCodeBlock t = createCodeBlock(type.getType(), node.getStartPosition(), node.getLength()); t.setModifiers(node.getModifiers()); t.setName(node.getName().getFullyQualifiedName()); childrens.add(t); return t; } /** {@inheritDoc} */ @Override public boolean visit(FieldDeclaration node) { if (node == astParent) return true; for (VariableDeclarationFragment fragment : node.fragments()) { WorkerCodeBlock f = createCodeBlock(BlockTypes.FIELD.getType(), fragment.getStartPosition(), fragment.getLength()); f.setName(fragment.getName().getFullyQualifiedName()); f.setModifiers(node.getModifiers()); f.setJavaType(node.getType().toString()); childrens.add(f); } return false; } /** {@inheritDoc} */ @Override public boolean visit(MethodDeclaration node) { if (node == astParent) return true; WorkerCodeBlock m = createCodeBlock(BlockTypes.METHOD.getType(), node.getStartPosition(), node.getLength()); m.setModifiers(node.getModifiers()); m.setName(node.getName().getFullyQualifiedName() + getMethodParams(node)); Type returnType = node.getReturnType2(); m.setJavaType(returnType != null ? returnType.toString() : null); childrens.add(m); addChildrens(node, m); return false; } /** {@inheritDoc} */ @Override public boolean visit(AnonymousClassDeclaration node) { if (node == astParent) return true; String name = ""; ASTNode parent = node.getParent(); if (parent instanceof ClassInstanceCreation) { Type type = ((ClassInstanceCreation)parent).getType(); name = ASTNodes.getTypeName(type); } WorkerCodeBlock type = createCodeBlock(BlockTypes.CLASS.getType(), node.getStartPosition(), node.getLength()); type.setName(name); childrens.add(type); addChildrens(node, type); return false; } private WorkerCodeBlock createCodeBlock(String type, int offset, int length) { return WorkerCodeBlock.make().setType(type).setOffset(offset).setLength(length).setChildren(JsoArray.<WorkerCodeBlock>create()); } /** * Returns the string presentation of method's parameters. * * @param method * @return {@link String} method's parameters comma separated */ @SuppressWarnings("unchecked") protected String getMethodParams(MethodDeclaration method) { if (method.parameters().isEmpty()) { return "()"; } else { Iterator<SingleVariableDeclaration> paramsIterator = method.parameters().iterator(); StringBuffer params = new StringBuffer("("); while (paramsIterator.hasNext()) { SingleVariableDeclaration variable = paramsIterator.next(); params.append(variable.getType().toString()); if (paramsIterator.hasNext()) { params.append(", "); } } params.append(")"); return params.toString(); } } } }