Package org.netbeans.modules.scala.debugger.projects

Source Code of org.netbeans.modules.scala.debugger.projects.EditorContextImpl

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License.  When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package org.netbeans.modules.scala.debugger.projects;

import java.awt.Color;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Caret;
import javax.swing.text.StyledDocument;
import javax.swing.JEditorPane;

import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePathScanner;

import java.util.Collections;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;

import org.netbeans.api.debugger.jpda.LineBreakpoint;

import org.netbeans.api.java.source.CompilationController;

import org.netbeans.modules.parsing.api.ResultIterator;
import org.openide.ErrorManager;
import org.openide.cookies.EditorCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.URLMapper;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.text.Line;
import org.openide.text.NbDocument;
import org.openide.util.Utilities;
import org.openide.util.WeakListeners;

import org.netbeans.spi.debugger.ui.EditorContextDispatcher;

import org.netbeans.editor.JumpList;
import org.netbeans.modules.csl.api.ElementKind;
import org.netbeans.modules.parsing.api.ParserManager;
import org.netbeans.modules.parsing.api.Source;
import org.netbeans.modules.parsing.api.UserTask;
import org.netbeans.modules.parsing.spi.ParseException;
import org.netbeans.modules.scala.core.ScalaParserResult;
import org.netbeans.modules.scala.core.ScalaSourceUtil;
import org.netbeans.spi.debugger.jpda.EditorContext;
import org.netbeans.spi.debugger.jpda.SourcePathProvider;

/**
*
* @author Jan Jancura
* @author Caoyuan Deng
*
* @todo This EditorContextImpl and the EditorContextImpl in debugger.jpda.projects
* should be instanced and get lookuped in org.netbeans.modules.debugger.jpda.EditorContextImpl#getContext,
* but, it seems org.netbeans.api.debugger.Lookup won't init the unloaded modules' META-INFO/debugger/
* services. We have to apply following ugly hacking:
*     1. Add debugger.jpda.projects module as run-dependency of this modules, so,
*        when this module is loaded first, debugger.jpda.projects module will also
*        be loaded.
*     2. Set this module as eager, so, even debugger.jpda.projects is loaded first,
*        this module will also be loaded
*
*/
public class EditorContextImpl extends EditorContext {

    private static String fronting =
            System.getProperty("netbeans.debugger.fronting");
    private PropertyChangeSupport pcs;
    private Map annotationToURL = new HashMap();
    private PropertyChangeListener dispatchListener;
    private EditorContextDispatcher contextDispatcher;

    {
        pcs = new PropertyChangeSupport(this);
        dispatchListener = new EditorContextDispatchListener();
        contextDispatcher = EditorContextDispatcher.getDefault();
        contextDispatcher.addPropertyChangeListener("text/x-scala",
                WeakListeners.propertyChange(dispatchListener, contextDispatcher));
    }

    /**
     * Shows source with given url on given line number.
     *
     * @param url a url of source to be shown
     * @param lineNumber a number of line to be shown
     * @param timeStamp a time stamp to be used
     */
    @Override
    public boolean showSource(String url, int lineNumber, Object timeStamp) {
        Line l = showSourceLine(url, lineNumber, timeStamp);
        if (l != null) {
            addPositionToJumpList(url, l, 0);
        }
        return l != null;
    }

    static Line showSourceLine(String url, int lineNumber, Object timeStamp) {
        Line l = LineTranslations.getTranslations().getLine(url, lineNumber, timeStamp); // false = use original ln
        if (l == null) {
            ErrorManager.getDefault().log(ErrorManager.WARNING,
                    "Show Source: Have no line for URL = " + url + ", line number = " + lineNumber);
            return null;
        }
        if ("true".equalsIgnoreCase(fronting) || Utilities.isWindows()) {
            l.show(Line.SHOW_REUSE);
            l.show(Line.SHOW_TOFRONT); //FIX 47825
        } else {
            l.show(Line.SHOW_REUSE);
        }
        return l;
    }

    /**
     * Shows source with given url on given line number.
     *
     * @param url a url of source to be shown
     * @param lineNumber a number of line to be shown
     * @param timeStamp a time stamp to be used
     */
    public boolean showSource(String url, int lineNumber, int column, int length, Object timeStamp) {
        Line l = LineTranslations.getTranslations().getLine(url, lineNumber, timeStamp); // false = use original ln
        if (l == null) {
            ErrorManager.getDefault().log(ErrorManager.WARNING,
                    "Show Source: Have no line for URL = " + url + ", line number = " + lineNumber);
            return false;
        }
        if ("true".equalsIgnoreCase(fronting) || Utilities.isWindows()) {
            l.show(Line.SHOW_TOFRONT, column); //FIX 47825
        } else {
            l.show(Line.SHOW_GOTO, column);
        }
        addPositionToJumpList(url, l, column);
        return true;
    }

    /** Add the line offset into the jump history */
    private void addPositionToJumpList(String url, Line l, int column) {
        DataObject dataObject = getDataObject(url);
        if (dataObject != null) {
            EditorCookie ec = dataObject.getLookup().lookup(EditorCookie.class);
            if (ec != null) {
                try {
                    StyledDocument doc = ec.openDocument();
                    JEditorPane[] eps = ec.getOpenedPanes();
                    if (eps != null && eps.length > 0) {
                        JumpList.addEntry(eps[0], NbDocument.findLineOffset(doc, l.getLineNumber()) + column);
                    }
                } catch (java.io.IOException ioex) {
                    ErrorManager.getDefault().notify(ioex);
                }
            }
        }
    }

    /**
     * Creates a new time stamp.
     *
     * @param timeStamp a new time stamp
     */
    @Override
    public void createTimeStamp(Object timeStamp) {
        LineTranslations.getTranslations().createTimeStamp(timeStamp);
    }

    /**
     * Disposes given time stamp.
     *
     * @param timeStamp a time stamp to be disposed
     */
    @Override
    public void disposeTimeStamp(Object timeStamp) {
        LineTranslations.getTranslations().disposeTimeStamp(timeStamp);
    }

    /**@Node:
     * the chained annotate method from EditorContextImpl under debug.jpda.projects
     * will also be called, so we do not need add a reduantant annotation
     */
    @Override
    public Object annotate(
            String url,
            int lineNumber,
            String annotationType,
            Object timeStamp) {
        return null;
        //return annotate(url, lineNumber, annotationType, timeStamp, null);
    }
//    public Object annotate (
//        String url,
//        int lineNumber,
//        String annotationType,
//        Object timeStamp,
//        JPDAThread thread
//    ) {
//        Line l =  LineTranslations.getTranslations().getLine (
//            url,
//            lineNumber,
//            (timeStamp instanceof JPDABreakpoint) ? null : timeStamp
//        );
//        if (l == null) return null;
//        Annotation annotation;
//        if (timeStamp instanceof JPDABreakpoint) {
//            annotation = new DebuggerBreakpointAnnotation(annotationType, l, (JPDABreakpoint) timeStamp);
//        } else {
//            annotation = new DebuggerAnnotation (annotationType, l, thread);
//        }
//        annotationToURL.put (annotation, url);
//
//        return annotation;
//    }
//
//    public Object annotate (
//        String url,
//        int startPosition,
//        int endPosition,
//        String annotationType,
//        Object timeStamp
//    ) {
//        AttributeSet attrs;
//        if (EditorContext.CURRENT_LAST_OPERATION_ANNOTATION_TYPE.equals(annotationType)) {
//            attrs = AttributesUtilities.createImmutable(EditorStyleConstants.WaveUnderlineColor, getColor(annotationType));
//        } else {
//            attrs = AttributesUtilities.createImmutable(StyleConstants.Background, getColor(annotationType));
//        }
//        DebuggerAnnotation annotation;
//        try {
//            annotation = new DebuggerAnnotation(annotationType, attrs, startPosition, endPosition,
//                    URLMapper.findFileObject(new URL(url)));
//        } catch (MalformedURLException ex) {
//            RuntimeException rex = new RuntimeException("Bad URL: "+url);
//            rex.initCause(ex);
//            throw rex;
//        }
//        annotationToURL.put (annotation, url);
//
//        return annotation;
//    }

