
org.fife.rsta.ac.java.PackageMapNode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of languagesupport Show documentation
Show all versions of languagesupport Show documentation
A library adding code completion and other advanced features for Java, JavaScript, Perl, and other languages to RSyntaxTextArea.
/* * 04/04/2015 * * Copyright (C) 2015 Robert Futrell * robert_futrell at users.sourceforge.net * http://fifesoft.com/rsyntaxtextarea * * This library is distributed under a modified BSD license. See the included * RSTALanguageSupport.License.txt file for details. */ package org.fife.rsta.ac.java; import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import org.fife.rsta.ac.java.buildpath.LibraryInfo; import org.fife.rsta.ac.java.classreader.ClassFile; import org.fife.ui.autocomplete.Completion; import org.fife.ui.autocomplete.CompletionProvider; /** * A data structure modeling all classes in a jar or directory, or on a * classpath. It's a recursive mapping of
' character. This should be (the start of) a * fully-qualified class, interface, or enum name. * @param addTo The list to add completion choices to. */ public void addCompletions(LibraryInfo info, CompletionProvider provider, String[] pkgNames, SetString
s to either *Map
s or {@link ClassFile}s (which are lazily created and * may benull
). At each level of the nested map, the string * key is a package name iff its corresponding value is aMap
. * Examine thatMap
's contents to explore the contents of * that package. If the corresponding value is aClassFile
, * then the string key's value is the name of that class. Finally, if * the corresponding value isnull
, then the string key's * value is the name of a class, but its contents have not yet been * loaded for use by the code completion library (ClassFile
s * are lazily loaded to conserve memory). */ public class PackageMapNode { /** * A mapping of sub-package name to the sub-packages and classes under it. */ private SortedMapsubpackages; /** * A mapping of class file names to class files in this package. The * actual {@link ClassFile} values are lazily instantiated, so any map * entry with a value of null
simply has not been created * yet. */ private SortedMapclassFiles; public PackageMapNode() { subpackages = new TreeMap (String.CASE_INSENSITIVE_ORDER); classFiles = new TreeMap (String.CASE_INSENSITIVE_ORDER); } /** * Adds entries for a fully-qualified class name, of the form * "org/fife/util/DynamicIntArray.class"
. This method should * only be called on the "root" node of a package map. * * @param className A fully-qualified class name of the form described * above. */ public void add(String className) { String[] tokens = Util.splitOnChar(className, '/'); PackageMapNode pmn = this; for (int i=0; i. addTo) { PackageMapNode map = this; for (int i=0; i largest valid class char // First add completions for matching subpackage names. SortedMap subpackages = map.subpackages.subMap(fromKey, toKey); if (!subpackages.isEmpty()) { StringBuilder sb = new StringBuilder(); for (int j=0; j entry : subpackages.entrySet()) { String completionPackageName = entry.getKey(); String text = earlierPackages + completionPackageName; addTo.add(new PackageNameCompletion(provider, text, fromKey)); } } // Next, add completions for matching class names SortedMap sm = map.classFiles.subMap(fromKey, toKey); for (Map.Entry entry : sm.entrySet()) { String key = entry.getKey(); ClassFile cf = entry.getValue(); // The ClassFile may have already been loaded for this one if (cf != null) { boolean inPkg = false; // TODO: Pass me in if (inPkg || org.fife.rsta.ac.java.classreader.Util.isPublic(cf.getAccessFlags())) { addTo.add(new ClassCompletion(provider, cf)); } } // If the ClassFile isn't yet cached else { String[] items = new String[pkgNames.length]; System.arraycopy(pkgNames, 0, items, 0, pkgNames.length-1); items[items.length-1] = key; cf = getClassEntry(info, items); if (cf!=null) { boolean inPkg = false; // TODO: Pass me in if (inPkg || org.fife.rsta.ac.java.classreader.Util.isPublic(cf.getAccessFlags())) { addTo.add(new ClassCompletion(provider, cf)); } } else { // This should never happen - class name without a ClassFile } } } } /** * Removes the cache of all ClassFile
s from this package * map. * * @return The number of class file entries removed. */ public int clearClassFiles() { return clearClassFilesImpl(this); } private int clearClassFilesImpl(PackageMapNode pmn) { int clearedCount = 0; for (Map.Entryentry : pmn.classFiles.entrySet()) { entry.setValue(null); clearedCount++; } for (Map.Entry entry : pmn.subpackages.entrySet()) { clearedCount += clearClassFilesImpl(entry.getValue()); } return clearedCount; } public boolean containsClass(String className) { String[] items = className.split("\\."); PackageMapNode pmn = this; for (int i=0; i addTo, String[] pkgs, boolean inPkg) { PackageMapNode map = this; for (int i=0; i entry : map.classFiles.entrySet()) { ClassFile cf = entry.getValue(); if (cf == null) { StringBuilder name = new StringBuilder(pkgs[0]); for (int j=1; j map belongs to (i.e. * all levels of packages scanned before this one), separated by * ' /
'. * @param addTo The list to add any matchingClassFile
s to. */ void getClassesWithNamesStartingWith(LibraryInfo info, String prefix, String currentPkg, ListaddTo) { final int prefixLen = prefix.length(); for (Map.Entry children : subpackages.entrySet()) { String key = children.getKey(); PackageMapNode child = children.getValue(); child.getClassesWithNamesStartingWith(info, prefix, currentPkg + key + "/", addTo); } for (Map.Entry cfEntry : classFiles.entrySet()) { // If value is null, we only lazily create the ClassFile if // necessary (i.e. if the class name does match what they've // typed). String className = cfEntry.getKey(); if (className.regionMatches(true, 0, prefix, 0, prefixLen)) { ClassFile cf = cfEntry.getValue(); if (cf==null) { String fqClassName = currentPkg + className + ".class"; try { cf = info.createClassFile(fqClassName); cfEntry.setValue(cf); // Update the map } catch (IOException ioe) { ioe.printStackTrace(); } } if (cf!=null) { // possibly null if IOException above addTo.add(cf); } } } } private static final void possiblyAddTo(Collection addTo, ClassFile cf, boolean inPkg) { if (inPkg || org.fife.rsta.ac.java.classreader.Util.isPublic(cf.getAccessFlags())) { addTo.add(cf); } } }
© 2015 - 2025 Weber Informatics LLC | Privacy Policy