alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.editor.java;

import java.awt.Dialog;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import javax.swing.ImageIcon;
import javax.swing.ListCellRenderer;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.editor.BaseDocument;
import org.netbeans.editor.SyntaxSupport;
import org.netbeans.editor.Utilities;
import org.netbeans.editor.ext.Completion;
import org.netbeans.editor.ext.CompletionQuery;
import org.netbeans.editor.ext.ExtUtilities;
import org.netbeans.editor.ext.java.JavaCompletion;
import org.netbeans.editor.ext.java.JCClass;
import org.netbeans.editor.ext.java.JCType;
import org.netbeans.editor.ext.java.JCConstructor;
import org.netbeans.editor.ext.java.JCMethod;
import org.netbeans.editor.ext.java.JCField;
import org.netbeans.editor.ext.java.JCParameter;
import org.netbeans.editor.ext.java.JCFinder;
import org.netbeans.editor.ext.java.JCCellRenderer;
import org.netbeans.editor.ext.java.JCResultItem;
import org.netbeans.modules.editor.NbEditorUtilities;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
import org.openide.src.ClassElement;
import org.openide.src.ConstructorElement;
import org.openide.src.MethodElement;
import org.openide.src.FieldElement;
import org.openide.src.Identifier;
import org.openide.src.SourceElement;
import org.openide.src.Type;
import org.openide.src.MethodParameter;
import org.openide.src.nodes.ElementNode;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataFolder;
import org.openide.nodes.Node;
import org.openide.cookies.SourceCookie;
import org.openide.filesystems.FileObject;
import org.openide.DialogDescriptor;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.filesystems.FileSystem;
import org.openide.src.JavaDoc;
import org.openide.src.JavaDocTag;
import org.openide.util.enum.QueueEnumeration;

/**
* Extended Java Completion support
*
* @author Miloslav Metelka
* @version 1.00
*/

public class JCExtension {

    public static boolean equals(JCClass cls1, ClassElement cls2) {
        return cls1.getFullName().equals(cls2.getName().getFullName());
    }

    public static boolean equals(JCType typ1, Type typ2) {
        // Get array depth of the type
        int arrayDepth = 0;
        while(typ2.isArray()) {
            arrayDepth++;
            typ2 = typ2.getElementType();
        }

        String fn = typ2.isPrimitive() ? typ2.getFullString()
                    : typ2.getClassName().getFullName();
        return (typ1.getArrayDepth() == arrayDepth)
               && typ1.getClazz().getFullName().equals(fn);
    }

    public static boolean equals(JCField fld1, FieldElement fld2) {
        return fld1.getName().equals(fld2.getName().getFullName())
               && equals(fld1.getType(), fld2.getType());
    }

    public static boolean equals(JCConstructor ctr1, ConstructorElement ctr2) {
        JCParameter[] parms1 = ctr1.getParameters();
        MethodParameter[] parms2 = ctr2.getParameters();
        if (parms2 == null || parms1.length != parms2.length) {
            return false;
        }
        for (int i = parms1.length - 1; i >= 0; i--) {
            if (!equals(parms1[i].getType(), parms2[i].getType())) {
                return false;
            }
        }
        return true;
    }

    public static boolean equals(JCMethod mtd1, MethodElement mtd2) {
        return mtd1.getName().equals(mtd2.getName().getFullName())
               && equals((JCConstructor)mtd1, (ConstructorElement)mtd2);
    }

    public static FieldElement findFieldElement(JCField fld, ClassElement ce) {
        FieldElement[] fes = ce.getFields();
        if (fes != null) {
            for (int i = 0; i < fes.length; i++) {
                if (equals(fld, fes[i])) {
                    return fes[i];
                }
            }
        }
        return null;
    }

    public static ConstructorElement findConstructorElement(JCConstructor ctr, ClassElement ce) {
        ConstructorElement[] ces = ce.getConstructors();
        if (ces != null) {
            for (int i = 0; i < ces.length; i++) {
                if (equals(ctr, ces[i])) {
                    return ces[i];
                }
            }
        }
        return null;
    }

    public static MethodElement findMethodElement(JCMethod mtd, ClassElement ce) {
        MethodElement[] mes = ce.getMethods();
        if (mes != null) {
            for (int i = 0; i < mes.length; i++) {
                if (equals(mtd, mes[i])) {
                    return mes[i];
                }
            }
        }
        return null;
    }

    
    private static JCFinder getFinder(FileObject fo) {
        return JavaCompletion.getFinder();
    }