    private static Color getColor(String annotationType) {
        if (annotationType.endsWith("_broken")) {
            annotationType = annotationType.substring(0, annotationType.length() - "_broken".length());
        }
        if (EditorContext.BREAKPOINT_ANNOTATION_TYPE.equals(annotationType)) {
            return new Color(0xFC9D9F);
        } else if (EditorContext.CURRENT_LINE_ANNOTATION_TYPE.equals(annotationType) ||
                EditorContext.CURRENT_OUT_OPERATION_ANNOTATION_TYPE.equals(annotationType)) {
            return new Color(0xBDE6AA);
        } else if (EditorContext.CURRENT_EXPRESSION_CURRENT_LINE_ANNOTATION_TYPE.equals(annotationType)) {
            return new Color(0xE9FFE6); // 0xE3FFD2// 0xD1FFBC
        } else if (EditorContext.CURRENT_LAST_OPERATION_ANNOTATION_TYPE.equals(annotationType)) {
            return new Color(0x99BB8A);
        } else {
            return new Color(0x0000FF);
        }
    }

    /**
     * Removes given annotation.
     *
     * @return true if annotation has been successfully removed
     */
    @Override
    public void removeAnnotation(
            Object a) {
        return;
//        if (a instanceof Collection) {
//            Collection annotations = ((Collection) a);
//            for (Iterator it = annotations.iterator(); it.hasNext(); ) {
//                removeAnnotation((Annotation) it.next());
//            }
//        } else {
//            removeAnnotation((Annotation) a);
//        }
    }

//    private void removeAnnotation(Annotation annotation) {
//        annotation.detach ();
//        annotationToURL.remove (annotation);
//    }
    /**
     * Returns line number given annotation is associated with.
     *
     * @param annotation an annotation, or an array of "url" and new Integer(line number)
     * @param timeStamp a time stamp to be used
     *
     * @return line number given annotation is associated with
     */
    @Override
    public int getLineNumber(
            Object annotation,
            Object timeStamp) {
        if (annotation instanceof LineBreakpoint) {
            // A sort of hack to be able to retrieve the original line.
            LineBreakpoint lb = (LineBreakpoint) annotation;
            return LineTranslations.getTranslations().getOriginalLineNumber(lb, timeStamp);
        }
        /*if (annotation instanceof Object[]) {
        // A sort of hack to be able to retrieve the original line.
        Object[] urlLine = (Object[]) annotation;
        String url = (String) urlLine[0];
        int line = ((Integer) urlLine[1]).intValue();
        return LineTranslations.getTranslations().getOriginalLineNumber(url, line, timeStamp);
        }*/
        Line line;
        if (annotation instanceof DebuggerBreakpointAnnotation) {
            line = ((DebuggerBreakpointAnnotation) annotation).getLine();
        } else {
            line = ((DebuggerAnnotation) annotation).getLine();
        }
        if (timeStamp == null) {
            return line.getLineNumber() + 1;
        }
        String url = (String) annotationToURL.get(annotation);
        Line.Set lineSet = LineTranslations.getTranslations().getLineSet(url, timeStamp);
        return lineSet.getOriginalLineNumber(line) + 1;
    }

    /**
     * Updates timeStamp for gived url.
     *
     * @param timeStamp time stamp to be updated
     * @param url an url
     */
    @Override
    public void updateTimeStamp(Object timeStamp, String url) {
        LineTranslations.getTranslations().updateTimeStamp(timeStamp, url);
    }

    /**
     * Returns number of line currently selected in editor or <code>-1</code>.
     *
     * @return number of line currently selected in editor or <code>-1</code>
     */
    @Override
    public int getCurrentLineNumber() {
        return contextDispatcher.getCurrentLineNumber();
    }

    /**
     * Returns number of line currently selected in editor or <code>-1</code>.
     *
     * @return number of line currently selected in editor or <code>-1</code>
     */
    public int getCurrentOffset() {
        JEditorPane ep = contextDispatcher.getCurrentEditor();
        if (ep == null) {
            return -1;
        }
        Caret caret = ep.getCaret();
        if (caret == null) {
            return -1;
        }
        return caret.getDot();
    }

    /**
     * Returns name of class currently selected in editor or empty string.
     *
     * @return name of class currently selected in editor or empty string
     */
    @Override
    public String getCurrentClassName() {
        String currentClass = getClassName(getCurrentURL(), getCurrentLineNumber());//getCurrentElement(ElementKind.CLASS);
        if (currentClass == null) {
            return "";
        } else {
            return currentClass;
        }
    }

    /**
     * Returns URL of source currently selected in editor or empty string.
     *
     * @return URL of source currently selected in editor or empty string
     */
    @Override
    public String getCurrentURL() {
        return contextDispatcher.getCurrentURLAsString();
    }

    /**
     * Returns name of method currently selected in editor or empty string.
     *
     * @return name of method currently selected in editor or empty string
     */
    @Override
    public String getCurrentMethodName() {
        String currentMethod = getCurrentElement(ElementKind.METHOD);
        if (currentMethod == null) {
            return "";
        } else {
            return currentMethod;
        }
    }

    /**
     * Returns signature of method currently selected in editor or null.
     *
     * @return signature of method currently selected in editor or null
     */
    public String getCurrentMethodSignature() {
        final Element[] elementPtr = new Element[]{null};
        try {
            getCurrentElement(ElementKind.METHOD, elementPtr);
        } catch (final java.awt.IllegalComponentStateException icse) {
            throw new java.awt.IllegalComponentStateException() {

                @Override
                public String getMessage() {
                    icse.getMessage();
                    return createSignature((ExecutableElement) elementPtr[0]);
                }
            };
        }
        if (elementPtr[0] != null) {
            return createSignature((ExecutableElement) elementPtr[0]);
        } else {
            return null;
        }
    }

    /**
     * Returns name of field currently selected in editor or <code>null</code>.
     *
     * @return name of field currently selected in editor or <code>null</code>
     */
    @Override
    public String getCurrentFieldName() {
        String currentField = getCurrentElement(ElementKind.FIELD);
        if (currentField == null) {
            return "";
        } else {
            return currentField;
        }
        //return getSelectedIdentifier ();
    }

    /**
     * Returns identifier currently selected in editor or <code>null</code>.
     *
     * @return identifier currently selected in editor or <code>null</code>
     */
    @Override
    public String getSelectedIdentifier() {
        JEditorPane ep = contextDispatcher.getCurrentEditor();
        if (ep == null) {
            return null;
        }
        String s = ep.getSelectedText();
        if (s == null) {
            return null;
        }
        if (Utilities.isJavaIdentifier(s)) {
            return s;
        }
        return null;
    }

    /**
     * Returns method name currently selected in editor or empty string.
     *
     * @return method name currently selected in editor or empty string
     */
    @Override
    public String getSelectedMethodName() {
        if (SwingUtilities.isEventDispatchThread()) {
            return getSelectedMethodName_();
        } else {
            final String[] mn = new String[1];
            try {
                SwingUtilities.invokeAndWait(new Runnable() {

                    @Override
                    public void run() {
                        mn[0] = getSelectedMethodName_();
                    }
                });
            } catch (InvocationTargetException ex) {
                ErrorManager.getDefault().notify(ex.getTargetException());
            } catch (InterruptedException ex) {
                // interrupted, ignored.
            }
            return mn[0];
        }
    }

