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

Java Open Source » IDE Netbeans » javascript 
javascript » org » netbeans » modules » javascript » editing » JsTypeSearcher.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.File;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import org.mozilla.javascript.Node;
import org.netbeans.modules.gsf.api.ElementHandle;
import org.netbeans.modules.gsf.api.Index;
import org.netbeans.modules.gsf.api.Index.SearchScope;
import org.netbeans.modules.gsf.api.NameKind;
import org.netbeans.modules.gsf.api.TypeSearcher;
import org.netbeans.modules.gsf.api.TypeSearcher.GsfTypeDescriptor;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.api.project.ProjectUtils;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle;

/**
 *
 * @todo Figure out why "base" searches gives me lower-case matches on "base" (which seems invalid)
 * 
 * @author Tor Norbye
 */
public class JsTypeSearcher implements TypeSearcher {
    public JsTypeSearcher() {
    }
    
    private static boolean isAllUpper( String text ) {
        for( int i = 0; i < text.length(); i++ ) {
            char c = text.charAt(i);
            if (!Character.isUpperCase(c) && c != ':' ) {
                return false;
            }
        }
        
        return true;
    }
    
    private static Pattern camelCasePattern = Pattern.compile("(?:\\p{javaUpperCase}(?:\\p{javaLowerCase}|\\p{Digit}|\\:|\\.|\\$)*){2,}"); // NOI18N
    
    private static boolean isCamelCase(String text) {
         return camelCasePattern.matcher(text).matches();
    }
    
    private NameKind cachedKind;
    private String cachedString = "/";
    
    private NameKind adjustKind(NameKind kind, String text) {
        if (text.equals(cachedString)) {
            return cachedKind;
        }
        if (kind == NameKind.CASE_INSENSITIVE_PREFIX) {
            if ((isAllUpper(text) && text.length() > 1) || isCamelCase(text)) {
                kind = NameKind.CAMEL_CASE;            
            }
        }

        cachedString = text;
        cachedKind = kind;
        return kind;
    }
    
    public Set<? extends GsfTypeDescriptor> getDeclaredTypes(Index gsfIndex,
                                                        String textForQuery,
                                                        NameKind kind,
                                                        EnumSet<SearchScope> scope, Helper helper) {
        // In addition to just computing the declared types here, we perform some additional
        // "second guessing" of the query. In particular, we want to allow double colons
        // to be part of the query names (to specify full module names), but since colon is
        // treated by the Open Type dialog as a regexp char, it will turn it into a regexp query
        // for example. Thus, I look at the query string and I might turn it into a different kind
        // of query. (We also allow #method suffixes which are handled here.)
        
        
//        if (textForQuery.endsWith("::")) {
//            textForQuery = textForQuery.substring(0, textForQuery.length()-2);
//        } else if (textForQuery.endsWith(":")) {
//            textForQuery = textForQuery.substring(0, textForQuery.length()-1);
//        }
        
        JsIndex index = JsIndex.get(gsfIndex);
        if (index == null) {
            return Collections.emptySet();
        }

        kind = adjustKind(kind, textForQuery);
        
        if (kind == NameKind.CASE_INSENSITIVE_PREFIX /*|| kind == NameKind.CASE_INSENSITIVE_REGEXP*/) {
            textForQuery = textForQuery.toLowerCase();
        }

        Set<JsTypeDescriptor> result = new HashSet<JsTypeDescriptor>();
        Set<IndexedElement> elements;
        int dot = textForQuery.lastIndexOf('.');
        if (dot != -1) {
            String prefix = textForQuery.substring(dot+1);
            String in = textForQuery.substring(0, dot);
            elements = index.getElements(prefix, in, kind, scope, null);
        } else {
            elements = index.getAllNames(textForQuery, kind, scope, null);
        }
        for (IndexedElement element : elements) {
            result.add(new JsTypeDescriptor(element, helper));
        }
        
        
//        String method = null;
//        int methodIndex = textForQuery.indexOf('#');
//        if (methodIndex != -1) {
//            method = textForQuery.substring(methodIndex+1);
//            textForQuery = textForQuery.substring(0, methodIndex);
//        }
//        
//        Set<IndexedClass> classes = null;
//        if (method == null || textForQuery.length() > 0) {
//            classes = index.getClasses(textForQuery, kind, true, false, false, scope, null);
//        }
//        
//        Set<JsTypeDescriptor> result = new HashSet<JsTypeDescriptor>();
//        
//        if (method != null) {
//            // Query methods
//            Set<IndexedMethod> methods = index.getMethods(method, null, kind, scope);
//            for (IndexedMethod m : methods) {
//                if (textForQuery.length() > 0 && m.getClz() != null) {
//                    String in = m.getClz();
//                    switch (kind) {
//                    case CASE_INSENSITIVE_REGEXP:
//                    case REGEXP:
//                        try {
//                            if (in.indexOf("::") != -1 && textForQuery.indexOf("::") == -1) { // NOI18N
//                                // Try matching each
//                                boolean matches = false;
//                                for (String c : in.split("::")) { // NOI18N
//                                    if (c.matches(textForQuery)) {
//                                        matches = true;
//                                        break;
//                                    }
//                                }
//                                
//                                if (!matches) {
//                                    continue;
//                                }
//                            } else if (!in.matches(textForQuery)) {
//                                continue;
//                            }
//                        } catch (Exception e) {
//                            // Silently ignore errors in regexps since they can come from the user
//                        }
//                        break;
//                    case CASE_INSENSITIVE_PREFIX:
//                        if (!in.regionMatches(true, 0, textForQuery, 0, textForQuery.length())) {
//                            continue;
//                        }
//                        break;
//                    case PREFIX:
//                        if (!in.regionMatches(false, 0, textForQuery, 0, textForQuery.length())) {
//                            continue;
//                        }
//                        break;
//                    case EXACT_NAME:
//                        if (!in.equalsIgnoreCase(textForQuery)) {
//                            continue;
//                        }
//                    }
//                }
//                result.add(new JsTypeDescriptor(m, helper));
//            }
//        } else {
//            for (IndexedClass cls : classes) {
//                result.add(new JsTypeDescriptor(cls, helper));
//            }
//        }
        
        return result;
    }

