blob: cc06de3831a3177be80cf78b88abbb1195f63303 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.text.tests.contentassist;
import java.util.Hashtable;
import junit.framework.TestCase;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.swt.graphics.Point;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.text.IJavaPartitions;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import org.eclipse.jdt.internal.ui.text.java.JavaCompletionProcessor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
import org.eclipse.jdt.internal.corext.template.java.CodeTemplateContextType;
import org.eclipse.jdt.testplugin.TestOptions;
import org.eclipse.jdt.text.tests.performance.EditorTestHelper;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.texteditor.ITextEditor;
public class AbstractCompletionTest extends TestCase {
protected static String suiteName(Class fqn) {
String name= fqn.toString();
name= name.substring(name.lastIndexOf('.') + 1);
return name;
}
protected static final String CARET= "|";
private ICompilationUnit fCU;
private JavaEditor fEditor;
private String fBeforeImports;
private String fAfterImports;
private String fMembers;
private String fLocals;
private char fTrigger;
private boolean fWaitBeforeCompleting;
protected void setUp() throws Exception {
Hashtable options= TestOptions.getDefaultOptions();
configureCoreOptions(options);
JavaCore.setOptions(options);
IPreferenceStore store= getJDTUIPrefs();
store.setValue(PreferenceConstants.CODEGEN_ADD_COMMENTS, true);
store.setValue(PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS, false);
store.setValue(PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES, false);
store.setValue(PreferenceConstants.CODEASSIST_ADDIMPORT, true);
store.setValue(PreferenceConstants.CODEASSIST_INSERT_COMPLETION, true);
StubUtility.setCodeTemplate(CodeTemplateContextType.OVERRIDECOMMENT_ID, "/* (non-Javadoc)\n * ${see_to_overridden}\n */", null);
StubUtility.setCodeTemplate(CodeTemplateContextType.METHODSTUB_ID, "//TODO\n${body_statement}", null);
StubUtility.setCodeTemplate(CodeTemplateContextType.CONSTRUCTORCOMMENT_ID, "/**\n * Constructor.\n */", null);
StubUtility.setCodeTemplate(CodeTemplateContextType.METHODCOMMENT_ID, "/**\n * Method.\n */", null);
StubUtility.setCodeTemplate(CodeTemplateContextType.CONSTRUCTORSTUB_ID, "//TODO\n${body_statement}", null);
fBeforeImports= "";
fAfterImports= "";
fMembers= "";
fLocals= "";
fTrigger= '\0';
fWaitBeforeCompleting= false;
}
protected void configureCoreOptions(Hashtable options) {
options.put(DefaultCodeFormatterConstants.FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE, "1");
options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE);
options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "4");
options.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH, JavaCore.DISABLED);
options.put(JavaCore.CODEASSIST_FIELD_PREFIXES, "f");
}
protected void setCoreOption(String key, String value) {
Hashtable options= JavaCore.getOptions();
options.put(key, value);
JavaCore.setOptions(options);
}
protected void waitBeforeCompleting(boolean wait) {
fWaitBeforeCompleting= wait;
}
protected IPreferenceStore getJDTUIPrefs() {
IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore();
return store;
}
private ICompilationUnit createCU(IPackageFragment pack1, String contents) throws JavaModelException {
ICompilationUnit cu= pack1.createCompilationUnit("Completion_" + getName() + ".java", contents, false, null);
return cu;
}
protected void tearDown() throws Exception {
IPreferenceStore store= getJDTUIPrefs();
store.setToDefault(PreferenceConstants.CODEGEN_ADD_COMMENTS);
store.setToDefault(PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS);
store.setToDefault(PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES);
store.setToDefault(PreferenceConstants.CODEASSIST_INSERT_COMPLETION);
store.setToDefault(PreferenceConstants.CODEASSIST_ADDIMPORT);
store.setToDefault(PreferenceConstants.EDITOR_CLOSE_BRACKETS);
store.setToDefault(PreferenceConstants.CODEASSIST_INSERT_COMPLETION);
store.setToDefault(PreferenceConstants.CODEASSIST_PREFIX_COMPLETION);
store.setToDefault(PreferenceConstants.CODEASSIST_AUTOINSERT);
fCU= null;
}
protected void addImport(String imp) {
imp= normalizeImport(imp);
if (fBeforeImports.length() == 0)
fBeforeImports= "\n" + imp + "\n";
else
fBeforeImports += imp + "\n";
}
protected void expectImport(String imp) {
imp= normalizeImport(imp);
if (fAfterImports.length() == 0)
fAfterImports= "\n" + imp + "\n";
else
fAfterImports += imp + "\n";
}
private String normalizeImport(String imp) {
if (!imp.startsWith("import "))
imp= "import " + imp;
if (!imp.endsWith(";"))
imp+= ";";
return imp;
}
protected void addMembers(String member) {
fMembers += "\n " + member + "\n";
}
protected void addLocalVariables(String variable) {
fLocals += "\n " + variable + "\n";
}
protected void setTrigger(char trigger) {
fTrigger= trigger;
}
/**
* Creates a CU with a method containing <code>before</code>, then runs
* code assist and applies the first proposal whose display name matches <code>selector</code>
* and asserts that the method's body now has the content of <code>expected</code>.
*
* @param expected the expected contents of the type javadoc line
* @param javadocLine the contents of the javadoc line before code completion is run
* @param selector the prefix to match a proposal with
* @throws CoreException
*/
protected void assertMethodBodyProposal(String before, String selector, String expected) throws CoreException {
StringBuffer contents= new StringBuffer();
IRegion preSelection= assembleMethodBodyTestCUExtractSelection(contents, before, fBeforeImports);
StringBuffer result= new StringBuffer();
IRegion expectedSelection= assembleMethodBodyTestCUExtractSelection(result, expected, fAfterImports);
assertProposal(selector, contents, preSelection, result, expectedSelection);
}
/**
* Creates a CU with a method containing <code>before</code>, then runs incremental code
* assist and asserts that the method's body now has the content of <code>expected</code>.
*
* @param expected the expected contents of the type javadoc line
* @param before the contents of the javadoc line before code completion is run
* @throws CoreException
*/
protected void assertMethodBodyIncrementalCompletion(String before, String expected) throws CoreException {
StringBuffer contents= new StringBuffer();
IRegion preSelection= assembleMethodBodyTestCUExtractSelection(contents, before, fBeforeImports);
StringBuffer result= new StringBuffer();
IRegion expectedSelection= assembleMethodBodyTestCUExtractSelection(result, expected, fAfterImports);
assertIncrementalCompletion(contents, preSelection, result, expectedSelection);
}
/**
* Creates a CU with a method containing <code>before</code>, then runs
* code assist and applies the first proposal whose display name matches <code>selector</code>
* and asserts that the method's body now has the content of <code>expected</code>.
*
* @param expected the expected contents of the type javadoc line
* @param javadocLine the contents of the javadoc line before code completion is run
* @param selector the prefix to match a proposal with
* @throws CoreException
*/
protected void assertMemberJavadocProposal(String before, String selector, String expected) throws CoreException {
StringBuffer contents= new StringBuffer();
IRegion preSelection= assembleMethodJavadocTestCUExtractSelection(contents, before, fBeforeImports);
StringBuffer result= new StringBuffer();
IRegion expectedSelection= assembleMethodJavadocTestCUExtractSelection(result, expected, fAfterImports);
assertProposal(selector, contents, preSelection, result, expectedSelection);
}
/**
* Creates a CU with a method containing <code>before</code>, then runs
* code assist and applies the first proposal whose display name matches <code>selector</code>
* and asserts that the method's body now has the content of <code>expected</code>.
*
* @param expected the expected contents of the type javadoc line
* @param javadocLine the contents of the javadoc line before code completion is run
* @param selector the prefix to match a proposal with
* @throws CoreException
*/
protected void assertTypeBodyProposal(String before, String selector, String expected) throws CoreException {
StringBuffer contents= new StringBuffer();
IRegion preSelection= assembleClassBodyTestCUExtractSelection(contents, before, fBeforeImports);
StringBuffer result= new StringBuffer();
IRegion expectedSelection= assembleClassBodyTestCUExtractSelection(result, expected, fAfterImports);
assertProposal(selector, contents, preSelection, result, expectedSelection);
}
/**
* Creates a CU with a method containing <code>before</code>, then runs
* code assist and applies the first proposal whose display name matches <code>selector</code>
* and asserts that the method's body now has the content of <code>expected</code>.
*
* @param expected the expected contents of the type javadoc line
* @param before the contents of the line where before code completion is run
* @param selector the prefix to match a proposal with
* @throws CoreException
*/
protected void assertTypeJavadocProposal(String before, String selector, String expected) throws CoreException {
StringBuffer contents= new StringBuffer();
IRegion preSelection= assembleClassJavadocTestCUExtractSelection(contents, before, fBeforeImports);
StringBuffer result= new StringBuffer();
IRegion expectedSelection= assembleClassJavadocTestCUExtractSelection(result, expected, fAfterImports);
assertProposal(selector, contents, preSelection, result, expectedSelection);
}
/**
* Creates a CU with a method containing <code>before</code>, then runs
* code assist and asserts that there is no proposal starting with selector.
*
* @param expected the expected contents of the type javadoc line
* @param javadocLine the contents of the javadoc line before code completion is run
* @param selector the prefix to match a proposal with
* @throws CoreException
*/
protected void assertNoMethodBodyProposals(String before, String selector) throws CoreException {
StringBuffer contents= new StringBuffer();
IRegion preSelection= assembleMethodBodyTestCUExtractSelection(contents, before, fBeforeImports);
assertNoProposal(selector, contents, preSelection);
}
private void assertProposal(String selector, StringBuffer contents, IRegion preSelection, StringBuffer result, IRegion expectedSelection) throws CoreException {
fCU= createCU(CompletionTestSetup.getAnonymousTestPackage(), contents.toString());
fEditor= (JavaEditor) EditorUtility.openInEditor(fCU);
IDocument doc;
ITextSelection postSelection;
try {
ICompletionProposal proposal= findNonNullProposal(selector, fCU, preSelection);
doc= fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput());
apply(fEditor, doc, proposal, preSelection);
postSelection= (ITextSelection) fEditor.getSelectionProvider().getSelection();
} finally {
EditorTestHelper.closeEditor(fEditor);
}
assertEquals(result.toString(), doc.get());
assertEquals(expectedSelection.getOffset(), postSelection.getOffset());
assertEquals(expectedSelection.getLength(), postSelection.getLength());
}
private void assertIncrementalCompletion(StringBuffer contents, IRegion preSelection, StringBuffer result, IRegion expectedSelection) throws CoreException {
fCU= createCU(CompletionTestSetup.getAnonymousTestPackage(), contents.toString());
fEditor= (JavaEditor) EditorUtility.openInEditor(fCU);
IDocument doc;
ITextSelection postSelection;
try {
incrementalAssist(fCU, preSelection);
doc= fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput());
postSelection= (ITextSelection) fEditor.getSelectionProvider().getSelection();
} finally {
EditorTestHelper.closeEditor(fEditor);
}
assertEquals(result.toString(), doc.get());
assertEquals(expectedSelection.getOffset(), postSelection.getOffset());
assertEquals(expectedSelection.getLength(), postSelection.getLength());
}
private void assertNoProposal(String selector, StringBuffer contents, IRegion preSelection) throws CoreException {
fCU= createCU(CompletionTestSetup.getAnonymousTestPackage(), contents.toString());
fEditor= (JavaEditor) EditorUtility.openInEditor(fCU);
try {
assertNull(findNamedProposal(selector, fCU, preSelection));
} finally {
EditorTestHelper.closeEditor(fEditor);
}
}
private IRegion assembleMethodBodyTestCUExtractSelection(StringBuffer buffer, String javadocLine, String imports) {
String prefix= "package test1;\n" +
imports +
"\n" +
"public class Completion_" + getName() + "<T> {\n" +
" public void testMethod(int param) {\n" +
fLocals +
" ";
String postfix= "\n" +
" }\n" +
fMembers +
"}\n";
StringBuffer lineBuffer= new StringBuffer(javadocLine);
int firstPipe= lineBuffer.indexOf(CARET);
int secondPipe;
if (firstPipe == -1) {
firstPipe= lineBuffer.length();
secondPipe= firstPipe;
} else {
lineBuffer.replace(firstPipe, firstPipe + CARET.length(), "");
secondPipe= lineBuffer.indexOf(CARET, firstPipe);
if (secondPipe ==-1)
secondPipe= firstPipe;
else
lineBuffer.replace(secondPipe, secondPipe + CARET.length(), "");
}
buffer.append(prefix + lineBuffer + postfix);
return new Region(firstPipe + prefix.length(), secondPipe - firstPipe);
}
private IRegion assembleClassBodyTestCUExtractSelection(StringBuffer buffer, String javadocLine, String imports) {
String prefix= "package test1;\n" +
imports +
"\n" +
"public class Completion_" + getName() + "<T> {\n" +
fLocals +
" ";
String postfix= "\n" +
"\n" +
fMembers +
"}\n";
StringBuffer lineBuffer= new StringBuffer(javadocLine);
int firstPipe= lineBuffer.indexOf(CARET);
int secondPipe;
if (firstPipe == -1) {
firstPipe= lineBuffer.length();
secondPipe= firstPipe;
} else {
lineBuffer.replace(firstPipe, firstPipe + CARET.length(), "");
secondPipe= lineBuffer.indexOf(CARET, firstPipe);
if (secondPipe ==-1)
secondPipe= firstPipe;
else
lineBuffer.replace(secondPipe, secondPipe + CARET.length(), "");
}
buffer.append(prefix + lineBuffer + postfix);
return new Region(firstPipe + prefix.length(), secondPipe - firstPipe);
}
private IRegion assembleClassJavadocTestCUExtractSelection(StringBuffer buffer, String javadocLine, String imports) {
String prefix= "package test1;\n" +
imports +
"\n" +
"/**\n";
String postfix= "\n" +
" */\n" +
"public class Completion_" + getName() + "<T> {\n" +
"\n" +
fMembers +
"}\n";
StringBuffer lineBuffer= new StringBuffer(javadocLine);
int firstPipe= lineBuffer.indexOf(CARET);
int secondPipe;
if (firstPipe == -1) {
firstPipe= lineBuffer.length();
secondPipe= firstPipe;
} else {
lineBuffer.replace(firstPipe, firstPipe + CARET.length(), "");
secondPipe= lineBuffer.indexOf(CARET, firstPipe);
if (secondPipe ==-1)
secondPipe= firstPipe;
else
lineBuffer.replace(secondPipe, secondPipe + CARET.length(), "");
}
buffer.append(prefix + lineBuffer + postfix);
return new Region(firstPipe + prefix.length(), secondPipe - firstPipe);
}
private IRegion assembleMethodJavadocTestCUExtractSelection(StringBuffer buffer, String javadocLine, String imports) {
String prefix= "package test1;\n" +
"\n" +
"public class Completion_" + getName() + "<T> {\n" +
" /**\n ";
String postfix= "\n" +
" */\n" +
fMembers +
"}\n";
StringBuffer lineBuffer= new StringBuffer(javadocLine);
int firstPipe= lineBuffer.indexOf(CARET);
int secondPipe;
if (firstPipe == -1) {
firstPipe= lineBuffer.length();
secondPipe= firstPipe;
} else {
lineBuffer.replace(firstPipe, firstPipe + CARET.length(), "");
secondPipe= lineBuffer.indexOf(CARET, firstPipe);
if (secondPipe ==-1)
secondPipe= firstPipe;
else
lineBuffer.replace(secondPipe, secondPipe + CARET.length(), "");
}
buffer.append(prefix + lineBuffer + postfix);
return new Region(firstPipe + prefix.length(), secondPipe - firstPipe);
}
private ICompletionProposal findNonNullProposal(String prefix, ICompilationUnit cu, IRegion selection) throws JavaModelException, PartInitException {
ICompletionProposal proposal= findNamedProposal(prefix, cu, selection);
assertNotNull("no proposal starting with \"" + prefix + "\"", proposal);
return proposal;
}
private ICompletionProposal findNamedProposal(String prefix, ICompilationUnit cu, IRegion selection) throws JavaModelException, PartInitException {
ICompletionProposal[] proposals= collectProposals(cu, selection);
ICompletionProposal found= null;
for (int i= 0; i < proposals.length; i++) {
String displayString= proposals[i].getDisplayString();
if (displayString.startsWith(prefix)) {
if (found == null || displayString.equals(prefix))
found= proposals[i];
}
}
return found;
}
private ICompletionProposal[] collectProposals(ICompilationUnit cu, IRegion selection) throws JavaModelException, PartInitException {
waitBeforeCoreCompletion();
ContentAssistant assistant= new ContentAssistant();
assistant.setDocumentPartitioning(IJavaPartitions.JAVA_PARTITIONING);
IContentAssistProcessor javaProcessor= new JavaCompletionProcessor(fEditor, assistant, getContentType());
ICompletionProposal[] proposals= javaProcessor.computeCompletionProposals(fEditor.getViewer(), selection.getOffset());
return proposals;
}
private void incrementalAssist(ICompilationUnit cu, IRegion selection) throws JavaModelException, PartInitException {
waitBeforeCoreCompletion();
ContentAssistant assistant= new ContentAssistant();
assistant.enableAutoInsert(true);
final ISourceViewer viewer= fEditor.getViewer();
viewer.setSelectedRange(selection.getOffset(), selection.getLength());
assistant.install(viewer);
assistant.setDocumentPartitioning(IJavaPartitions.JAVA_PARTITIONING);
IContentAssistProcessor javaProcessor= new JavaCompletionProcessor(fEditor, assistant, getContentType());
assistant.setContentAssistProcessor(javaProcessor, getContentType());
assistant.completePrefix();
assistant.uninstall();
}
/**
* Invokes {@link Thread#sleep(long)} if {@link #waitBeforeCompleting(boolean)} was set to
* <code>true</code> or camel case completions are enabled. For some reasons, inner types and
* camel case matches don't show up otherwise.
*
* @since 3.2
*/
private void waitBeforeCoreCompletion() {
if (fWaitBeforeCompleting || JavaCore.ENABLED.equals(JavaCore.getOption(JavaCore.CODEASSIST_CAMEL_CASE_MATCH))) {
try {
Thread.sleep(1000);
} catch (InterruptedException x) {
}
}
}
protected String getContentType() {
return IDocument.DEFAULT_CONTENT_TYPE;
}
private void apply(ITextEditor editor, IDocument doc, ICompletionProposal proposal, IRegion selection) {
if (proposal instanceof ICompletionProposalExtension2) {
ICompletionProposalExtension2 ext= (ICompletionProposalExtension2) proposal;
ITextViewer viewer= (ITextViewer) editor.getAdapter(ITextOperationTarget.class);
ext.selected(viewer, false);
viewer.setSelectedRange(selection.getOffset(), selection.getLength());
ext.apply(viewer, fTrigger, 0, selection.getOffset());
Point range= proposal.getSelection(doc);
if (range != null)
viewer.setSelectedRange(range.x, range.y);
} else if (proposal instanceof ICompletionProposalExtension) {
ICompletionProposalExtension ext= (ICompletionProposalExtension) proposal;
ext.apply(doc, fTrigger, selection.getOffset() + selection.getLength());
} else {
proposal.apply(doc);
}
}
}