    private String getSelectedMethodName_() {
        JEditorPane ep = contextDispatcher.getCurrentEditor();
        if (ep == null) {
            return "";
        }
        StyledDocument doc = (StyledDocument) ep.getDocument();
        if (doc == null) {
            return "";
        }
        int offset = ep.getCaret().getDot();
        String t = null;
//        if ( (ep.getSelectionStart () <= offset) &&
//             (offset <= ep.getSelectionEnd ())
//        )   t = ep.getSelectedText ();
//        if (t != null) return t;

        int line = NbDocument.findLineNumber(
                doc,
                offset);
        int col = NbDocument.findLineColumn(
                doc,
                offset);
        try {
            javax.swing.text.Element lineElem =
                    org.openide.text.NbDocument.findLineRootElement(doc).
                    getElement(line);

            if (lineElem == null) {
                return "";
            }
            int lineStartOffset = lineElem.getStartOffset();
            int lineLen = lineElem.getEndOffset() - lineStartOffset;
            // t contains current line in editor
            t = doc.getText(lineStartOffset, lineLen);

            int identStart = col;
            while (identStart > 0 &&
                    Character.isJavaIdentifierPart(
                    t.charAt(identStart - 1))) {
                identStart--;
            }

            int identEnd = col;
            while (identEnd < lineLen &&
                    Character.isJavaIdentifierPart(t.charAt(identEnd))) {
                identEnd++;
            }
            int i = t.indexOf('(', identEnd);
            if (i < 0) {
                return "";
            }
            if (t.substring(identEnd, i).trim().length() > 0) {
                return "";
            }

            if (identStart == identEnd) {
                return "";
            }
            return t.substring(identStart, identEnd);
        } catch (javax.swing.text.BadLocationException ex) {
            return "";
        }
    }

//    private static TypeElement getTypeElement(CompilationController ci,
//                                              String binaryName,
//                                              String[] classExcludeNames) {
//        ClassScanner cs = new ClassScanner(ci.getTrees(), ci.getElements(),
//                                           binaryName, classExcludeNames);
//        TypeElement te = cs.scan(ci.getCompilationUnit(), null);
//        if (te != null) {
//            return te;
//        } else {
//            return null;
//        }
//    }
    /**
     * Returns line number of given field in given class.
     *
     * @param url the url of file the class is deined in
     * @param className the name of class (or innerclass) the field is
     *                  defined in
     * @param fieldName the name of field
     *
     * @return line number or -1
     */
    @Override
    public int getFieldLineNumber(
            String url,
            final String className,
            final String fieldName) {
        final DataObject dataObject = getDataObject(url);
        if (dataObject == null) {
            return -1;
        }
        return getFieldLineNumber(dataObject.getPrimaryFile(), className, fieldName);
    }

    static int getFieldLineNumber(
            FileObject fo,
            final String className,
            final String fieldName) {
        Source source = Source.create(fo);
        if (source == null) {
            return -1;
        }
        final int[] result = new int[]{-1};

        final DataObject dataObject;
        try {
            dataObject = DataObject.find(fo);
        } catch (DataObjectNotFoundException ex) {
            return -1;
        }
        try {
            ParserManager.parse(Collections.singleton(source), new UserTask() {

                @Override
                public void run(ResultIterator resultIterator) throws Exception {
//                    Elements elms = ci.getElements();
//                    TypeElement classElement = getTypeElement(ci, className, null);
//                    if (classElement == null) {
//                        return;
//                    }
//                    List classMemberElements = elms.getAllMembers(classElement);
//                    for (Iterator it = classMemberElements.iterator(); it.hasNext();) {
//                        Element elm = (Element) it.next();
//                        if (elm.getKind() == ElementKind.FIELD) {
//                            String name = ((VariableElement) elm).getSimpleName().toString();
//                            if (name.equals(fieldName)) {
//                                SourcePositions positions = ci.getTrees().getSourcePositions();
//                                Tree tree = ci.getTrees().getTree(elm);
//                                int pos = (int) positions.getStartPosition(ci.getCompilationUnit(), tree);
//                                EditorCookie editor = (EditorCookie) dataObject.getCookie(EditorCookie.class);
//                                result[0] = NbDocument.findLineNumber(editor.openDocument(), pos) + 1;
//                            //return elms.getSourcePosition(elm).getLine();
//                            }
//                        }
//                    }
                }
            });
        } catch (ParseException ex) {
            ErrorManager.getDefault().notify(ex);
            return -1;
        }
        return result[0];
        /*
        CompilationUnitTree cutree = ci.getTree();
        if (cutree == null) return -1;
        List typeDecls = cutree.getTypeDecls();
        ClassTree ctree = findClassTree(typeDecls, className);
         */
        /*
        Elements elms = ci.getElements();
        SourceCookie.Editor sc = (SourceCookie.Editor) dataObject.getCookie
        (SourceCookie.Editor.class);
        if (sc == null) return -1;
        sc.open ();
        StyledDocument sd = sc.getDocument ();
        if (sd == null) return -1;
        ClassElement[] classes = sc.getSource ().getAllClasses ();
        FieldElement fe = null;
        int i, k = classes.length;
        for (i = 0; i < k; i++)
        if (classes [i].getName ().getFullName ().equals (className)) {
        fe = classes [i].getField (Identifier.create (fieldName));
        break;
        }
        if (fe == null) return -1;
        int position = sc.sourceToText (fe).getStartOffset ();
        return NbDocument.findLineNumber (sd, position) + 1;
         */
    }

    /**
     * Returns line number of given method in given class.
     *
     * @param url the url of file the class is deined in
     * @param className the name of class (or innerclass) the method is
     *                  defined in
     * @param methodName the name of method
     * @param methodSignature the JNI-style signature of the method.
     *        If <code>null</code>, then the first method found is returned.
     *
     * @return line number or -1
     */
    @Override
    public int getMethodLineNumber(
            String url,
            final String className,
            final String methodName,
            final String methodSignature) {
        final DataObject dataObject = getDataObject(url);
        if (dataObject == null) {
            return -1;
        }
        int[] lns = getMethodLineNumbers(dataObject.getPrimaryFile(), className, null, methodName, methodSignature);
        if (lns.length == 0) {
            return -1;
        } else {
            return lns[0];
        }
    }

    static int[] getMethodLineNumbers(
            FileObject fo,
            final String className,
            final String[] classExcludeNames,
            final String methodName,
            final String methodSignature) {
        Source source = Source.create(fo);
        if (source == null) {
            return new int[]{};
        }
        final List<Integer> result = new ArrayList<Integer>();

        final DataObject dataObject;
        try {
            dataObject = DataObject.find(fo);
        } catch (DataObjectNotFoundException ex) {
            return new int[]{};
        }
        try {
            ParserManager.parse(Collections.singleton(source), new UserTask() {

                @Override
                public void run(ResultIterator resultIterator) throws Exception {
//                    TypeElement classElement = getTypeElement(ci, className, classExcludeNames);
//                    if (classElement == null) {
//                        return;
//                    }
//                    List classMemberElements = ci.getElements().getAllMembers(classElement);
//                    for (Iterator it = classMemberElements.iterator(); it.hasNext();) {
//                        Element elm = (Element) it.next();
//                        if (elm.getKind() == ElementKind.METHOD || elm.getKind() == ElementKind.CONSTRUCTOR) {
//                            String name;
//                            if (elm.getKind() == ElementKind.CONSTRUCTOR && !methodName.equals("<init>")) {
//                                name = elm.getEnclosingElement().getSimpleName().toString();
//                            } else {
//                                name = elm.getSimpleName().toString();
//                            }
//                            if (name.equals(methodName)) {
//                                if (methodSignature == null || egualMethodSignatures(methodSignature, createSignature((ExecutableElement) elm))) {
//                                    SourcePositions positions = ci.getTrees().getSourcePositions();
//                                    Tree tree = ci.getTrees().getTree(elm);
//                                    int pos = (int) positions.getStartPosition(ci.getCompilationUnit(), tree);
//                                    EditorCookie editor = (EditorCookie) dataObject.getCookie(EditorCookie.class);
//                                    result.add(new Integer(NbDocument.findLineNumber(editor.openDocument(), pos) + 1));
//                                }
//                            }
//                        }
//                    }
                }
            });
        } catch (ParseException ex) {
            ErrorManager.getDefault().notify(ex);
            return new int[]{};
        }
        int[] resultArray = new int[result.size()];
        for (int i = 0; i < resultArray.length; i++) {
            resultArray[i] = result.get(i).intValue();
        }
        return resultArray;
    }

