ElementUtilities.java :  » IDE-Netbeans » javascript » org » netbeans » modules » javascript » editing » Java Open Source

Java Open Source » IDE Netbeans » javascript 
javascript » org » netbeans » modules » javascript » editing » ElementUtilities.java
/*
 * 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-2006 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.javascript.editing;

import java.io.IOException;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import javax.swing.text.Document;
import org.mozilla.javascript.Node;
import org.netbeans.editor.BaseDocument;
import org.netbeans.modules.gsf.api.CompilationInfo;
import org.netbeans.modules.gsf.api.DeclarationFinder.DeclarationLocation;
import org.netbeans.modules.gsf.api.ElementHandle;
import org.netbeans.modules.javascript.editing.lexer.LexUtilities;
import org.openide.ErrorManager;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;

/**
 *
 * @author Martin Adamek
 */
public class ElementUtilities {

    public static Element getElement(CompilationInfo info, ElementHandle handle) {
        Element element = null;
        if (handle instanceof ElementHandle.UrlHandle) {
            String url = ((ElementHandle.UrlHandle)handle).getUrl();
            DeclarationLocation loc = new JsDeclarationFinder().findLinkedMethod(info, url);
            if (loc != DeclarationLocation.NONE) {
                //element = loc.getElement();
                ElementHandle h = loc.getElement();
                if (handle != null) {
                    element = JsParser.resolveHandle(info, h);
                }
            }
        } else {
            element = JsParser.resolveHandle(info, handle);
        }
        return element;
    }
    
    /**
     * @todo If you invoke this on top of a symbol, I should really just show
     *   the documentation for that symbol!
     * 
     * @param element The element we want to look up comments for
     * @param info The (optional) compilation info for a document referencing the element.
     *   This is used to consult require-statements in the given compilation context etc.
     *   to choose among many alternatives. May be null, in which case the element had
     *   better be an IndexedElement.
     */
    public static List<String> getComments(CompilationInfo info, Element element) {
        assert info != null || element instanceof IndexedFunction;
        
        if (element == null) {
            return null;
        }

        if (element instanceof IndexedElement) {
            IndexedElement indexedElement = (IndexedElement) element;
            // this was called in code moved to getNode
            List<String> comments = indexedElement.getComments();
            if (comments != null || indexedElement.getDocOffset() == -1) {
                return comments;
            }
        }
        
        Node node = getNode(info, element);
        if (node == null) {
            return null;
        }

        // Initially, I implemented this by using JsParserResult.getCommentNodes.
        // However, I -still- had to rely on looking in the Document itself, since
        // the CommentNodes are not attached to the AST, and to do things the way
        // RDoc does, I have to (for example) look to see if a comment is at the
        // beginning of a line or on the same line as something else, or if two
        // comments have any empty lines between them, and so on.
        // When I started looking in the document itself, I realized I might as well
        // do all the manipulation on the document, since having the Comment nodes
        // don't particularly help.
        BaseDocument baseDoc = getBaseDocument(info, element);

        List<String> comments = null;

        // Check for JsComObject: These are external files (like Js lib) where I need to check many files
//        if (node instanceof ClassNode && !(element instanceof IndexedElement)) {
//            String className = AstUtilities.getClassOrModuleName((ClassNode)node);
//            List<ClassNode> classes = AstUtilities.getClasses(AstUtilities.getRoot(info));
//
//            // Iterate backwards through the list because the most recent documentation
//            // should be chosen, if any
//            for (int i = classes.size() - 1; i >= 0; i--) {
//                ClassNode clz = classes.get(i);
//                String name = AstUtilities.getClassOrModuleName(clz);
//
//                if (name.equals(className)) {
//                    comments = AstUtilities.gatherDocumentation(info, baseDoc, clz);
//
//                    if ((comments != null) && (comments.size() > 0)) {
//                        break;
//                    }
//                }
//            }
//        } else {
            comments = LexUtilities.gatherDocumentation(info, baseDoc, node.getSourceStart());
//        }

        if ((comments == null) || (comments.size() == 0)) {
            return null;
        }
        
        return comments;
    }
    
