# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: /Users/samuel/Documents/Java/NetBeans/main-golden/java.editor # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: src/org/netbeans/modules/editor/java/ExcludeCompletion.java --- src/org/netbeans/modules/editor/java/ExcludeCompletion.java Base (BASE) +++ src/org/netbeans/modules/editor/java/ExcludeCompletion.java Locally New @@ -0,0 +1,145 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 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]" + * + * 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. + * + * Contributor(s): + * + * Samuel Halliday + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ +package org.netbeans.modules.editor.java; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.prefs.PreferenceChangeEvent; +import java.util.prefs.PreferenceChangeListener; +import java.util.prefs.Preferences; +import org.netbeans.api.editor.mimelookup.MimeLookup; + +/** + * A whitelist/blacklist of excluded classes and packages for the Java completer. + * Requested in RFE #125060. + * + * @author Samuel Halliday + */ +public final class ExcludeCompletion implements PreferenceChangeListener { + + // TODO: move to CodeCompletionPanel + public static final String JAVA_COMPLETION_WHITELIST = "javaCompletionWhitelist"; //NOI18N + public static final String JAVA_COMPLETION_BLACKLIST = "javaCompletionBlacklist"; //NOI18N + private final Collection exclude = new ArrayList(); + private final Collection include = new ArrayList(); + private static volatile ExcludeCompletion singleton = null; + + /** + * Cheap operation to return an instance + * + * @return + */ + public static ExcludeCompletion getInstance() { + // lazy check without lock + if (singleton == null) + synchronized (ExcludeCompletion.class) { + if (singleton == null) { + singleton = new ExcludeCompletion(); + // is there not a way to just register to listen to Java Completion changes? + // the preferences tree does not appear to be very deep + Preferences preferences = + MimeLookup.getLookup(JavaKit.JAVA_MIME_TYPE).lookup(Preferences.class); + // ?? why is this commented "weak" code used in Utilities? + // WeakListeners.create(PreferenceChangeListener.class, this, preferences); + // preferences.addPreferenceChangeListener(null); + preferences.addPreferenceChangeListener(singleton); + // initial population + preferences.put(JAVA_COMPLETION_BLACKLIST, "sun,apple"); + preferences.put(JAVA_COMPLETION_WHITELIST, "sun.security"); + } + } + assert singleton != null; + return singleton; + } + + private ExcludeCompletion() { + } + + /** + * @param fqn Fully Qualified Name + * @return + */ + public boolean isExcluded(String fqn) { + //#122334: do not propose imports from the default package + if (fqn == null || fqn.length() == 0) + return true; + + if (include.size() > 0) + for (String entry : include) { + if (entry.length() > fqn.length()) + continue; + if (fqn.startsWith(entry)) + return false; + } + + if (exclude.size() > 0) + for (String entry : exclude) { + if (entry.length() > fqn.length()) + continue; + if (fqn.startsWith(entry)) + return true; + } + + return false; + } + + public void preferenceChange(PreferenceChangeEvent evt) { + if (evt == null) + return; + String key = evt.getKey(); + if (JAVA_COMPLETION_BLACKLIST.equals(key)) + update(exclude, evt.getNewValue()); + else if (JAVA_COMPLETION_WHITELIST.equals(key)) + update(include, evt.getNewValue()); + } + + private void update(Collection existing, String updated) { + // ??: how thread safe does this class need to be with regards to preferences? + existing.clear(); + if (updated == null || updated.length() == 0) + return; + String[] entries = updated.split(","); //NOI18N + for (String entry : entries) { + if (entry != null && entry.length() > 0) + existing.add(entry); + } + } +} Index: src/org/netbeans/modules/editor/java/JavaCompletionProvider.java --- src/org/netbeans/modules/editor/java/JavaCompletionProvider.java Base (BASE) +++ src/org/netbeans/modules/editor/java/JavaCompletionProvider.java Locally Modified (Based On LOCAL) @@ -2728,10 +2728,13 @@ private void addPackages(Env env, String fqnPrefix, boolean inPkgStmt) { if (fqnPrefix == null) fqnPrefix = EMPTY; - for (String pkgName : env.getController().getClasspathInfo().getClassIndex().getPackageNames(fqnPrefix, true,EnumSet.allOf(ClassIndex.SearchScope.class))) - if (pkgName.length() > 0) + ExcludeCompletion excluder = ExcludeCompletion.getInstance(); + for (String pkgName : env.getController().getClasspathInfo().getClassIndex().getPackageNames(fqnPrefix, true,EnumSet.allOf(ClassIndex.SearchScope.class))){ + if (excluder.isExcluded(pkgName)) + continue; results.add(JavaCompletionItem.createPackageItem(pkgName, anchorOffset, inPkgStmt)); } + } private void addTypes(Env env, EnumSet kinds, DeclaredType baseType, Set toExclude, boolean insideNew) throws IOException { if (queryType == COMPLETION_ALL_QUERY_TYPE) { @@ -2807,7 +2810,11 @@ ClassIndex.NameKind kind = env.isCamelCasePrefix() ? Utilities.isCaseSensitive() ? ClassIndex.NameKind.CAMEL_CASE : ClassIndex.NameKind.CAMEL_CASE_INSENSITIVE : Utilities.isCaseSensitive() ? ClassIndex.NameKind.PREFIX : ClassIndex.NameKind.CASE_INSENSITIVE_PREFIX; + ExcludeCompletion excluder = ExcludeCompletion.getInstance(); for(ElementHandle name : controller.getClasspathInfo().getClassIndex().getDeclaredTypes(prefix != null ? prefix : EMPTY, kind, EnumSet.allOf(ClassIndex.SearchScope.class))) { + String fqn = name.getQualifiedName(); + if (excluder.isExcluded(fqn)) + continue; LazyTypeCompletionItem item = LazyTypeCompletionItem.create(name, kinds, anchorOffset, controller.getSnapshot().getSource(), insideNew); if (item.isAnnonInner()) continue; Index: src/org/netbeans/modules/java/editor/imports/ComputeImports.java --- src/org/netbeans/modules/java/editor/imports/ComputeImports.java Base (BASE) +++ src/org/netbeans/modules/java/editor/imports/ComputeImports.java Locally Modified (Based On LOCAL) @@ -72,6 +72,7 @@ import org.netbeans.api.java.source.ClassIndex.NameKind; import org.netbeans.api.java.source.ElementHandle; import org.netbeans.api.java.source.support.CancellableTreePathScanner; +import org.netbeans.modules.editor.java.ExcludeCompletion; import org.netbeans.modules.java.editor.javadoc.JavadocImports; import org.openide.util.Union2; @@ -127,6 +128,7 @@ unresolvedNames.addAll(JavadocImports.computeUnresolvedImports(info)); + ExcludeCompletion excluder = ExcludeCompletion.getInstance(); for (String unresolved : unresolvedNames) { if (isCancelled()) return null; @@ -145,11 +147,11 @@ continue; } - //#122334: do not propose imports from the default package: - if (info.getElements().getPackageOf(te).getQualifiedName().length() != 0) { + String fqn = info.getElements().getPackageOf(te).getQualifiedName().toString(); + if (excluder.isExcluded(fqn)) + continue; classes.add(te); } - } Collections.sort(classes, new Comparator() { public int compare(TypeElement te1, TypeElement te2) { return (te1 == te2) ? 0 : te1.getQualifiedName().toString().compareTo(te2.getQualifiedName().toString()); Index: src/org/netbeans/modules/java/editor/imports/JavaFixAllImports.java --- src/org/netbeans/modules/java/editor/imports/JavaFixAllImports.java Base (BASE) +++ src/org/netbeans/modules/java/editor/imports/JavaFixAllImports.java Locally Modified (Based On LOCAL) @@ -321,7 +321,8 @@ private ImportVisitor (CompilationInfo info) { this.info = info; - currentPackage = info.getCompilationUnit().getPackageName().toString(); + ExpressionTree pkg = info.getCompilationUnit().getPackageName(); + currentPackage = pkg != null ? pkg.toString() : ""; imports = new ArrayList(); } Index: src/org/netbeans/modules/java/editor/javadoc/JavadocCompletionQuery.java --- src/org/netbeans/modules/java/editor/javadoc/JavadocCompletionQuery.java Base (BASE) +++ src/org/netbeans/modules/java/editor/javadoc/JavadocCompletionQuery.java Locally Modified (Based On LOCAL) @@ -94,6 +94,7 @@ import org.netbeans.api.java.source.TreeUtilities; import org.netbeans.api.lexer.Token; import org.netbeans.api.lexer.TokenSequence; +import org.netbeans.modules.editor.java.ExcludeCompletion; import org.netbeans.modules.editor.java.JavaCompletionItem; import org.netbeans.modules.editor.java.LazyTypeCompletionItem; import org.netbeans.modules.editor.java.Utilities; @@ -602,10 +603,13 @@ } } - for (String pkgName : jdctx.javac.getClasspathInfo().getClassIndex().getPackageNames(pkgPrefix, true, EnumSet.allOf(ClassIndex.SearchScope.class))) - if (pkgName.length() > 0) + ExcludeCompletion excluder = ExcludeCompletion.getInstance(); + for (String pkgName : jdctx.javac.getClasspathInfo().getClassIndex().getPackageNames(pkgPrefix, true, EnumSet.allOf(ClassIndex.SearchScope.class))){ + if (excluder.isExcluded(pkgName)) + continue; items.add(JavaCompletionItem.createPackageItem(pkgName, substitutionOffset, false)); } + } private void completeThrowsOrPkg(String fqn, String prefix, int substitutionOffset, JavadocContext jdctx) { final Elements elements = jdctx.javac.getElements(); @@ -1006,7 +1010,11 @@ // ClassIndex.NameKind kind = env.isCamelCasePrefix() ? // Utilities.isCaseSensitive() ? ClassIndex.NameKind.CAMEL_CASE : ClassIndex.NameKind.CAMEL_CASE_INSENSITIVE : // Utilities.isCaseSensitive() ? ClassIndex.NameKind.PREFIX : ClassIndex.NameKind.CASE_INSENSITIVE_PREFIX; + ExcludeCompletion excluder = ExcludeCompletion.getInstance(); for(ElementHandle name : controller.getClasspathInfo().getClassIndex().getDeclaredTypes(prefix, kind, EnumSet.allOf(ClassIndex.SearchScope.class))) { + String fqn = name.getQualifiedName(); + if (excluder.isExcluded(fqn)) + continue; LazyTypeCompletionItem item = LazyTypeCompletionItem.create(name, kinds, substitutionOffset, controller.getSnapshot().getSource(), false); // XXX item.isAnnonInner() is package private :-( // if (item.isAnnonInner())