    private static boolean egualMethodSignatures(String s1, String s2) {
        int i = s1.lastIndexOf(")");
        if (i > 0) {
            s1 = s1.substring(0, i);
        }
        i = s2.lastIndexOf(")");
        if (i > 0) {
            s2 = s2.substring(0, i);
        }
        return s1.equals(s2);
    }

    /** @return { "method name", "method signature", "enclosing class name" }
     */
    @Override
    public String[] getCurrentMethodDeclaration() {
        FileObject fo = contextDispatcher.getCurrentFile();
        if (fo == null) {
            return null;
        }
        JEditorPane ep = contextDispatcher.getCurrentEditor();
        Source source = Source.create(fo);
        if (source == null) {
            return null;
        }
        final int currentOffset = (ep == null) ? 0 : ep.getCaretPosition();
        final String[] currentMethodPtr = new String[]{null, null, null};
        final Future<Void> scanFinished;
//        try {
//            scanFinished = js.runWhenScanFinished(new CancellableTask<CompilationController>() {
//
//                public void cancel() {
//                }
//
//                public void run(CompilationController ci) throws Exception {
//                    if (ci.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) {//TODO: ELEMENTS_RESOLVED may be sufficient
//                        ErrorManager.getDefault().log(ErrorManager.WARNING,
//                                "Unable to resolve " + ci.getFileObject() + " to phase " + Phase.RESOLVED + ", current phase = " + ci.getPhase() +
//                                "\nFree memory = " + Runtime.getRuntime().freeMemory());
//                        return;
//                    }
//                    int offset = currentOffset;
//                    //AstScope scope = ci.getTreeUtilities().scopeFor(offset);
//                    String text = ci.getText();
//                    int l = text.length();
//                    char c = 0;
//                    while (offset < l && (c = text.charAt(offset)) != '(' && c != ')' && c != '\n' && c != '\r') {
//                        offset++;
//                    }
//                    if (offset >= l) {
//                        return;
//                    }
//                    if (c == '(') {
//                        offset--;
//                    }
//
//                    Tree tree = ci.getTreeUtilities().pathFor(offset).getLeaf();
//                    if (tree.getKind() == Tree.Kind.METHOD) {
//                        Element el = ci.getTrees().getElement(ci.getTrees().getPath(ci.getCompilationUnit(), tree));
//
//                        //Element el = ci.getTrees().getElement(ci.getTreeUtilities().pathFor(offset));
//                        if (el != null && (el.getKind() == ElementKind.METHOD || el.getKind() == ElementKind.CONSTRUCTOR)) {
//                            currentMethodPtr[0] = el.getSimpleName().toString();
//                            if (currentMethodPtr[0].equals("<init>")) {
//                                // The constructor name is the class name:
//                                currentMethodPtr[0] = el.getEnclosingElement().getSimpleName().toString();
//                            }
//                            currentMethodPtr[1] = createSignature((ExecutableElement) el);
//                            Element enclosingClassElement = el;
//                            TypeElement te = null; // SourceUtils.getEnclosingTypeElement(el);
//                            while (enclosingClassElement != null) {
//                                ElementKind kind = enclosingClassElement.getKind();
//                                if (kind == ElementKind.CLASS || kind == ElementKind.INTERFACE) {
//                                    te = (TypeElement) enclosingClassElement;
//                                    break;
//                                } else {
//                                    enclosingClassElement = enclosingClassElement.getEnclosingElement();
//                                }
//                            }
//                            if (te != null) {
//                                currentMethodPtr[2] = ElementUtilities.getBinaryName(te);
//                            }
//                        }
//                    }
//                }
//            }, true);
//            if (!scanFinished.isDone()) {
//                if (java.awt.EventQueue.isDispatchThread()) {
//                    // Hack: We should not wait for the scan in AWT!
//                    //       Thus we throw IllegalComponentStateException,
//                    //       which returns the data upon call to getMessage()
//                    throw new java.awt.IllegalComponentStateException() {
//
//                        private void waitScanFinished() {
//                            try {
//                                scanFinished.get();
//                            } catch (InterruptedException iex) {
//                            } catch (java.util.concurrent.ExecutionException eex) {
//                                ErrorManager.getDefault().notify(eex);
//                            }
//                        }
//
//                        public String getMessage() {
//                            waitScanFinished();
//                            return currentMethodPtr[0];
//                        }
//
//                        public String getLocalizedMessage() {
//                            waitScanFinished();
//                            return currentMethodPtr[1];
//                        }
//                    };
//                } else {
//                    try {
//                        scanFinished.get();
//                    } catch (InterruptedException iex) {
//                        return null;
//                    } catch (java.util.concurrent.ExecutionException eex) {
//                        ErrorManager.getDefault().notify(eex);
//                        return null;
//                    }
//                }
//            }
//        } catch (IOException ioex) {
//            ErrorManager.getDefault().notify(ioex);
//            return null;
//        }
//        if (currentMethodPtr[0] != null) {
//            return currentMethodPtr;
//        } else {
//            return null;
//        }
        return null;
    }

    private static String createSignature(ExecutableElement elm) {
        StringBuilder signature = new StringBuilder("(");
        for (VariableElement param : elm.getParameters()) {
            String paramType = param.asType().toString();
            signature.append(getSignature(paramType));
        }
        signature.append(')');
        String returnType = elm.getReturnType().toString();
        signature.append(getSignature(returnType));
        return signature.toString();
    }

    private static String getSignature(String javaType) {
        if (javaType.equals("boolean")) {
            return "Z";
        } else if (javaType.equals("byte")) {
            return "B";
        } else if (javaType.equals("char")) {
            return "C";
        } else if (javaType.equals("short")) {
            return "S";
        } else if (javaType.equals("int")) {
            return "I";
        } else if (javaType.equals("long")) {
            return "J";
        } else if (javaType.equals("float")) {
            return "F";
        } else if (javaType.equals("double")) {
            return "D";
        } else if (javaType.endsWith("[]")) {
            return "[" + getSignature(javaType.substring(0, javaType.length() - 2));
        } else {
            return "L" + javaType.replace('.', '/') + ";";
        }
    }

