Index: ui/org/eclipse/jdt/internal/ui/JavaUIMessages.properties =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/JavaUIMessages.properties,v retrieving revision 1.102 diff -u -r1.102 JavaUIMessages.properties --- ui/org/eclipse/jdt/internal/ui/JavaUIMessages.properties 3 May 2002 15:25:07 -0000 1.102 +++ ui/org/eclipse/jdt/internal/ui/JavaUIMessages.properties 5 May 2002 03:54:14 -0000 @@ -438,6 +438,7 @@ WorkInProgressPreferencePage.description=&Exposed features as work is in progress: WorkInProgressPreferencePage.codeassist.experimental=&Fill argument names on method completion +WorkInProgressPreferencePage.codeassist.experimental.guessparameters=&Guess method parameters on method completion WorkInProgressPreferencePage.packagesView.pkgNamePatternForPackagesView.text= &Replace package name fragments (xxx.) in packages view with: WorkInProgressPreferencePage.packagesView.pkgNamePatternForPackagesView.tooltip= The pattern may contain exactly one digit n\nwhich is replaced by the first n characters\nof each package name fragment Index: ui/org/eclipse/jdt/internal/ui/preferences/WorkInProgressPreferencePage.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/WorkInProgressPreferencePage.java,v retrieving revision 1.17 diff -u -r1.17 WorkInProgressPreferencePage.java --- ui/org/eclipse/jdt/internal/ui/preferences/WorkInProgressPreferencePage.java 3 May 2002 12:37:41 -0000 1.17 +++ ui/org/eclipse/jdt/internal/ui/preferences/WorkInProgressPreferencePage.java 5 May 2002 03:54:14 -0000 @@ -63,7 +63,17 @@ parent ); addField(boolEditor); - + + + BooleanFieldEditor expGuessEditor= new BooleanFieldEditor( + ExperimentalPreference.CODE_ASSIST_EXPERIMENTAL_GUESS_PARAM, + JavaUIMessages.getString("WorkInProgressPreferencePage.codeassist.experimental.guessparameters"), //$NON-NLS-1$ + parent + ); + + addField(expGuessEditor); + + boolEditor= new BooleanFieldEditor( PREF_SYNC_OUTLINE_ON_CURSOR_MOVE, "Synchronize &outline selection on cursor move", //$NON-NLS-1$ Index: ui/org/eclipse/jdt/internal/ui/text/java/ExperimentalPreference.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ExperimentalPreference.java,v retrieving revision 1.1 diff -u -r1.1 ExperimentalPreference.java --- ui/org/eclipse/jdt/internal/ui/text/java/ExperimentalPreference.java 20 Nov 2001 11:02:04 -0000 1.1 +++ ui/org/eclipse/jdt/internal/ui/text/java/ExperimentalPreference.java 5 May 2002 03:54:15 -0000 @@ -11,8 +11,14 @@ public static final String CODE_ASSIST_EXPERIMENTAL= "org.eclipse.jdt.ui.text.codeassist.experimental"; //$NON-NLS-1$ + public static final String CODE_ASSIST_EXPERIMENTAL_GUESS_PARAM = "org.eclipse.jdt.ui.text.codeassist.experimental.guessparameters"; //$NON-NLS-1$ + public static boolean fillArgumentsOnMethodCompletion(IPreferenceStore store) { return store.getBoolean(CODE_ASSIST_EXPERIMENTAL); + } + + public static boolean guessArgumentsOnMethodCompletion(IPreferenceStore store) { + return store.getBoolean(CODE_ASSIST_EXPERIMENTAL_GUESS_PARAM); } } Index: ui/org/eclipse/jdt/internal/ui/text/java/ExperimentalResultCollector.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/ExperimentalResultCollector.java,v retrieving revision 1.12 diff -u -r1.12 ExperimentalResultCollector.java --- ui/org/eclipse/jdt/internal/ui/text/java/ExperimentalResultCollector.java 12 Apr 2002 15:03:36 -0000 1.12 +++ ui/org/eclipse/jdt/internal/ui/text/java/ExperimentalResultCollector.java 5 May 2002 03:54:15 -0000 @@ -4,49 +4,349 @@ * (c) Copyright IBM Corp. 2000, 2001. * All Rights Reserved. */ - + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jdt.core.CompletionRequestorAdapter; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.ICompletionRequestor; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.internal.codeassist.CompletionEngine; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import org.eclipse.jdt.internal.compiler.util.CharOperation; +import org.eclipse.jdt.internal.core.CompletionRequestorWrapper; +import org.eclipse.jdt.internal.core.JavaProject; +import org.eclipse.jdt.internal.core.NameLookup; +import org.eclipse.jdt.internal.core.SearchableEnvironment; +import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jface.text.ITextViewer; /** * Bin to collect the proposal of the infrastructure on code assist in a java text. */ public class ExperimentalResultCollector extends ResultCollector { + + private final static boolean DEBUG = false; + private ITextViewer fViewer; + + /** + * This is an ICompletionRequester that tracks all possible local/member variables to be used as proposals.\ + */ + private VariableTracker varTracker = new VariableTracker(); + + /** + * Track variables by priority: Local variables get highest priority, member variables second highest + * This is how we determine how "close" in a java-scope sense a proposal is to the point of the code completion + * Currently we only have two levels - local and field. There is no API to distinguish scope at a finer level + * using the ICompletionRequester + */ + public static final int NUM_PRIORITIES = 3; + + public static final int LOCAL_PRIORITY = 0; + // This does no appear to be used... what would trigger "acceptVariable" -- putting it here for now?? + public static final int VARIABLE_PRIORITY = 1; + + public static final int FIELD_PRIORITY = 2; + + // All possible variable proposals based on local/member variables... + private List[] parameterProposals = new List[NUM_PRIORITIES]; + + private boolean guessParams = ExperimentalPreference.guessArgumentsOnMethodCompletion(JavaPlugin.getDefault().getPreferenceStore()); + + + private class Variable { + + char[] typePackage = null; + char[] typeName = null; + char[] name = null; + + public String toString() { + return "LocalVariable name = " + new String(name) + " type package = " + + new String(typePackage) + " type = " + new String(typeName); + } + + + + } + + /** + * This inner class triggers a second code-completion that will track all local ane member variables for later + * use as a parameter proposal. + * + * @author Andrew McCullough + */ + private class VariableTracker extends CompletionRequestorAdapter { + + + + /** + * @see ICompletionRequestor#acceptField(char[], char[], char[], char[], char[], char[], int, int, int, int) + */ + public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name,char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) { + + addVariable(FIELD_PRIORITY, typePackageName, typeName, name); + } + + + /** + * @see ICompletionRequestor#acceptLocalVariable(char[], char[], char[], int, int, int, int) + */ + public void acceptLocalVariable(char[] name,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd,int relevance) { + + addVariable(LOCAL_PRIORITY, typePackageName, typeName, name); + + } + + /** + * @see ICompletionRequestor#acceptVariableName(char[], char[], char[], char[], int, int, int) + */ + public void acceptVariableName(char[] typePackageName,char[] typeName,char[] name,char[] completionName,int completionStart,int completionEnd,int relevance) { + + addVariable(VARIABLE_PRIORITY, typePackageName, typeName, name); + } + + + private void addVariable(int priority, char[] typePackageName, char[] typeName, char[] name) { + + if (DEBUG) { + System.out.println("adding local variable"); + System.out.println("priority: " + priority); + System.out.println("package : " + new String(typePackageName)); + System.out.println("type : " + new String(typeName)); + System.out.println("name : " + new String(name)); + } + + Variable proposal = new Variable(); + + proposal.typePackage = typePackageName; + proposal.typeName = typeName; + proposal.name = name; + + + if (DEBUG) System.out.println("adding local variable: " + proposal); + + parameterProposals[priority].add(proposal); + } + + } + + + + + + public ExperimentalResultCollector() { + + for (int i = 0; i < parameterProposals.length; i++) { + parameterProposals[i] = new ArrayList(); + + } + } + protected JavaCompletionProposal createMethodCallCompletion(char[] declaringTypeName, char[] name, char[][] parameterTypeNames, char[][] parameterNames, char[] returnTypeName, char[] completionName, int modifiers, int start, int end, int relevance) { + + // the packages are being ignored... so I can't do anything about them now unless superclass changes + // char[][] parameterPackages should/could be a parameter to this call if ResultCollector is modified.. + JavaCompletionProposal original= super.createMethodCallCompletion(declaringTypeName, name, parameterTypeNames, parameterNames, returnTypeName, completionName, modifiers, start, end, relevance); + // XXX hack to handle empty code completion - if ((completionName.length == 0) || ((completionName.length == 1) && completionName[0] == ')')) + if ((completionName.length == 0) + || ((completionName.length == 1) && completionName[0] == ')')) return original; + + + if (guessParams) { + + for (int i = 0; i < parameterNames.length; i++) { + parameterNames[i] = findMatchingVariable(TypeConstants.NoChar, parameterTypeNames[i], parameterNames[i]); + + } + } - int count= parameterNames.length; - int[] offsets= new int[count]; - int[] lengths= new int[count]; + int count = parameterNames.length; + int[] offsets = new int[count]; + int[] lengths = new int[count]; - StringBuffer buffer= new StringBuffer(); + StringBuffer buffer = new StringBuffer(); buffer.append(name); buffer.append('('); - for (int i= 0; i != count; i++) { - if (i != 0) - buffer.append(", "); //$NON-NLS-1$ - - offsets[i]= buffer.length(); + + // build it.. + for (int i = 0; i != count; i++) { + if (i != 0) { + buffer.append(", "); + } + offsets[i] = buffer.length(); buffer.append(parameterNames[i]); - lengths[i]= buffer.length() - offsets[i]; + lengths[i] = buffer.length() - offsets[i]; } + buffer.append(')'); return new ExperimentalProposal(buffer.toString(), start, end - start, original.getImage(), original.getDisplayString(), offsets, lengths, fViewer, relevance); + + } + + + + + /** + * Find a local or member variable that matched the type of the parameter... + * + */ + private char[] findMatchingVariable(char[] typePackage, char[] typeName, char[] defaultName) { + + if (typeName == null || typeName.length == 0) { + return defaultName; + } + + if (DEBUG) { + System.out.println("Searching for type: " + new String(typeName)); + for (int i = 0; i < parameterProposals.length; i++) { + System.out.println("Proposal List [" + i + "]" + parameterProposals[i]); + } + } + + + for (int i = 0; i < parameterProposals.length; ++i) { + + char[] result = searchForVariable(parameterProposals[i], typePackage, typeName); + if (result != null) { + return result; + } + } + + + // no match found.. + return defaultName; + } + + /** + * Search a list of variables for a match, return null if no match found + */ + private char[] searchForVariable(List variableList, char[] typePackage, char[] typeName) { + + // traverse the lists in reverse order, since it is empirically true that the code + // completion engine returns variables in the order they are found -- and we want to find + // matches closest to the codecompletion point.. No idea if this behavior is garaunteed. + + int numVariables = variableList.size(); + + for (int variableIndex = numVariables - 1; variableIndex >= 0; --variableIndex) { + + Variable variable = (Variable)variableList.get(variableIndex); + if (isMatch(variable, typePackage, typeName)) { + return variable.name; + } + } + + // return null if no matched found... + return null; + } /** - * Sets the viewer. - * @param viewer The viewer to set + * Return true if this variable is a match for this type... */ + private boolean isMatch(Variable variable, char[] typePackage, char[] typeName) { + + // this should look at fully qualified name, but currently the ComepletionEngine is not + // sending the packag names... + + // hack to handle lack of packages.. if either package is empty, don't use package names + // should have the helpful side effect of working for primitives too + + if (typePackage == null || variable.typePackage == null || + typePackage.length == 0 || variable.typePackage.length == 0) { + + if (CharOperation.equals(typeName, variable.typeName)) { + if (DEBUG) System.out.println("Found (no-package) match: " + variable); + return true; + } + + } else /* we have package names for the types, do a fully qualified match */ { + + // we're not always getting packages for types... + // we don't need the ".", but it makes the debug statements pretty... + + + if ( CharOperation.equals(typeName, variable.typeName) && + CharOperation.equals(typePackage, variable.typePackage) ) { + + if (DEBUG) System.out.println("Found match: " + variable); + + return true; + } + + } + // no match found + return false; + + } + + public void setViewer(ITextViewer viewer) { - fViewer= viewer; + fViewer = viewer; + } + + + public void reset(int codeAssistOffset, IJavaProject jproject, ICompilationUnit cu) { + + super.reset(codeAssistOffset, jproject, cu); + + // Clear out all the old variables.. reinitialize through the VariableTracker + + // I think we need to recheck this preference... + guessParams = ExperimentalPreference.guessArgumentsOnMethodCompletion(JavaPlugin.getDefault().getPreferenceStore()); + + if (!guessParams) { + return; + } + + + // Clear old variables... + for (int i = 0; i < parameterProposals.length; i++) { + List proposalList = parameterProposals[i]; + proposalList.clear(); + + } + + try { + + // find some whitepace to start our variable-finding code complete from. + // this allows the VariableTracker to find all available variables (no prefix to match for the code completion) + + // Is there a faster/better way to do this? + String source = cu.getSource(); + + int charIndex = codeAssistOffset - 1; + while ( !Character.isWhitespace(source.charAt(charIndex)) ) { + + charIndex = charIndex - 1; + + } + + // Trigger the code completion engine to call the VariableTracker + cu.codeComplete(charIndex, varTracker); + + } catch (StringIndexOutOfBoundsException strIndx) { + // just eat it we ran off the edge of the CU... + JavaPlugin.log(strIndx); + + } catch (JavaModelException jme) { + JavaPlugin.log(jme); + } + } + -} +} \ No newline at end of file