    private class JsTypeDescriptor extends GsfTypeDescriptor {
        private final IndexedElement element;
        private String projectName;
        private Icon projectIcon;
        private final Helper helper;
        private boolean isLibrary;
        private static final String ICON_PATH = "org/netbeans/modules/javascript/editing/javascript.png"; //NOI18N
        
        public JsTypeDescriptor(IndexedElement element, Helper helper) {
            this.element = element;
            this.helper = helper;
        }

        public Icon getIcon() {
            if (projectName == null) {
                initProjectInfo();
            }
            //if (isLibrary) {
            //    return new ImageIcon(org.openide.util.Utilities.loadImage(Js_KEYWORD));
            //}
            return helper.getIcon(element);
        }

        public String getTypeName() {
            return element.getName();
        }

        public String getProjectName() {
            if (projectName == null) {
                initProjectInfo();
            }
            return projectName;
        }

        private void initProjectInfo() {
            FileObject fo = element.getFileObject();
            if (fo != null) {
                File f = FileUtil.toFile(fo);
                Project p = FileOwnerQuery.getOwner(fo);
                if (p != null) {
//                    JsPlatform platform = JsPlatform.platformFor(p);
//                    if (platform != null) {
//                        String lib = platform.getLib();
//                        if (lib != null && f.getPath().startsWith(lib)) {
//                            projectName = "Js Library";
//                            isLibrary = true;
//                        }
//                    } else {
                        ProjectInformation pi = ProjectUtils.getInformation(p);
                        projectName = pi.getDisplayName();
                        projectIcon = pi.getIcon();
//                    }
                }
            } else {
                isLibrary = true;
                Logger.getLogger(JsTypeSearcher.class.getName()).fine("No fileobject for " + element.toString() + " with fileurl=" + element.getFilenameUrl());
            }
            if (projectName == null) {
                projectName = "";
            }
        }
        
        public Icon getProjectIcon() {
            if (projectName == null) {
                initProjectInfo();
            }
            if (isLibrary) {
                return new ImageIcon(org.openide.util.Utilities.loadImage(ICON_PATH));
            }
            return projectIcon;
        }

        public FileObject getFileObject() {
            return element.getFileObject();
        }

        public void open() {
            Node node = AstUtilities.getForeignNode(element, null);
            
            if (node != null) {
                // TODO - embedding context?
                int offset = AstUtilities.getRange(node).getStart();
                NbUtilities.open(element.getFileObject(), offset, element.getName());
                return;
            }
            
            FileObject fileObject = element.getFileObject();
            if (fileObject == null) {
                NotifyDescriptor nd =
                    new NotifyDescriptor.Message(NbBundle.getMessage(JsTypeSearcher.class, "FileDeleted"), 
                    NotifyDescriptor.Message.ERROR_MESSAGE);
                DialogDisplayer.getDefault().notify(nd);
                // TODO: Try to remove the item from the index? Can't fix yet because the url is wiped
                // out by getFileObject (to avoid checking file existence multiple times; use a boolean
                // flag for that instead)
                
                return;
            }
            
            helper.open(fileObject, element);
        }

        public String getContextName() {
            // XXX This is lame - move formatting logic to the goto action!
            StringBuilder sb = new StringBuilder();
//            String require = element.getRequire();
//            String fqn = element.getFqn();
            String fqn = element.getIn() != null ? element.getIn() + "." + element.getName() : element.getName();
            if (element.getName().equals(fqn)) {
                fqn = null;
            }
            if (fqn != null/* || require != null*/) {
                sb.append(" (");
                if (fqn != null) {
                    sb.append(fqn);
                }
//                if (require != null) {
//                    if (fqn != null) {
//                        sb.append(" ");
//                    }
//                    sb.append("in ");
//                    sb.append(require);
//                    sb.append(".rb");
//                }
                sb.append(")");
                return sb.toString();
            } else {
                return null;
            }
        }

        public ElementHandle getElement() {
            return element;
        }

        public int getOffset() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public String getSimpleName() {
            return element.getName();
        }

        public String getOuterName() {
            return null;
        }

    }

    public String getMimetype() {
        return JsMimeResolver.JAVASCRIPT_MIME_TYPE;
    }
}
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.