    /**
     * Returns binary class name for given url and line number or null.
     *
     * @param url a url
     * @param lineNumber a line number
     *
     * @return binary class name for given url and line number or null
     */
    @Override
    public String getClassName(String url, final int lineNumber) {
        DataObject dataObject = getDataObject(url);
        if (dataObject == null) {
            return null;
        }
        FileObject fo = dataObject.getPrimaryFile();
        if (fo == null) {
            return null;
        }
        Source source = Source.create(fo);
        if (source == null) {
            return "";
        }
        if (!"text/x-scala".equals(fo.getMIMEType())) {
            /** Should return null instead of "" here,
             * @see org.netbeans.modules.debugger.jpda.EditorContextBridge#CompoundContextProvider#getClassName
             * @notice this has been fixed in main's rev: 30100e497ae4
             */
            return null;
        }
        EditorCookie ec = (EditorCookie) dataObject.getLookup().lookup(EditorCookie.class);
        if (ec == null) {
            return "";
        }
        StyledDocument doc;
        try {
            doc = ec.openDocument();
        } catch (IOException ex) {
            ErrorManager.getDefault().notify(ex);
            return "";
        }
        try {
            final int offset = NbDocument.findLineOffset(doc, lineNumber - 1);
            final String[] result = new String[]{""};

            ParserManager.parse(Collections.singleton(source), new UserTask() {

                @Override
                public void run(ResultIterator ri) throws Exception {
                    ScalaParserResult pResult = (ScalaParserResult) ri.getParserResult(offset);
                    String clzFqn = ScalaSourceUtil.getBinaryClassName(pResult, lineNumber);

                    if (clzFqn == null) {
                        ErrorManager.getDefault().log(
                                ErrorManager.WARNING,
                                "No enclosing class for " + pResult.getSnapshot().getSource().getFileObject() + ", offset = " + offset);
                        result[0] = "";
                    } else {
                        result[0] = clzFqn;
                    }
                }
            });
            return result[0];
        } catch (ParseException ex) {
            ErrorManager.getDefault().notify(ex);
            return "";
        } catch (IndexOutOfBoundsException ioobex) {
            //XXX: log the exception?
            return null;
        }
        /*
        SourceCookie.Editor sc = (SourceCookie.Editor) dataObject.getCookie
        (SourceCookie.Editor.class);
        if (sc == null) return null;
        StyledDocument sd = null;
        try {
        sd = sc.openDocument ();
        } catch (IOException ex) {
        }
        if (sd == null) return null;
        int offset;
        try {
        offset = NbDocument.findLineOffset (sd, lineNumber - 1);
        } catch (IndexOutOfBoundsException ioobex) {
        return null;
        }
        Element element = sc.findElement (offset);

        if (element == null) return "";
        if (element instanceof ClassElement)
        return getClassName ((ClassElement) element);
        if (element instanceof ConstructorElement)
        return getClassName (((ConstructorElement) element).getDeclaringClass ());
        if (element instanceof FieldElement)
        return getClassName (((FieldElement) element).getDeclaringClass ());
        if (element instanceof InitializerElement)
        return getClassName (((InitializerElement) element).getDeclaringClass());
        return "";
         */
    }

    @Override
    public Operation[] getOperations(String url, final int lineNumber,
            final BytecodeProvider bytecodeProvider) {
        DataObject dataObject = getDataObject(url);
        if (dataObject == null) {
            return null;
        }
        FileObject fileObject = dataObject.getPrimaryFile();
        if (fileObject == null) {
            return null;
        }
        if (!"text/x-scala".equals(fileObject.getMIMEType())) {
            return null;
        }

        // at the following step, do not return null to avoid another EditorContextImpl to process
        final Operation ops[][] = new Operation[1][];
        Source source = Source.create(dataObject.getPrimaryFile());
        if (source == null) {
            return ops[0];
        }
        EditorCookie ec = (EditorCookie) dataObject.getLookup().lookup(EditorCookie.class);
        if (ec == null) {
            return ops[0];
        }
        final StyledDocument doc;
        try {
            doc = ec.openDocument();
        } catch (IOException ex) {
            ErrorManager.getDefault().notify(ex);
            return ops[0];
        }
        final int offset = findLineOffset(doc, (int) lineNumber);
        try {
            ParserManager.parse(Collections.singleton(source), new UserTask() {

                @Override
                public void run(ResultIterator resultIterator) throws Exception {
//                    AstScope scope = ci.getTreeUtilities().scopeFor(offset);
//                    Element method = scope.getEnclosingMethod();
//                    if (method == null) {
//                        ops[0] = new Operation[]{};
//                        return;
//                    }
//                    Tree methodTree = ci.getTrees().getTree(method);
//                    CompilationUnitTree cu = ci.getCompilationUnit();
//                    ExpressionScanner scanner = new ExpressionScanner(lineNumber, cu, ci.getTrees().getSourcePositions());
//                    ExpressionScanner.ExpressionsInfo info = new ExpressionScanner.ExpressionsInfo();
//                    List<Tree> expTrees = methodTree.accept(scanner, info);
//
//                    //com.sun.source.tree.ExpressionTree expTree = scanner.getExpressionTree();
//                    if (expTrees == null || expTrees.size() == 0) {
//                        ops[0] = new Operation[]{};
//                        return;
//                    }
//                    //Tree[] expTrees = expTreeSet.toArray(new Tree[0]);
//                    SourcePositions sp = ci.getTrees().getSourcePositions();
//                    int treeStartLine =
//                            (int) cu.getLineMap().getLineNumber(
//                            sp.getStartPosition(cu, expTrees.get(0)));
//                    int treeEndLine =
//                            (int) cu.getLineMap().getLineNumber(
//                            sp.getEndPosition(cu, expTrees.get(expTrees.size() - 1)));
//
//                    int[] indexes = bytecodeProvider.indexAtLines(treeStartLine, treeEndLine);
//                    if (indexes == null) {
//                        return;
//                    }
//                    Map<Tree, Operation> nodeOperations = new HashMap<Tree, Operation>();
//                    ops[0] = AST2Bytecode.matchSourceTree2Bytecode(
//                            cu,
//                            ci,
//                            expTrees, info, bytecodeProvider.byteCodes(),
//                            indexes,
//                            bytecodeProvider.constantPool(),
//                            new OperationCreationDelegateImpl(),
//                            nodeOperations);
//                    if (ops[0] != null) {
//                        assignNextOperations(methodTree, cu, ci, bytecodeProvider, expTrees, info, nodeOperations);
//                    }
                }
            });
        } catch (ParseException ex) {
            ErrorManager.getDefault().notify(ex);
            return null;
        }
        return ops[0];
    }

    private void assignNextOperations(Tree methodTree,
            CompilationUnitTree cu,
            CompilationController ci,
            BytecodeProvider bytecodeProvider,
            List<Tree> treeNodes,
            ExpressionScanner.ExpressionsInfo info,
            Map<Tree, Operation> nodeOperations) {
        int length = treeNodes.size();
        for (int treeIndex = 0; treeIndex < length; treeIndex++) {
            Tree node = treeNodes.get(treeIndex);
            Set<Tree> nextNodes = info.getNextExpressions(node);
            if (nextNodes != null) {
                EditorContext.Operation op = nodeOperations.get(node);
                if (op == null) {
                    for (int backIndex = treeIndex - 1; backIndex >= 0; backIndex--) {
                        node = treeNodes.get(backIndex);
                        op = nodeOperations.get(node);
                        if (op != null) {
                            break;
                        }
                    }
                }
                if (op != null) {
//                    for (Tree t : nextNodes) {
//                        EditorContext.Operation nextOp = nodeOperations.get(t);
//                        if (nextOp == null) {
//                            SourcePositions sp = ci.getTrees().getSourcePositions();
//                            int treeStartLine =
//                                    (int) cu.getLineMap().getLineNumber(
//                                    sp.getStartPosition(cu, t));
//                            ExpressionScanner scanner = new ExpressionScanner(treeStartLine, cu, ci.getTrees().getSourcePositions());
//                            ExpressionScanner.ExpressionsInfo newInfo = new ExpressionScanner.ExpressionsInfo();
//                            List<Tree> newExpTrees = methodTree.accept(scanner, newInfo);
//                            treeStartLine =
//                                    (int) cu.getLineMap().getLineNumber(
//                                    sp.getStartPosition(cu, newExpTrees.get(0)));
//                            int treeEndLine =
//                                    (int) cu.getLineMap().getLineNumber(
//                                    sp.getEndPosition(cu, newExpTrees.get(newExpTrees.size() - 1)));
//
//                            int[] indexes = bytecodeProvider.indexAtLines(treeStartLine, treeEndLine);
//                            Map<Tree, Operation> newNodeOperations = new HashMap<Tree, Operation>();
//                            Operation[] newOps = AST2Bytecode.matchSourceTree2Bytecode(
//                                    cu,
//                                    ci,
//                                    newExpTrees, newInfo, bytecodeProvider.byteCodes(),
//                                    indexes,
//                                    bytecodeProvider.constantPool(),
//                                    new OperationCreationDelegateImpl(),
//                                    newNodeOperations);
//                            nextOp = newNodeOperations.get(t);
//                            if (nextOp == null) {
//                                // Next operation not found
//                                System.err.println("Next operation not found!");
//                                continue;
//                            }
//                        }
//                        addNextOperationTo(op, nextOp);
//                    }
                }
            }
        }

    }