    public static String getSignature(Element element) {
        StringBuilder sb = new StringBuilder();
        IndexedElement indexedElement = null;
        if (element instanceof IndexedElement) {
            indexedElement = (IndexedElement)element;
        }
        
        // Insert browser icons... TODO - consult flags etc.
        sb.append("<table width=\"100%\" border=\"0\"><tr>\n");

        sb.append("<td>");

        if (element.getIn() != null) {
            String in = element.getIn();
            if (in != null && in.length() > 0) {
                sb.append("<i>");
                sb.append(in);
                sb.append("</i>");
            
                if (indexedElement != null) {
                    String url = indexedElement.getFilenameUrl();
                    if (url.indexOf("jsstubs/stub_core_") != -1) { // NOI18N
                        sb.append(" (Core JavaScript)");
                    } else if (url.indexOf("jsstubs/stub_") != -1) { // NOI18N
                        sb.append(" (DOM)");
                    }
                }

                sb.append("<br>");
            }
        }
        // TODO - share this between Navigator implementation and here...
        sb.append("<b>");
        sb.append(element.getName());
        sb.append("</b>");

        if (element instanceof FunctionElement) {
            FunctionElement executable = (FunctionElement) element;
            Collection<String> parameters = executable.getParameters();

            if ((parameters != null) && (parameters.size() > 0)) {
                sb.append("(");

                sb.append("<font color=\"#808080\">");

                for (Iterator<String> it = parameters.iterator(); it.hasNext();) {
                    String ve = it.next();
                    // TODO - if I know types, list the type here instead. For now, just use the parameter name instead
                    sb.append(ve);

                    if (it.hasNext()) {
                        sb.append(", ");
                    }
                }

                sb.append("</font>");

                sb.append(")");
            }
        }
        sb.append("</td>\n");
        if (indexedElement != null) {
            sb.append("<td width=\"100\">");
            EnumSet<BrowserVersion> es = indexedElement.getCompatibility();
            try {
                if (es.contains(BrowserVersion.FF3)) {
                    appendImage(sb, "firefox20.png");
                } else {
                    appendImage(sb, "firefox20-disabled.png");
                }
                if (es.contains(BrowserVersion.IE7)) {
                    appendImage(sb, "ie20.png");
                } else {
                    appendImage(sb, "ie20-disabled.png");
                }
                if (es.contains(BrowserVersion.SAFARI3)) {
                    appendImage(sb, "safari20.png");
                } else {
                    appendImage(sb, "safari20-disabled.png");
                }
                if (es.contains(BrowserVersion.OPERA)) {
                    appendImage(sb, "opera20.png");
                } else {
                    appendImage(sb, "opera20-disabled.png");
                }
            } catch (Exception ex) {
                Exceptions.printStackTrace(ex);
            }
            sb.append("</td>");
        }
        sb.append("</tr></table>");

        if (indexedElement != null && indexedElement.getFilenameUrl() != null && indexedElement.getFilenameUrl().indexOf("jsstubs") == -1) {
            sb.append(NbBundle.getMessage(JsCodeCompletion.class, "FileLabel"));
            sb.append(" <tt>");
            String file = indexedElement.getFilenameUrl();
            int baseIndex = file.lastIndexOf('/');
            if (baseIndex != -1) {
                file = file.substring(baseIndex+1);
            }
            sb.append(file);
            sb.append("</tt><br>");
        }
        
        // Generate compatibility notes
        if (indexedElement != null && !SupportedBrowsers.getInstance().isSupported(indexedElement.getCompatibility())) {
            sb.append("<hr>");
            sb.append("<p style=\"background:#ffcccc\">");
            sb.append(NbBundle.getMessage(JsCodeCompletion.class, "NotSupportedBr"));
            sb.append("\n");
            sb.append("<ul>");
            for (BrowserVersion v : BrowserVersion.ALL) {
                if (SupportedBrowsers.getInstance().isSupported(v) && 
                        !indexedElement.getCompatibility().contains(v)) {
                    sb.append("<li>");
                    sb.append(v.getDisplayName());
                }
            }
            sb.append("</ul>\n");
            //sb.append("Click <a href=\"netbeans:choosebrowsers\">here</a> to choose targeted browsers.\n");
            sb.append(NbBundle.getMessage(JsCodeCompletion.class, "EditTargetedBr"));
            sb.append("\n");
            sb.append("</p>");
        }

        return sb.toString();
    }

    private static Node getNode(CompilationInfo info, Element element) {
        Node node = null;

        if (element instanceof AstElement) {
            node = ((AstElement)element).getNode();
        } else if (element instanceof IndexedElement) {
            IndexedElement indexedElement = (IndexedElement)element;
            IndexedElement match = null;
            Node root = null;
            if (info != null) {
                root = AstUtilities.getRoot(info);
                match = findDocumentationEntry(root, indexedElement);
            }

            if (match != null) {
                indexedElement = match;
            }

            node = AstUtilities.getForeignNode(indexedElement, null);
        } else {
            assert false : element;
        }
        return node;
    }
    
    private static BaseDocument getBaseDocument(CompilationInfo info, Element element) {
        Document doc = null;
        BaseDocument baseDoc = null;

        try {
            if (element instanceof IndexedFunction) {
                doc = ((IndexedFunction)element).getDocument();
                info = null;
            } else if (info != null) {
                doc = info.getDocument();
            }

            if (doc instanceof BaseDocument) {
                baseDoc = (BaseDocument)doc;
            }
        } catch (IOException ioe) {
            ErrorManager.getDefault().notify(ioe);
        }
        return baseDoc;
    }
    
    /**
     * @todo is it possible to have multiple sources of documentation fo JavaScript?
     */
    private static IndexedElement findDocumentationEntry(Node root, IndexedElement obj) {
        return obj;
    }
    
    private static void appendImage(StringBuilder sb, String image) {
        sb.append("<img src=\"" + JsCodeCompletion.class.getResource("icons/" + image).toExternalForm() + "\">"); // NOI18N
    }
    
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.