    /**
     * Get or create the simple class from class element.
     * @param finder finder for searching class if necessary; cannot be
     *     null if preferFinder is true
     * @param cp classpath on which the class can be searched if necessary; 
     *    cannot be null
     */
    private static JCClass getIdentifierClass(ClassElement ce, Map lookupCache, 
            boolean preferFinder, JCFinder finder, ClassPath cp) {
        String fn = ce.getName().getFullName();
        
        // First try the lookupCache
        JCClass cls = (JCClass)lookupCache.get(fn);
        // check that class has a package - it is possible that it is already in cache
        // but with no package and in such a case the cache and class should be updated
        if (cls != null && cls.getPackageName() != null && cls.getPackageName().length() > 0) {
            return cls;
        }

        SourceElement se = ce.getSource();
        if (se != null) {
            int pkgLen = 0;
            if (se.getPackage() != null) {
                pkgLen = se.getPackage().getFullName().length();
            }
            cls = JavaCompletion.getSimpleClass(fn, pkgLen);
            lookupCache.put(fn, cls);
            return cls;
        }
        
        return getIdentifierClass(ce.getName(), lookupCache, preferFinder, finder, cp);
    }

    /** Get or create the simple class from identifier.
    * @param i identifier holding the class information
    * @param lookupCache cache holding the [name, simple-class] pairs for already found classes
    * @param preferFinder whether the package name finding should be first tried
    *   through the finder or through the ClassElement.forName()
    * @param finder finder for searching class if necessary; cannot be
    *     null if preferFinder is true
    * @param cp classpath on which the class can be searched if necessary;
    *    cannot be null
    */
    // PERF: do not use ClassElement.forName() to learn package name. 
    // It is too expensive!!
    private static JCClass getIdentifierClass(Identifier i, Map lookupCache, boolean preferFinder, JCFinder finder, ClassPath cp) {
        String fn = i.getFullName(); // Get identifier's full name

        // First try the lookupCache
        JCClass cls = (JCClass)lookupCache.get(fn);
        if (cls != null) {
            return cls;
        }

        // Try finder if it's preferred
        if (preferFinder) {
            assert finder != null;
            cls = finder.getExactClass(fn); // try to find through the current finder
            if (cls != null) {
                cls = JavaCompletion.getSimpleClass(cls); // be sure to have simple class
                lookupCache.put(fn, cls);
                return cls;
            }
        }

        // try to find Identifier on classpath
        int pkgLen = getPackageLength(fn, cp);
        
        // If failed try to resolve through the current finder
        if (pkgLen < 0) {
            if (finder != null) {
                if (!preferFinder) { // already tried for preferFinder == true
                    cls = finder.getExactClass(fn);
                }

                if (cls == null) { // not exact fullname, try by name only
                    List clsList = finder.findClasses(null, fn, true);
                    if (clsList != null && clsList.size() == 1) { // only when exactly one match
                        cls = (JCClass)clsList.get(0);
                    }
                }
                
                if (cls != null) {
                    cls = JavaCompletion.getSimpleClass(cls); // be sure to have simple class
                    lookupCache.put(fn, cls);
                    return cls;
                }
            }
        }

        if (pkgLen < 0) {
            // ok, could not detect package length and so whole fully
            // qualified name will be used instead of just class name.
            pkgLen = 0;
        }

        // Get the class
        cls = JavaCompletion.getSimpleClass(fn, pkgLen);
        lookupCache.put(fn, cls);
        return cls;
    }

    /*
       DEBUG to getIdentifierClass() that test if the class is reachable
              if (pkgName != null && clsName != null) {
                try { // !!! Try to create the class without init
                  Class.forName(pkgName + '.' + clsName.replace('.', '$'), false, JCExtension.class.getClassLoader());
                } catch (ClassNotFoundException e) {
                  System.out.println("Class not found: '" + pkgName + '.' + clsName + "', fn='" + fn + "'"); // NOI18N
                }
              }
    */