    /** return the offset of the first non-whitespace character on the line,
    or -1 when the line does not exist
     */
    private static int findLineOffset(StyledDocument doc, int lineNumber) {
        int offset;
        try {
            offset = NbDocument.findLineOffset(doc, lineNumber - 1);
            int offset2 = NbDocument.findLineOffset(doc, lineNumber);
            try {
                String lineStr = doc.getText(offset, offset2 - offset);
                for (int i = 0; i < lineStr.length(); i++) {
                    if (!Character.isWhitespace(lineStr.charAt(i))) {
                        offset += i;
                        break;
                    }
                }
            } catch (BadLocationException ex) {
                // ignore
            }
        } catch (IndexOutOfBoundsException ioobex) {
            return -1;
        }
        return offset;
    }

    @Override
    public MethodArgument[] getArguments(String url, final Operation operation) {
        DataObject dataObject = getDataObject(url);
        if (dataObject == null) {
            return null;
        }
        FileObject fo = dataObject.getPrimaryFile();
        if (fo == null) {
            return null;
        }
        Source source = Source.create(fo);
        if (source == null) {
            return null;
        }
        final MethodArgument args[][] = new MethodArgument[1][];
        try {
            ParserManager.parse(Collections.singleton(source), new UserTask() {

                @Override
                public void run(ResultIterator resultIterator) throws Exception {
                    int offset = operation.getMethodEndPosition().getOffset();
//                    AstScope scope = ci.getTreeUtilities().scopeFor(offset);
//                    Element method = scope.getEnclosingMethod();
//                    if (method == null) {
//                        return;
//                    }
//                    Tree methodTree = ci.getTrees().getTree(method);
//                    CompilationUnitTree cu = ci.getCompilationUnit();
//                    MethodArgumentsScanner scanner =
//                            new MethodArgumentsScanner(offset, cu, ci.getTrees().getSourcePositions(), true,
//                            new OperationCreationDelegateImpl());
//                    args[0] = methodTree.accept(scanner, null);
//                    args[0] = scanner.getArguments();
                }
            });
        } catch (ParseException ex) {
            ErrorManager.getDefault().notify(ex);
            return null;
        }
        return args[0];
    }

    @Override
    public MethodArgument[] getArguments(String url, final int methodLineNumber) {
        DataObject dataObject = getDataObject(url);
        if (dataObject == null) {
            return null;
        }
        FileObject fo = dataObject.getPrimaryFile();
        if (fo == null) {
            return null;
        }
        Source source = Source.create(fo);
        if (source == null) {
            return null;
        }
        EditorCookie ec = (EditorCookie) dataObject.getLookup().lookup(EditorCookie.class);
        if (ec == null) {
            return null;
        }
        final StyledDocument doc;
        try {
            doc = ec.openDocument();
        } catch (IOException ex) {
            ErrorManager.getDefault().notify(ex);
            return null;
        }
        final int offset = findLineOffset(doc, methodLineNumber);
        final MethodArgument args[][] = new MethodArgument[1][];
        try {
            ParserManager.parse(Collections.singleton(source), new UserTask() {

                @Override
                public void run(ResultIterator resultIterator) throws Exception {
//                    AstScope scope = ci.getTreeUtilities().scopeFor(offset);
//                    Element clazz = scope.getEnclosingClass();
//                    if (clazz == null) {
//                        return;
//                    }
//                    Tree methodTree = ci.getTrees().getTree(clazz);
//                    CompilationUnitTree cu = ci.getCompilationUnit();
//                    MethodArgumentsScanner scanner =
//                            new MethodArgumentsScanner(methodLineNumber, cu, ci.getTrees().getSourcePositions(), false,
//                            new OperationCreationDelegateImpl());
//                    args[0] = methodTree.accept(scanner, null);
//                    args[0] = scanner.getArguments();
                }
            });
        } catch (ParseException ex) {
            ErrorManager.getDefault().notify(ex);
            return null;
        }
        return args[0];
    }

