@ -24,7 +24,11 @@ import javax.swing.text.Segment;
import javax.xml.parsers.ParserConfigurationException ;
import javax.xml.parsers.ParserConfigurationException ;
import javax.xml.parsers.SAXParser ;
import javax.xml.parsers.SAXParser ;
import javax.xml.parsers.SAXParserFactory ;
import javax.xml.parsers.SAXParserFactory ;
import com.fr.log.FineLoggerFactory ;
import org.xml.sax.SAXException ;
import org.xml.sax.SAXException ;
import org.xml.sax.SAXNotRecognizedException ;
import org.xml.sax.SAXNotSupportedException ;
/ * *
/ * *
@ -81,10 +85,10 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
/ * *
/ * *
* Returns the text just before the current caret position that could be
* Returns the text just before the current caret position that could be
* the start of something auto - completable . < p >
* the start of something auto - completable . < p >
*
* < p >
* This method returns all characters before the caret that are matched
* This method returns all characters before the caret that are matched
* by { @link # isValidChar ( char ) } .
* by { @link # isValidChar ( char ) } .
*
* < p >
* { @inheritDoc }
* { @inheritDoc }
* /
* /
public String getAlreadyEnteredText ( JTextComponent comp ) {
public String getAlreadyEnteredText ( JTextComponent comp ) {
@ -96,7 +100,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
int index = root . getElementIndex ( dot ) ;
int index = root . getElementIndex ( dot ) ;
Element elem = root . getElement ( index ) ;
Element elem = root . getElement ( index ) ;
int start = elem . getStartOffset ( ) ;
int start = elem . getStartOffset ( ) ;
int len = dot - start ;
int len = dot - start ;
try {
try {
doc . getText ( start , len , seg ) ;
doc . getText ( start , len , seg ) ;
} catch ( BadLocationException ble ) {
} catch ( BadLocationException ble ) {
@ -106,13 +110,13 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
int segEnd = seg . offset + len ;
int segEnd = seg . offset + len ;
start = segEnd - 1 ;
start = segEnd - 1 ;
while ( start > = seg . offset & & isValidChar ( seg . array [ start ] ) ) {
while ( start > = seg . offset & & isValidChar ( seg . array [ start ] ) ) {
start - - ;
start - - ;
}
}
start + + ;
start + + ;
len = segEnd - start ;
len = segEnd - start ;
return len = = 0 ? EMPTY_STRING : new String ( seg . array , start , len ) ;
return len = = 0 ? EMPTY_STRING : new String ( seg . array , start , len ) ;
}
}
@ -123,7 +127,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
public List < Completion > getCompletionsAt ( JTextComponent tc , Point p ) {
public List < Completion > getCompletionsAt ( JTextComponent tc , Point p ) {
int offset = tc . viewToModel ( p ) ;
int offset = tc . viewToModel ( p ) ;
if ( offset < 0 | | offset > = tc . getDocument ( ) . getLength ( ) ) {
if ( offset < 0 | | offset > = tc . getDocument ( ) . getLength ( ) ) {
lastCompletionsAtText = null ;
lastCompletionsAtText = null ;
return lastParameterizedCompletionsAt = null ;
return lastParameterizedCompletionsAt = null ;
}
}
@ -138,25 +142,25 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
try {
try {
doc . getText ( start , end - start , s ) ;
doc . getText ( start , end - start , s ) ;
// Get the valid chars before the specified offset.
// Get the valid chars before the specified offset.
int startOffs = s . offset + ( offset - start ) - 1 ;
int startOffs = s . offset + ( offset - start ) - 1 ;
while ( startOffs > = s . offset & & isValidChar ( s . array [ startOffs ] ) ) {
while ( startOffs > = s . offset & & isValidChar ( s . array [ startOffs ] ) ) {
startOffs - - ;
startOffs - - ;
}
}
// Get the valid chars at and after the specified offset.
// Get the valid chars at and after the specified offset.
int endOffs = s . offset + ( offset - start ) ;
int endOffs = s . offset + ( offset - start ) ;
while ( endOffs < s . offset + s . count & & isValidChar ( s . array [ endOffs ] ) ) {
while ( endOffs < s . offset + s . count & & isValidChar ( s . array [ endOffs ] ) ) {
endOffs + + ;
endOffs + + ;
}
}
int len = endOffs - startOffs - 1 ;
int len = endOffs - startOffs - 1 ;
if ( len < = 0 ) {
if ( len < = 0 ) {
return lastParameterizedCompletionsAt = null ;
return lastParameterizedCompletionsAt = null ;
}
}
String text = new String ( s . array , startOffs + 1 , len ) ;
String text = new String ( s . array , startOffs + 1 , len ) ;
if ( text . equals ( lastCompletionsAtText ) ) {
if ( text . equals ( lastCompletionsAtText ) ) {
return lastParameterizedCompletionsAt ;
return lastParameterizedCompletionsAt ;
@ -188,7 +192,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
// If this provider doesn't support parameterized completions,
// If this provider doesn't support parameterized completions,
// bail out now.
// bail out now.
char paramListStart = getParameterListStart ( ) ;
char paramListStart = getParameterListStart ( ) ;
if ( paramListStart = = 0 ) {
if ( paramListStart = = 0 ) {
return list ; // null
return list ; // null
}
}
@ -200,7 +204,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
Element elem = root . getElement ( line ) ;
Element elem = root . getElement ( line ) ;
int offs = elem . getStartOffset ( ) ;
int offs = elem . getStartOffset ( ) ;
int len = dot - offs - 1 /*paramListStart.length()*/ ;
int len = dot - offs - 1 /*paramListStart.length()*/ ;
if ( len < = 0 ) { // Not enough chars on line for a method.
if ( len < = 0 ) { // Not enough chars on line for a method.
return list ; // null
return list ; // null
}
}
@ -211,27 +215,27 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
// Get the identifier preceding the '(', ignoring any whitespace
// Get the identifier preceding the '(', ignoring any whitespace
// between them.
// between them.
offs = s . offset + len - 1 ;
offs = s . offset + len - 1 ;
while ( offs > = s . offset & & Character . isWhitespace ( s . array [ offs ] ) ) {
while ( offs > = s . offset & & Character . isWhitespace ( s . array [ offs ] ) ) {
offs - - ;
offs - - ;
}
}
int end = offs ;
int end = offs ;
while ( offs > = s . offset & & isValidChar ( s . array [ offs ] ) ) {
while ( offs > = s . offset & & isValidChar ( s . array [ offs ] ) ) {
offs - - ;
offs - - ;
}
}
String text = new String ( s . array , offs + 1 , end - offs ) ;
String text = new String ( s . array , offs + 1 , end - offs ) ;
// Get a list of all Completions matching the text, but then
// Get a list of all Completions matching the text, but then
// narrow it down to just the ParameterizedCompletions.
// narrow it down to just the ParameterizedCompletions.
List < Completion > l = getCompletionByInputText ( text ) ;
List < Completion > l = getCompletionByInputText ( text ) ;
if ( l ! = null & & ! l . isEmpty ( ) ) {
if ( l ! = null & & ! l . isEmpty ( ) ) {
for ( int i = 0 ; i < l . size ( ) ; i + + ) {
for ( int i = 0 ; i < l . size ( ) ; i + + ) {
Object o = l . get ( i ) ;
Object o = l . get ( i ) ;
if ( o instanceof ParameterizedCompletion ) {
if ( o instanceof ParameterizedCompletion ) {
if ( list = = null ) {
if ( list = = null ) {
list = new ArrayList < ParameterizedCompletion > ( 1 ) ;
list = new ArrayList < ParameterizedCompletion > ( 1 ) ;
}
}
list . add ( ( ParameterizedCompletion ) o ) ;
list . add ( ( ParameterizedCompletion ) o ) ;
}
}
}
}
}
}
@ -264,7 +268,7 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
* @return Whether the character is valid .
* @return Whether the character is valid .
* /
* /
protected boolean isValidChar ( char ch ) {
protected boolean isValidChar ( char ch ) {
return Character . isLetterOrDigit ( ch ) | | ch = = '_' ;
return Character . isLetterOrDigit ( ch ) | | ch = = '_' ;
}
}
@ -314,6 +318,15 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
//long start = System.currentTimeMillis();
//long start = System.currentTimeMillis();
SAXParserFactory factory = SAXParserFactory . newInstance ( ) ;
SAXParserFactory factory = SAXParserFactory . newInstance ( ) ;
try {
factory . setFeature ( "http://apache.org/xml/features/disallow-doctype-decl" , true ) ;
factory . setFeature ( "http://xml.org/sax/features/external-general-entities" , false ) ;
factory . setFeature ( "http://xml.org/sax/features/external-parameter-entities" , false ) ;
factory . setFeature ( "http://apache.org/xml/features/nonvalidating/load-external-dtd" , false ) ;
} catch ( ParserConfigurationException | SAXNotSupportedException | SAXNotRecognizedException e ) {
FineLoggerFactory . getLogger ( ) . warn ( e . getMessage ( ) , e ) ;
}
factory . setValidating ( true ) ;
factory . setValidating ( true ) ;
CompletionXMLParser handler = new CompletionXMLParser ( this , cl ) ;
CompletionXMLParser handler = new CompletionXMLParser ( this , cl ) ;
BufferedInputStream bin = new BufferedInputStream ( in ) ;
BufferedInputStream bin = new BufferedInputStream ( in ) ;
@ -323,10 +336,10 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
List < Completion > completions = handler . getCompletions ( ) ;
List < Completion > completions = handler . getCompletions ( ) ;
addCompletions ( completions ) ;
addCompletions ( completions ) ;
char startChar = handler . getParamStartChar ( ) ;
char startChar = handler . getParamStartChar ( ) ;
if ( startChar ! = 0 ) {
if ( startChar ! = 0 ) {
char endChar = handler . getParamEndChar ( ) ;
char endChar = handler . getParamEndChar ( ) ;
String sep = handler . getParamSeparator ( ) ;
String sep = handler . getParamSeparator ( ) ;
if ( endChar ! = 0 & & sep ! = null & & sep . length ( ) > 0 ) { // Sanity
if ( endChar ! = 0 & & sep ! = null & & sep . length ( ) > 0 ) { // Sanity
setParameterizedCompletionParams ( startChar , sep , endChar ) ;
setParameterizedCompletionParams ( startChar , sep , endChar ) ;
}
}
}
}
@ -353,12 +366,11 @@ public class DefaultCompletionProvider extends AbstractCompletionProvider {
public void loadFromXML ( String resource ) throws IOException {
public void loadFromXML ( String resource ) throws IOException {
ClassLoader cl = getClass ( ) . getClassLoader ( ) ;
ClassLoader cl = getClass ( ) . getClassLoader ( ) ;
InputStream in = cl . getResourceAsStream ( resource ) ;
InputStream in = cl . getResourceAsStream ( resource ) ;
if ( in = = null ) {
if ( in = = null ) {
File file = new File ( resource ) ;
File file = new File ( resource ) ;
if ( file . isFile ( ) ) {
if ( file . isFile ( ) ) {
in = new FileInputStream ( file ) ;
in = new FileInputStream ( file ) ;
}
} else {
else {
throw new IOException ( "No such resource: " + resource ) ;
throw new IOException ( "No such resource: " + resource ) ;
}
}
}
}