content: /*******************************************************************************
   * Copyright (c) 2000, 2009 IBM Corporation and others.
   * 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:
   *     IBM Corporation - initial API and implementation
   *******************************************************************************/
  package org.eclipse.wst.jsdt.internal.ui.compare;
  
  import java.util.Iterator;
  import java.util.Stack;
  
  import org.eclipse.wst.jsdt.core.dom.ASTNode;
  import org.eclipse.wst.jsdt.core.dom.ASTVisitor;
  import org.eclipse.wst.jsdt.core.dom.FieldDeclaration;
  import org.eclipse.wst.jsdt.core.dom.FunctionDeclaration;
  import org.eclipse.wst.jsdt.core.dom.ImportDeclaration;
  import org.eclipse.wst.jsdt.core.dom.Initializer;
  import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
  import org.eclipse.wst.jsdt.core.dom.PackageDeclaration;
  import org.eclipse.wst.jsdt.core.dom.SimpleName;
  import org.eclipse.wst.jsdt.core.dom.SingleVariableDeclaration;
  import org.eclipse.wst.jsdt.core.dom.Type;
  import org.eclipse.wst.jsdt.core.dom.TypeDeclaration;
  import org.eclipse.wst.jsdt.core.dom.VariableDeclarationFragment;
  
  
  class JavaParseTreeBuilder extends ASTVisitor {
  
      private char[] fBuffer;
      private Stack fStack= new Stack();
      private JavaNode fImportContainer;
      private boolean fShowCU;
  
      /*
       * Parsing is performed on the given buffer and the resulting tree (if any)
       * hangs below the given root.
       */
      JavaParseTreeBuilder(JavaNode root, char[] buffer, boolean showCU) {
          fBuffer= buffer;
          fShowCU= showCU;
          fStack.clear();
          fStack.push(root);
      }
  
      public boolean visit(PackageDeclaration node) {
          new JavaNode(getCurrentContainer(), JavaNode.PACKAGE, null, node.getStartPosition(), node.getLength());
          return false;
      }
  
      public boolean visit(JavaScriptUnit node) {
          if (fShowCU)
              push(JavaNode.CU, null, node.getStartPosition(), node.getLength());
          return true;
      }
  
      public void endVisit(JavaScriptUnit node) {
          if (fShowCU)
              pop();
      }
  
      public boolean visit(TypeDeclaration node) {
          push(JavaNode.CLASS, node.getName().toString(), node.getStartPosition(), node.getLength());
          return true;
      }
  
      public void endVisit(TypeDeclaration node) {
          pop();
      }
  
   
      
  
  
      public boolean visit(FunctionDeclaration node) {
          String signature= getSignature(node);
          push(node.isConstructor() ? JavaNode.CONSTRUCTOR : JavaNode.METHOD, signature, node.getStartPosition(), node.getLength());
          return false;
      }
  
      public void endVisit(FunctionDeclaration node) {
          pop();
      }
  
      public boolean visit(Initializer node) {
          push(JavaNode.INIT, getCurrentContainer().getInitializerCount(), node.getStartPosition(), node.getLength());
          return false;
      }
  
      public void endVisit(Initializer node) {
          pop();
      }
  
      public boolean visit(ImportDeclaration node) {
          int s= node.getStartPosition();
          int l= node.getLength();
          int declarationEnd= s + l;
          if (fImportContainer == null)
              fImportContainer= new JavaNode(getCurrentContainer(), JavaNode.IMPORT_CONTAINER, null, s, l);
          String nm= node.getName().toString();
          if (node.isOnDemand())
              nm+= ".*"; //$NON-NLS-1$
          new JavaNode(fImportContainer, JavaNode.IMPORT, nm, s, l);
          fImportContainer.setLength(declarationEnd - fImportContainer.getRange().getOffset() + 1);
          fImportContainer.setAppendPosition(declarationEnd + 2); // FIXME
          return false;
      }
  
      public boolean visit(VariableDeclarationFragment node) {
          String name= getFieldName(node);
          ASTNode parent= node.getParent();
          push(JavaNode.FIELD, name, parent.getStartPosition(), parent.getLength());
          return false;
      }
  
      public void endVisit(VariableDeclarationFragment node) {
          pop();
      }
  
      // private stuff
  
      /**
       * Adds a new JavaNode with the given type and name to the current
       * container.
       */
      private void push(int type, String name, int declarationStart, int length) {
  
          while (declarationStart > 0) {
              char c= fBuffer[declarationStart - 1];
              if (c != ' ' && c != '\t')
                  break;
              declarationStart--;
              length++;
          }
  
          JavaNode node= new JavaNode(getCurrentContainer(), type, name, declarationStart, length);
          if (type == JavaNode.CU)
              node.setAppendPosition(declarationStart + length + 1);
          else
              node.setAppendPosition(declarationStart + length);
  
          fStack.push(node);
      }
  
      /**
       * Closes the current Java node by setting its end position and pops it off
       * the stack.
       */
      private void pop() {
          fStack.pop();
      }
  
      private JavaNode getCurrentContainer() {
          return (JavaNode) fStack.peek();
      }
  
      private String getFieldName(VariableDeclarationFragment node) {
          StringBuffer buffer= new StringBuffer();
          buffer.append(node.getName().toString());
          ASTNode parent= node.getParent();
          if (parent instanceof FieldDeclaration) {
              FieldDeclaration fd= (FieldDeclaration) parent;
              buffer.append(" : "); //$NON-NLS-1$
              buffer.append(getType(fd.getType()));
          }
          return buffer.toString();
      }
  
      private String getSignature(FunctionDeclaration node) {
      	StringBuffer buffer= new StringBuffer();
          SimpleName name = node.getName();
          if (name!=null)
          	buffer.append(name.toString());
       
          buffer.append('(');
          boolean first= true;
          Iterator iterator= node.parameters().iterator();
          while (iterator.hasNext()) {
              Object parameterDecl= iterator.next();
              if (parameterDecl instanceof SingleVariableDeclaration) {
                  SingleVariableDeclaration svd= (SingleVariableDeclaration) parameterDecl;
                  if (!first)
                      buffer.append(", "); //$NON-NLS-1$
                  buffer.append(getType(svd.getType()));
                  if (svd.isVarargs())
                      buffer.append("..."); //$NON-NLS-1$
                  first= false;
              }
          }
          buffer.append(')');
          return buffer.toString();
      }
  
  
      private String getType(Type type) {
          String name= type.toString();
          int pos= name.lastIndexOf('.');
          if (pos >= 0)
              name= name.substring(pos + 1);
          return name;
      }
  }
  