    /**
     * Returns list of imports for given source url.
     *
     * @param url the url of source file
     *
     * @return list of imports for given source url
     */
    public String[] getImports(
            String url) {
        DataObject dataObject = getDataObject(url);
        if (dataObject == null) {
            return new String[0];
        }
        FileObject fo = dataObject.getPrimaryFile();
        if (fo == null) {
            return new String[0];
        }
        Source source = Source.create(fo);
        if (source == null) {
            return new String[0];
        }
        final List<String> imports = new ArrayList<String>();
        try {
            ParserManager.parse(Collections.singleton(source), new UserTask() {

                @Override
                public void run(ResultIterator resultIterator) throws Exception {
//                    List importDecl = ci.getCompilationUnit().getImports();
//                    int i = 0;
//                    for (Iterator it = importDecl.iterator(); it.hasNext(); i++) {
//                        ImportTree itree = (ImportTree) it.next();
//                        String importStr = itree.getQualifiedIdentifier().toString();
//                        imports.add(importStr);
//                    }
                }
            });
        } catch (ParseException ex) {
            ErrorManager.getDefault().notify(ex);
            return new String[0];
        }
        return imports.toArray(new String[0]);
        /*
        SourceCookie.Editor sc = (SourceCookie.Editor) dataObject.getCookie
        (SourceCookie.Editor.class);
        if (sc == null) return new String [0];
        Import[] is = sc.getSource ().getImports ();
        int i, k = is.length;
        String[] is2 = new String [k];
        for (i = 0; i < k; i++)
        is2 [i] = is [i].getIdentifier ().getFullName ();
        return is2;
         */
    }

//    private JavaSource getJavaSource(SourcePathProvider sp) {
//        String[] roots = sp.getOriginalSourceRoots();
//        List<FileObject> sourcePathFiles = new ArrayList<FileObject>();
//        for (String root : roots) {
//            FileObject fo = FileUtil.toFileObject(new java.io.File(root));
//            if (fo != null && FileUtil.isArchiveFile(fo)) {
//                fo = FileUtil.getArchiveRoot(fo);
//            }
//            sourcePathFiles.add(fo);
//        }
//        ClassPath bootPath = ClassPathSupport.createClassPath(new FileObject[]{});
//        ClassPath classPath = ClassPathSupport.createClassPath(new FileObject[]{});
//        ClassPath sourcePath = ClassPathSupport.createClassPath(sourcePathFiles.toArray(new FileObject[]{}));
//        return JavaSource.create(ClasspathInfo.create(bootPath, classPath, sourcePath), new FileObject[]{});
//    }
    /**
     * Parse the expression into AST tree and traverse is via the provided visitor.
     *
     * @return the visitor value or <code>null</code>.
     */
    public <R, D> R parseExpression(final String expression, String url, final int line,
            final TreePathScanner<R, D> visitor, final D context,
            final SourcePathProvider sp) {
        DataObject dataObject = getDataObject(url);
        if (dataObject == null) {
            return null;
        }
        FileObject fo = dataObject.getPrimaryFile();
        if (fo == null) {
            return null;
        }
        if (!"text/x-scala".equals(fo.getMIMEType())) {
            return null;
        }
        /** @todo*/
        final R[] retValue = (R[]) new Object[]{null};
        return retValue[0];
//        if (js == null) {
//            js = getJavaSource(sp);
//        }
//        final R[] retValue = (R[]) new Object[]{null                };
//        try {
//            js.runUserActionTask(new Task<CompilationController>() {
//
//                public void run(CompilationController ci) throws Exception {
//                    if (ci.toPhase(Phase.PARSED).compareTo(Phase.PARSED) < 0) {
//                        return;
//                    }
//                    AstScope scope = null;
//                    int offset = 0;
//                    StyledDocument doc = (StyledDocument) ci.getDocument();
//                    if (doc != null) {
//                        offset = findLineOffset(doc, line);
//                        scope = ci.getTreeUtilities().scopeFor(offset);
//                    }
//                    SourcePositions[] sourcePtr = new SourcePositions[]{null                    };
//                    Tree tree = ci.getTreeUtilities().parseExpression(
//                            expression,
//                            sourcePtr);
//                    if (scope != null) {
//                        ci.getTreeUtilities().attributeTree(tree, scope);
//                    }
//                    try {
//                        //context.setTrees(ci.getTrees());
//                        java.lang.reflect.Method setTreesMethod =
//                                context.getClass().getMethod("setTrees", new Class[]{Trees.class                                });
//                        setTreesMethod.invoke(context, ci.getTrees());
//                    } catch (Exception ex) {
//                    }
//                    try {
//                        //context.setCompilationUnit(ci.getCompilationUnit());
//                        java.lang.reflect.Method setCompilationUnitMethod =
//                                context.getClass().getMethod("setCompilationUnit", new Class[]{CompilationUnitTree.class                                });
//                        setCompilationUnitMethod.invoke(context, ci.getCompilationUnit());
//                    } catch (Exception ex) {
//                    }
//                    TreePath treePath = null;
//                    try {
//                        //context.setTrees(ci.getTrees());
//                        java.lang.reflect.Method setTreePathMethod =
//                                context.getClass().getMethod("setTreePath", new Class[]{TreePath.class                                });
//                        if (doc != null) {
//                            treePath = ci.getTreeUtilities().pathFor(offset);
//                            treePath = new TreePath(treePath, tree);
//                            setTreePathMethod.invoke(context, treePath);
//                        }
//                    } catch (Exception ex) {
//                        return;
//                    }
//                    if (treePath != null) {
//                        retValue[0] = visitor.scan(treePath, context);
//                    } else {
//                        retValue[0] = tree.accept(visitor, context);
//                    }
//                }
//            }, true);
//            /*
//            js.runModificationTask(new Task<WorkingCopy>() {
//            public void run(WorkingCopy wc) throws Exception {
//            if (wc.toPhase(Phase.PARSED).compareTo(Phase.PARSED) < 0)
//            return;
//            int offset = findLineOffset((StyledDocument) wc.getDocument(), line);
//            AstScope scope = wc.getTreeUtilities().scopeFor(offset);
//            Element clazz = scope.getEnclosingClass();
//            if (clazz == null) {
//            return ;
//            }
//            ExpressionTree expressionTree = wc.getTreeUtilities().parseExpression(
//            expression,
//            new SourcePositions[] { wc.getTrees().getSourcePositions() }
//            );
//            wc.getTreeUtilities().attributeTree(expressionTree, scope);
//            TreeMaker tm = wc.getTreeMaker();
//            ExpressionStatementTree est = tm.ExpressionStatement(expressionTree);
//            addStatement(tm, wc.getTrees(), wc.getTreeUtilities().pathFor(offset), offset, est);
//            //wc.rewrite(est, est);
//            }
//            });
//             */
//            return retValue[0];
//        } catch (IOException ioex) {
//            ErrorManager.getDefault().notify(ioex);
//            return null;
//        }
    }
    /*
    private static void addStatement(TreeMaker tm, Trees trees, TreePath positionPath, int offset, StatementTree statement) {
    SourcePositions sourcePositions = trees.getSourcePositions();
    CompilationUnitTree root = positionPath.getCompilationUnit();
    Tree newTree = null;
    for (java.util.Iterator<Tree> it = positionPath.iterator(); it.hasNext(); ) {
    Tree element = it.next();
    if (element.getKind() == Tree.Kind.BLOCK && newTree == null) {
    BlockTree block = (BlockTree) element;
    List<? extends StatementTree> statements = block.getStatements();
    int index = 0;
    for (StatementTree st : statements) {
    if (sourcePositions.getStartPosition(root, st) >= offset) {
    break;
    }
    index++;
    }
    newTree = tm.insertBlockStatement(block, index, statement);
    } else {
   
    }
    }
    }
     */

    /**
     * Adds a property change listener.
     *
     * @param l the listener to add
     */
    public void addPropertyChangeListener(PropertyChangeListener l) {
        pcs.addPropertyChangeListener(l);
    }

    /**
     * Removes a property change listener.
     *
     * @param l the listener to remove
     */
    public void removePropertyChangeListener(PropertyChangeListener l) {
        pcs.removePropertyChangeListener(l);
    }

    /**
     * Adds a property change listener.
     *
     * @param propertyName the name of property
     * @param l the listener to add
     */
    public void addPropertyChangeListener(
            String propertyName,
            PropertyChangeListener l) {
        pcs.addPropertyChangeListener(propertyName, l);
    }

    /**
     * Removes a property change listener.
     *
     * @param propertyName the name of property
     * @param l the listener to remove
     */
    public void removePropertyChangeListener(
            String propertyName,
            PropertyChangeListener l) {
        pcs.removePropertyChangeListener(propertyName, l);
    }

    // private helper methods ..................................................
//    public void fileChanged (FileEvent fe) {
//  pcs.firePropertyChange (PROP_LINE_NUMBER, null, null);
//    }
//   
//    public void fileDeleted (FileEvent fe) {}
//    public void fileAttributeChanged (org.openide.filesystems.FileAttributeEvent fe) {}
//    public void fileDataCreated (FileEvent fe) {}
//    public void fileFolderCreated (FileEvent fe) {}
//    public void fileRenamed (org.openide.filesystems.FileRenameEvent fe) {}
    private String getCurrentElement(ElementKind kind) {
        return getCurrentElement(kind, null);
    }