    /**
     * Searches class on the classpath. The method searches existence of
     * .java or .class file on the classpath. It goes from the root of classpath
     * till it finds a corresponding file.
     *
     * @param name fully qualified class name; dot must be separator
     * @param cp classpath to use for class searching; cannot be null
     * @return length of the package or -1 if package could not be detected 
     */
    private static int getPackageLength(String name, ClassPath cp) {
        if (name.indexOf('.') == -1) {
            // default package
            return 0;
        }
        assert cp != null;
        List l = new ArrayList();
        if (cp.getRoots().length > 0) {
            l.addAll(Arrays.asList(cp.getRoots()));
        }
        StringTokenizer tok = new StringTokenizer(name, "."); // NOI18N
        int pkgLen = 0;
        while (tok.hasMoreTokens()) {
            String nm = tok.nextToken();
            
            Iterator it = l.iterator();
            l = new ArrayList();
            while (it.hasNext()) {
                FileObject fo = (FileObject)it.next();
                if (fo.getFileObject(nm, "java") != null) { // NOI18N
                    return pkgLen;
                }
                if (fo.getFileObject(nm, "class") != null) { // NOI18N
                    return pkgLen;
                }
                FileObject f = fo.getFileObject(nm, null);
                if (f != null) {
                    l.add(f);
                }
            }
            
            if (l.size() == 0) {
                return -1;
            }
            
            if (pkgLen == 0) {
                pkgLen += nm.length();
            } else {
                pkgLen += nm.length() + 1;
            }
        }
        return -1;
    }
    
    private static JCType getType(Type t, Map lookupCache, boolean preferFinder, JCFinder finder, ClassPath cp) {
        // Get array depth of the type
        int arrayDepth = 0;
        while(t.isArray()) {
            arrayDepth++;
            t = t.getElementType();
        }

        JCClass c;
        if (t.isPrimitive()) {
            c = JavaCompletion.getPrimitiveClass(t.getFullString());
        } else {
            c = getIdentifierClass(t.getClassName(), lookupCache, preferFinder, finder, cp);
        }
        return JavaCompletion.getType(c, arrayDepth);
    }

    
    /**
     * Returns one classpath which is merge of SOURCE, COMPILE and BOOT
     * classpaths of the given file object.
     */
    public static ClassPath getFullClassPath(FileObject context) {
        ArrayList l = new ArrayList();
        ClassPath cp = ClassPath.getClassPath(context, ClassPath.SOURCE);
        if (cp != null) {
            l.add(cp);
        }
        cp = ClassPath.getClassPath(context, ClassPath.COMPILE);
        if (cp != null) {
            l.add(cp);
        }
        cp = ClassPath.getClassPath(context, ClassPath.BOOT);
        if (cp != null) {
            l.add(cp);
        }
        return ClassPathSupport.createProxyClassPath((ClassPath[])l.toArray(new ClassPath[l.size()]));
    }
    

    /** Finds an inner class with the same name as the resultClassItem */
    static JCClass findResultInnerClass(JCFinder finder, JCClass topClass, String innerClsName, Document doc){
        if (topClass == null || innerClsName == null) return null;

        ClassElement ce = ClassElement.forName(topClass.getFullName(),
                NbEditorUtilities.getDataObject (doc).getPrimaryFile());
        if (ce == null) return null;
        ClassElement innerClasses[] = ce.getClasses();
        
        if (innerClsName != null){
            for (int i=0; i0) && (doc.getChars(dotPos-1, 1)[0] == '(') && (dotPos == idFunBlk[0]))){
                        idFunBlk = new int[] { dotPos, dotPos };
                    }

                    for (int ind = idFunBlk.length - 1; ind >= 1; ind--) {
                        CompletionQuery.Result result = completion.getQuery().query(
                                                            target, idFunBlk[ind], sup);
                        if (result != null && result.getData().size() > 0) {
                            Object itm = result.getData().get(0);
                            if (itm instanceof JCResultItem){
                                itm = ((JCResultItem)itm).getAssociatedObject();
                            }

                            if ( ((itm instanceof JCConstructor) || (itm instanceof JCMethod) )&& (result.getData().size() > 1) ){
                                // It is overloaded method, lets check for the right one
                                int endOfMethod = findEndOfMethod(target, idFunBlk[ind]);

                                if (endOfMethod>-1){
                                    CompletionQuery.Result resultx = completion.getQuery().query(target, endOfMethod, sup);
                                    if (resultx != null && resultx.getData().size() > 0) {
                                        Object itmx = resultx.getData().get(0);
                                        if (itmx instanceof JCResultItem){
                                            itmx = ((JCResultItem)itmx).getAssociatedObject();
                                        }

                                        return itmx;
                                    }
                                }

                            } 

                            // check whether the item is not declared in the inner class
                            Object innerClassItem = findResultInnerItem(nbJavaSup, result, doc);
                            if (innerClassItem !=null){
                                return innerClassItem;
                            }

                            Object importedItem = findImportedItem(nbJavaSup, result);
                            if (importedItem != null) return importedItem;
                            Object itmx = result.getData().get(0);
                            if (itmx instanceof JCResultItem){
                                return ((JCResultItem)itmx).getAssociatedObject();
                            }

                        }
                    }
                } catch (BadLocationException e) {
                }
            }
        }

        // Complete the messages
        return null;

    }
    

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.