|
What this is
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-2000 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.editor.ext.java; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import javax.swing.text.BadLocationException; import org.netbeans.editor.BaseDocument; import org.netbeans.editor.TokenProcessor; import org.netbeans.editor.TokenID; import org.netbeans.editor.TokenContextPath; import org.netbeans.editor.Syntax; import java.util.List; import java.util.Map; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; import org.netbeans.editor.Utilities; /** * Mapping of colorings to particular token types * * @author Miloslav Metelka * @version 1.00 */ public class JavaImport implements TokenProcessor { /** Initial length of the document to be scanned. It should be big enough * so that only one pass is necessary. If the initial section is too * long, then this value is doubled and the whole parsing restarted. */ private static final int INIT_SCAN_LEN = 4096; private static final int INIT = 0; // at the line begining before import kwd private static final int AFTER_IMPORT = 1; // right after the import kwd private static final int INSIDE_EXP = 2; // inside import expression // inside import expression mixed from several different tokens // exp string buffer is used in this case private static final int INSIDE_MIXED_EXP = 3; /** Short names to classes map */ private HashMap name2Class = new HashMap(501); private char[] buffer; private ArrayList infoList = new ArrayList(); /** Current state of the imports parsing */ private int state; /** Whether parsing package statement instead of import statment. * They have similair syntax so only this flag distinguishes them. */ private boolean parsingPackage; /** Start of the whole import statement */ private int startPos; /** Start position of the particular import expression */ private int expPos; private boolean eotReached; private StringBuffer exp = new StringBuffer(); /** Whether the star was found at the end of package expression */ private boolean star; /** The end of the import section. Used for optimized reparsing */ private int posEndOfImportSection; /** Disable reparing when change is not in import section */ private boolean disableReparsing; JavaSyntax debugSyntax = new JavaSyntax(); // !!! debugging syntax private int startOffset; private int endOffset; private int lastStartOffset = -1; private int lastEndOffset = -1; private boolean firstFiring = true; private EventListenerList listenerList = new EventListenerList(); private int bufferStartOffset; private JavaSyntaxSupport sup; private boolean useCustomImports = false; public JavaImport(JavaSyntaxSupport sup) { this.sup = sup; posEndOfImportSection = -1; disableReparsing = false; } public synchronized void update(BaseDocument doc) { // optimalization of the parsing if (disableReparsing) return; if (useCustomImports) return; // bugfix - deadlock #43192 initJavaLangPkg(); doc.readLock(); try { int scanLen = INIT_SCAN_LEN; int docLen = doc.getLength(); boolean wholeDoc = false; do { if (scanLen >= docLen) { scanLen = docLen; wholeDoc = true; } eotReached = false; init(); try { doc.getSyntaxSupport().tokenizeText(this, 0, scanLen, false); } catch (BadLocationException e) { Utilities.annotateLoggable(e); } scanLen *= 4; // increase the scanning size } while (!wholeDoc && eotReached); if (lastEndOffset!=endOffset || lastStartOffset!=startOffset){ lastStartOffset = startOffset; lastEndOffset = endOffset; if (!firstFiring) { fireChange(new ChangeEvent(this)); } } } finally { doc.readUnlock(); } buffer = null; } /** Appends imports from customImportsMap to ImportsMap * If customImportsMap is null, ImportsMap will be cleared and * set up with default java.lang.* classes */ public void appendCustomImportsMap(Map customImportsMap){ if (useCustomImports == false){ initJavaLangPkg(); } useCustomImports = true; if (customImportsMap == null){ initJavaLangPkg(); }else{ name2Class.putAll(customImportsMap); } } /** Gets unmodifiable imports map */ public Map getImportsMap(){ return Collections.unmodifiableMap(name2Class); } private void initJavaLangPkg(){ name2Class.clear(); // clear current mappings // add java.lang package by default JCPackage pkg = sup.getFinder().getExactPackage("java.lang"); // NOI18N if (pkg != null) { JCClass[] classes = pkg.getClasses(); for (int i = 0; i < classes.length; i++) { name2Class.put(classes[i].getName(), classes[i]); } } } protected void init() { exp.setLength(0); state = INIT; star = false; parsingPackage = false; startOffset = Integer.MAX_VALUE; endOffset = Integer.MIN_VALUE; infoList.clear(); } private JCClass checkForInnerClass(String innerClassName){ Iterator it = name2Class.values().iterator(); while(it.hasNext()){ JCClass cls = (JCClass)it.next(); if (cls != null && cls.getFullName().endsWith("."+innerClassName)){ //NOI18N return cls; } } return null; } /** Returns innerclasses from import section */ public List getInnerClasses(){ Iterator it = name2Class.values().iterator(); List ret = new ArrayList(); while(it.hasNext()){ JCClass cls = (JCClass)it.next(); if (cls != null && cls.getName().indexOf(".") >0 ){ //NOI18N ret.add(cls); } } return ret; } public int getStartOffset(){ return (startOffset == Integer.MAX_VALUE) ? -1 : startOffset; } public int getEndOffset(){ return (endOffset == Integer.MIN_VALUE) ? -1 : endOffset; } public boolean isEmpty() { return (getStartOffset() == -1); // should be sufficient test } public void addChangeListener(ChangeListener l) { listenerList.add(ChangeListener.class, l); } public void removeChangeListener(ChangeListener l) { listenerList.remove(ChangeListener.class, l); } private void fireChange(ChangeEvent evt) { Object[] listeners = listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == ChangeListener.class) { ((ChangeListener)listeners[i + 1]).stateChanged(evt); } } } public JCClass getClazz(String className) { JCFinder finder = sup.getFinder(); JCClass ret = (JCClass)name2Class.get(className);// first try package scope if (ret == null) ret = checkForInnerClass(className);// second try package scopes innerclasses if (ret == null) { ret = finder.getExactClass(className); }else{ if (finder.getExactClass(ret.getFullName()) != null){ // get updated class (#23649) ret = finder.getExactClass(ret.getFullName()); } } return ret; } protected void packageStatementFound(int packageStartPos, int packageEndPos, String packageExp) { JCPackage pkg = sup.getFinder().getExactPackage(packageExp); if (pkg != null) { JCClass[] classes = pkg.getClasses(); for (int i = 0; i < classes.length; i++) { name2Class.put(classes[i].getName(), classes[i]); } } } protected void importStatementFound(int importStartPos, int importEndPos, String importExp, boolean starAtEnd) { if (importStartPos < startOffset) startOffset = importStartPos; if (importEndPos > endOffset) endOffset = importEndPos; JCFinder finder = sup.getFinder(); Info info = new Info(importStartPos, importEndPos, starAtEnd); JCClass cls = finder.getExactClass(importExp); if (cls != null) { info.cls = cls; if (star) { // !!! dodelat } else { // only this single class name2Class.put(cls.getName(), cls); } } else { // not a direct class, try package JCPackage pkg = finder.getExactPackage(importExp); if (pkg != null) { info.pkg = pkg; if (starAtEnd) { // only useful with star JCClass[] classes = pkg.getClasses(); for (int i = 0; i < classes.length; i++) { name2Class.put(classes[i].getName(), classes[i]); } } } else { // not package, will be class String pkgName = importExp; String simplePkgName = null; int ind; while((ind = pkgName.lastIndexOf('.')) >= 0) { pkgName = pkgName.substring(0, ind); if (simplePkgName == null) { simplePkgName = pkgName; } /* * Removing this heuristic because of the bug #31481 * pkg = finder.getExactPackage(pkgName); if (pkg != null) { // found valid package, but unknown class cls = JavaCompletion.getSimpleClass(importExp, pkgName.length()); info.cls = cls; info.unknownImport=importExp; if (star) { // don't add in this case, can change in the future } else { name2Class.put(cls.getName(), cls); } break; } **/ } if (cls == null) { // didn't found a direct package, assume last is class name if (simplePkgName != null) { // at least one dot in importExp cls = JavaCompletion.getSimpleClass(importExp, simplePkgName.length()); if (star) { // don't add in this case, can change in the future } else { name2Class.put(cls.getName(), cls); } } } } } if ((info.cls==null) && (info.pkg==null)) { info.unknownImport=importExp; } infoList.add(info); } /** Returns true if className is in import, but in a package, that hasn't updated DB */ public boolean isUnknownImport(String className){ for(int i = 0; i |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
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.