|
Groovy example source code file (ReflectionCompletor.groovy)
The Groovy ReflectionCompletor.groovy source code
package org.codehaus.groovy.tools.shell
import jline.Completor
import org.codehaus.groovy.runtime.InvokerHelper
/**
* Implements the Completor interface to provide competions for
* GroovyShell by using reflection on global variables.
*
* @author <a href="mailto:probabilitytrees@gmail.com">Marty Saxton
*/
class ReflectionCompletor implements Completor {
private Shell shell;
ReflectionCompletor(Shell shell) {
this.shell = shell
}
int complete(String buffer, int cursor, List candidates) {
int identifierStart = findIdentifierStart(buffer, cursor)
String identifierPrefix = identifierStart != -1 ? buffer.substring(identifierStart, cursor) : ""
int lastDot = buffer.lastIndexOf('.')
// if there are no dots, and there is a valid identifier prefix
if (lastDot == -1 ) {
if (identifierStart != -1) {
List myCandidates = findMatchingVariables(identifierPrefix)
if (myCandidates.size() > 0) {
candidates.addAll(myCandidates)
return identifierStart
}
}
}
else {
// there are 1 or more dots
// if ends in a dot, or if there is a valid identifier prefix
if (lastDot == cursor-1 || identifierStart != -1){
// evaluate the part before the dot to get an instance
String instanceRefExpression = buffer.substring(0, lastDot)
def instance = shell.interp.evaluate([instanceRefExpression])
if (instance != null) {
// look for public methods/fields that match the prefix
List myCandidates = getPublicFieldsAndMethods(instance, identifierPrefix)
if (myCandidates.size() > 0) {
candidates.addAll(myCandidates)
return lastDot+1
}
}
}
}
// no candidates
return -1
}
/**
* Parse a buffer to determine the start index of the groovy identifier
* @param buffer the buffer to parse
* @param endingAt the end index with the buffer
* @return the start index of the identifier, or -1 if the buffer
* does not contain a valid identifier that ends at endingAt
*/
int findIdentifierStart(String buffer, int endingAt) {
// if the string is empty then there is no expression
if (endingAt == 0)
return -1
// if the last character is not valid then there is no expression
char lastChar = buffer.charAt(endingAt-1)
if (!Character.isJavaIdentifierPart(lastChar))
return -1
// scan backwards until the beginning of the expression is found
int startIndex = endingAt-1
while (startIndex > 0 && Character.isJavaIdentifierPart(buffer.charAt(startIndex-1)))
--startIndex
return startIndex
}
/**
* Build a list of public fields and methods for an object
* that match a given prefix.
* @param instance the object
* @param prefix the prefix that must be matched
* @return the list of public methods and fields that begin with the prefix
*/
List getPublicFieldsAndMethods(Object instance, String prefix) {
def rv = []
instance.class.fields.each {
if (it.name.startsWith(prefix))
rv << it.name
}
instance.class.methods.each {
if (it.name.startsWith(prefix))
rv << it.name + (it.parameterTypes.length == 0 ? "()" : "(")
}
InvokerHelper.getMetaClass(instance).metaMethods.each {
if (it.name.startsWith(prefix))
rv << it.name + (it.parameterTypes.length == 0 ? "()" : "(")
}
return rv.sort().unique()
}
/**
* Build a list of variables defined in the shell that
* match a given prefix.
* @param prefix the prefix to match
* @return the list of variables that match the prefix
*/
List findMatchingVariables(String prefix) {
def matches = []
for (String varName in shell.interp.context.variables.keySet())
if (varName.startsWith(prefix))
matches << varName
return matches
}
}
Other Groovy examples (source code examples)Here is a short list of links related to this Groovy ReflectionCompletor.groovy source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 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.