    /** throws IllegalComponentStateException when can not return the data in AWT. */
    private String getCurrentElement(final ElementKind kind, final Element[] elementPtr)
            throws java.awt.IllegalComponentStateException {
        FileObject fo = contextDispatcher.getCurrentFile();
        if (fo == null) {
            return null;
        }
        JEditorPane ep = contextDispatcher.getCurrentEditor();

        Source source = Source.create(fo);
        if (source == null) {
            return null;
        }
        final int currentOffset;
        final String selectedIdentifier;
        if (ep != null) {
            String s = ep.getSelectedText();
            currentOffset = ep.getCaretPosition();
            if (ep.getSelectionStart() > currentOffset || ep.getSelectionEnd() < currentOffset) {
                s = null; // caret outside of the selection
            }
            if (s != null && Utilities.isJavaIdentifier(s)) {
                selectedIdentifier = s;
            } else {
                selectedIdentifier = null;
            }
        } else {
            selectedIdentifier = null;
            currentOffset = 0;
        }

        final String[] currentElementPtr = new String[]{null};
        final Future<Void> scanFinished;
//        try {
//            scanFinished = js.runWhenScanFinished(new CancellableTask<CompilationController>() {
//
//                public void cancel() {
//                }
//
//                public void run(CompilationController ci) throws Exception {
//                    if (ci.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) {//TODO: ELEMENTS_RESOLVED may be sufficient
//                        ErrorManager.getDefault().log(ErrorManager.WARNING,
//                                "Unable to resolve " + ci.getFileObject() + " to phase " + Phase.RESOLVED + ", current phase = " + ci.getPhase() +
//                                "\nFree memory = " + Runtime.getRuntime().freeMemory());
//                        return;
//                    }
//                    Element el = null;
//                    if (kind == ElementKind.CLASS) {
//                        boolean isMemberClass = false;
//                        if (selectedIdentifier != null) {
//                            Tree tree = ci.getTreeUtilities().pathFor(currentOffset).getLeaf();
//                            if (tree.getKind() == Tree.Kind.MEMBER_SELECT) {
//                                MemberSelectTree mst = (MemberSelectTree) tree;
//                                el = ci.getTrees().getElement(ci.getTrees().getPath(ci.getCompilationUnit(), mst.getExpression()));
//                                TypeMirror tm = el.asType();
//                                if (tm.getKind().equals(TypeKind.DECLARED)) {
//                                    currentElementPtr[0] = tm.toString();
//                                    isMemberClass = true;
//                                }
//                            }
//                        }
//                        if (!isMemberClass) {
//                            TreePath currentPath = ci.getTreeUtilities().pathFor(currentOffset);
//                            Tree tree = currentPath.getLeaf();
//                            TypeElement te;
//                            if (tree.getKind() == Tree.Kind.CLASS) {
//                                te = (TypeElement) ci.getTrees().getElement(currentPath);
//                            } else {
//                                AstScope scope = ci.getTreeUtilities().scopeFor(currentOffset);
//                                te = scope.getEnclosingClass();
//                            }
//                            if (te != null) {
//                                currentElementPtr[0] = ElementUtilities.getBinaryName(te);
//                            }
//                            el = te;
//                        }
//                    } else if (kind == ElementKind.METHOD) {
//                        AstScope scope = ci.getTreeUtilities().scopeFor(currentOffset);
//                        el = scope.getEnclosingMethod();
//                        if (el != null) {
//                            currentElementPtr[0] = el.getSimpleName().toString();
//                            if (currentElementPtr[0].equals("<init>")) {
//                                // The constructor name is the class name:
//                                currentElementPtr[0] = el.getEnclosingElement().getSimpleName().toString();
//                            }
//                        }
//                    } else if (kind == ElementKind.FIELD) {
//                        int offset = currentOffset;
//
//                        if (selectedIdentifier == null) {
//                            String text = ci.getText();
//                            int l = text.length();
//                            char c = 0; // Search for the end of the field declaration
//                            while (offset < l && (c = text.charAt(offset)) != ';' && c != ',' && c != '\n' && c != '\r') {
//                                offset++;
//                            }
//                            if (offset < l && c == ';' || c == ',') { // we have it, but there might be '=' sign somewhere before
//                                int endOffset = --offset;
//                                int setOffset = -1;
//                                while (offset >= 0 && (c = text.charAt(offset)) != ';' && c != ',' && c != '\n' && c != '\r') {
//                                    if (c == '=') {
//                                        setOffset = offset;
//                                    }
//                                    offset--;
//                                }
//                                if (setOffset > -1) {
//                                    offset = setOffset;
//                                } else {
//                                    offset = endOffset;
//                                }
//                                while (offset >= 0 && Character.isWhitespace(text.charAt(offset))) {
//                                    offset--;
//                                }
//                            }
//                            if (offset < 0) {
//                                offset = 0;
//                            }
//                        }
//                        Tree tree = ci.getTreeUtilities().pathFor(offset).getLeaf();
//                        if (tree.getKind() == Tree.Kind.VARIABLE) {
//                            el = ci.getTrees().getElement(ci.getTrees().getPath(ci.getCompilationUnit(), tree));
//                            if (el.getKind() == ElementKind.FIELD || el.getKind() == ElementKind.ENUM_CONSTANT) {
//                                currentElementPtr[0] = ((VariableTree) tree).getName().toString();
//                            }
//                        } else if (tree.getKind() == Tree.Kind.IDENTIFIER && selectedIdentifier != null) {
//                            IdentifierTree it = (IdentifierTree) tree;
//                            String fieldName = it.getName().toString();
//                            AstScope scope = ci.getTreeUtilities().scopeFor(offset);
//                            TypeElement te = scope.getEnclosingClass();
//                            List<? extends Element> enclosedElms = te.getEnclosedElements();
//                            for (Element elm : enclosedElms) {
//                                if (elm.getKind().equals(ElementKind.FIELD) && elm.getSimpleName().contentEquals(fieldName)) {
//                                    currentElementPtr[0] = fieldName;
//                                    break;
//                                }
//                            }
//
//                        } else if (tree.getKind() == Tree.Kind.MEMBER_SELECT && selectedIdentifier != null) {
//                            MemberSelectTree mst = (MemberSelectTree) tree;
//                            String fieldName = mst.getIdentifier().toString();
//                            el = ci.getTrees().getElement(ci.getTrees().getPath(ci.getCompilationUnit(), mst.getExpression()));
//                            if (el.asType().getKind().equals(TypeKind.DECLARED)) {
//                                List<? extends Element> enclosedElms = ((DeclaredType) el.asType()).asElement().getEnclosedElements();
//                                for (Element elm : enclosedElms) {
//                                    if (elm.getKind().equals(ElementKind.FIELD) && elm.getSimpleName().contentEquals(fieldName)) {
//                                        currentElementPtr[0] = fieldName;
//                                        break;
//                                    }
//                                }
//                            }
//                        }
//                    }
//                    if (elementPtr != null) {
//                        elementPtr[0] = el;
//                    }
//                }
//            }, true);
//            if (!scanFinished.isDone()) {
//                if (java.awt.EventQueue.isDispatchThread()) {
//                    // Hack: We should not wait for the scan in AWT!
//                    //       Thus we throw IllegalComponentStateException,
//                    //       which returns the data upon call to getMessage()
//                    throw new java.awt.IllegalComponentStateException() {
//
//                        private void waitScanFinished() {
//                            try {
//                                scanFinished.get();
//                            } catch (InterruptedException iex) {
//                            } catch (java.util.concurrent.ExecutionException eex) {
//                                ErrorManager.getDefault().notify(eex);
//                            }
//                        }
//
//                        public String getMessage() {
//                            waitScanFinished();
//                            return currentElementPtr[0];
//                        }
//                    };
//                } else {
//                    try {
//                        scanFinished.get();
//                    } catch (InterruptedException iex) {
//                        return null;
//                    } catch (java.util.concurrent.ExecutionException eex) {
//                        ErrorManager.getDefault().notify(eex);
//                        return null;
//                    }
//                }
//            }
//        } catch (IOException ioex) {
//            ErrorManager.getDefault().notify(ioex);
//            return null;
//        }
//        return currentElementPtr[0];
        return null;
    }

    private static DataObject getDataObject(String url) {
        FileObject file;
        try {
            file = URLMapper.findFileObject(new URL(url));
        } catch (MalformedURLException e) {
            return null;
        }

        if (file == null) {
            return null;
        }
        try {
            return DataObject.find(file);
        } catch (DataObjectNotFoundException ex) {
            return null;
        }
    }

    private class EditorContextDispatchListener extends Object implements PropertyChangeListener {

        public void propertyChange(PropertyChangeEvent evt) {
            pcs.firePropertyChange(org.openide.windows.TopComponent.Registry.PROP_CURRENT_NODES, null, null);
        }
    }

    private class OperationCreationDelegateImpl implements AST2Bytecode.OperationCreationDelegate {
        /*
        public Operation createOperation(
        Position startPosition,
        Position endPosition,
        int bytecodeIndex) {
        return EditorContextImpl.this.createOperation(
        startPosition,
        endPosition,
        bytecodeIndex);
        }
         */

        public Operation createMethodOperation(
                Position startPosition,
                Position endPosition,
                Position methodStartPosition,
                Position methodEndPosition,
                String methodName,
                String methodClassType,
                int bytecodeIndex) {
            return EditorContextImpl.this.createMethodOperation(
                    startPosition,
                    endPosition,
                    methodStartPosition,
                    methodEndPosition,
                    methodName,
                    methodClassType,
                    bytecodeIndex);
        }

        public Position createPosition(
                int offset,
                int line,
                int column) {
            return EditorContextImpl.this.createPosition(
                    offset,
                    line,
                    column);
        }

        public void addNextOperationTo(Operation operation, Operation next) {
            EditorContextImpl.this.addNextOperationTo(operation, next);
        }
    }
}
TOP

Related Classes of org.netbeans.modules.scala.debugger.projects.EditorContextImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.