Bug 141864 - Ant content assist suggest nested target
diff --git a/ant/org.eclipse.ant.tests.ui/Ant Editor Tests/org/eclipse/ant/tests/ui/editor/CodeCompletionTest.java b/ant/org.eclipse.ant.tests.ui/Ant Editor Tests/org/eclipse/ant/tests/ui/editor/CodeCompletionTest.java
index 23ceac8..9174c02 100644
--- a/ant/org.eclipse.ant.tests.ui/Ant Editor Tests/org/eclipse/ant/tests/ui/editor/CodeCompletionTest.java
+++ b/ant/org.eclipse.ant.tests.ui/Ant Editor Tests/org/eclipse/ant/tests/ui/editor/CodeCompletionTest.java
@@ -501,7 +501,6 @@
*/
public void testTaskProposals() {
TestTextCompletionProcessor processor = new TestTextCompletionProcessor(getAntModel("buildtest1.xml"));
-
ICompletionProposal[] proposals = processor.getTaskProposals(" <", "rename", "");
assertEquals(0, proposals.length);
@@ -524,6 +523,40 @@
processor.dispose();
}
+ public void testTargetTemplateProposals() throws BadLocationException, PartInitException {
+ try {
+ IFile file= getIFile("buildtest1.xml");
+ AntEditor editor= (AntEditor)EditorTestHelper.openInEditor(file, ANT_EDITOR_ID, true);
+ TestTextCompletionProcessor processor= new TestTextCompletionProcessor(editor);
+ int lineNumber= 7;
+ int columnNumber= 6;
+ int lineOffset= editor.getDocumentProvider().getDocument(editor.getEditorInput()).getLineOffset(lineNumber);
+ processor.setLineNumber(lineNumber);
+ processor.setColumnNumber(columnNumber);
+ processor.setCursorPosition(lineOffset + columnNumber);
+
+ //complete inside a target
+ ICompletionProposal[] proposals= processor.determineTemplateProposals();
+ assertDoesNotContain("target - public target", proposals);
+
+ //complete outside of a target
+ lineNumber= 8;
+ columnNumber= 13;
+ lineOffset= editor.getDocumentProvider().getDocument(editor.getEditorInput()).getLineOffset(lineNumber);
+ processor.setLineNumber(lineNumber);
+ processor.setColumnNumber(columnNumber);
+ processor.setCursorPosition(lineOffset + columnNumber);
+
+ proposals= processor.determineTemplateProposals();
+ assertContains("target - public target", proposals);
+ //ensure all the tasks are still there
+ proposals = processor.getProposalsFromDocument(editor.getDocumentProvider().getDocument(editor.getEditorInput()), "");
+ assertContains("ant", proposals);
+ } finally {
+ EditorTestHelper.closeAllEditors();
+ }
+
+ }
/**
* Tests the code completion for the fail task
* bug 73637
diff --git a/ant/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorCompletionProcessor.java b/ant/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorCompletionProcessor.java
index 67140d8..67fa44b 100644
--- a/ant/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorCompletionProcessor.java
+++ b/ant/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorCompletionProcessor.java
@@ -22,9 +22,9 @@
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
-import com.ibm.icu.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
@@ -56,6 +56,7 @@
import org.eclipse.ant.internal.ui.editor.templates.AntTemplateInformationControlCreator;
import org.eclipse.ant.internal.ui.editor.templates.AntTemplateProposal;
import org.eclipse.ant.internal.ui.editor.templates.BuildFileContextType;
+import org.eclipse.ant.internal.ui.editor.templates.TargetContextType;
import org.eclipse.ant.internal.ui.editor.templates.TaskContextType;
import org.eclipse.ant.internal.ui.model.AntDefiningTaskNode;
import org.eclipse.ant.internal.ui.model.AntElementNode;
@@ -74,6 +75,7 @@
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.contentassist.ContentAssistEvent;
import org.eclipse.jface.text.contentassist.ICompletionListener;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
@@ -86,6 +88,8 @@
import org.eclipse.jface.text.templates.TemplateCompletionProcessor;
import org.eclipse.jface.text.templates.TemplateContext;
import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.text.templates.TemplateProposal;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.IEditorPart;
@@ -100,11 +104,21 @@
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import com.ibm.icu.text.MessageFormat;
+
/**
* The completion processor for the Ant Editor.
*/
public class AntEditorCompletionProcessor extends TemplateCompletionProcessor implements IContentAssistProcessor, ICompletionListener {
+ private static final class ProposalComparator implements Comparator {
+ public int compare(Object o1, Object o2) {
+ return ((TemplateProposal) o2).getRelevance() - ((TemplateProposal) o1).getRelevance();
+ }
+ }
+
+ private static final Comparator fgProposalComparator= new ProposalComparator();
+
private Comparator proposalComparator= new Comparator() {
public int compare(Object o1, Object o2) {
@@ -265,9 +279,9 @@
String prefix = getCurrentPrefix();
ICompletionProposal[] matchingTemplateProposals;
if (prefix.length() == 0) {
- matchingTemplateProposals = super.computeCompletionProposals(refViewer, documentOffset);
+ matchingTemplateProposals = determineTemplateProposalsForContext(documentOffset);
} else {
- ICompletionProposal[] templateProposals = super.computeCompletionProposals(refViewer, documentOffset);
+ ICompletionProposal[] templateProposals = determineTemplateProposalsForContext(documentOffset);
List templateProposalList = new ArrayList(templateProposals.length);
for (int i = 0; i < templateProposals.length; i++) {
if (templateProposals[i].getDisplayString().toLowerCase().startsWith(prefix)) {
@@ -280,6 +294,56 @@
return matchingTemplateProposals;
}
+ //essentially a copy of super.computeCompletionProposals but we need to have both context types work
+ //for target (task and target) context type in a backwards compatible way
+ private ICompletionProposal[] determineTemplateProposalsForContext(int offset) {
+ ITextSelection selection= (ITextSelection) viewer.getSelectionProvider().getSelection();
+
+ // adjust offset to end of normalized selection
+ if (selection.getOffset() == offset) {
+ offset= selection.getOffset() + selection.getLength();
+ }
+
+ String prefix= extractPrefix(viewer, offset);
+ Region region= new Region(offset - prefix.length(), prefix.length());
+ TemplateContext context= createContext(viewer, region);
+ if (context == null) {
+ return new ICompletionProposal[0];
+ }
+
+ context.setVariable("selection", selection.getText()); // name of the selection variables {line, word}_selection //$NON-NLS-1$
+
+ Template[] templates;
+ String contextTypeId = context.getContextType().getId();
+ boolean isTargetContextType = contextTypeId.equals(TargetContextType.TARGET_CONTEXT_TYPE);
+ if (isTargetContextType) {
+ Template[] tasks = AntTemplateAccess.getDefault().getTemplateStore().getTemplates(TaskContextType.TASK_CONTEXT_TYPE);
+ Template[] targets = getTemplates(contextTypeId);
+ templates = new Template[tasks.length + targets.length];
+ System.arraycopy(tasks, 0, templates, 0, tasks.length);
+ System.arraycopy(targets, 0, templates, tasks.length, targets.length);
+ } else {
+ templates = getTemplates(contextTypeId);
+ }
+
+ List matches= new ArrayList();
+ for (int i= 0; i < templates.length; i++) {
+ Template template= templates[i];
+ try {
+ context.getContextType().validate(template.getPattern());
+ } catch (TemplateException e) {
+ continue;
+ }
+ if (template.matches(prefix, contextTypeId) || (isTargetContextType && template.matches(prefix, TaskContextType.TASK_CONTEXT_TYPE))) {
+ matches.add(createProposal(template, context, (IRegion) region, getRelevance(template, prefix)));
+ }
+ }
+
+ Collections.sort(matches, fgProposalComparator);
+
+ return (ICompletionProposal[]) matches.toArray(new ICompletionProposal[matches.size()]);
+ }
+
private ICompletionProposal[] mergeProposals(ICompletionProposal[] proposals1, ICompletionProposal[] proposals2) {
ICompletionProposal[] combinedProposals = new ICompletionProposal[proposals1.length + proposals2.length];
@@ -1641,6 +1705,9 @@
protected TemplateContextType getContextType(ITextViewer textViewer, IRegion region) {
switch (determineProposalMode(textViewer.getDocument(), cursorPosition, getCurrentPrefix())) {
case PROPOSAL_MODE_TASK_PROPOSAL:
+ if (getEnclosingTargetName(textViewer.getDocument(), lineNumber, columnNumber) == null) {
+ return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(TargetContextType.TARGET_CONTEXT_TYPE);
+ }
return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(TaskContextType.TASK_CONTEXT_TYPE);
case PROPOSAL_MODE_BUILDFILE:
return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(BuildFileContextType.BUILDFILE_CONTEXT_TYPE);
diff --git a/ant/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/templates/AntTemplateAccess.java b/ant/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/templates/AntTemplateAccess.java
index ffa9532..f9da791 100644
--- a/ant/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/templates/AntTemplateAccess.java
+++ b/ant/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/templates/AntTemplateAccess.java
@@ -74,6 +74,7 @@
// create and configure the contexts available in the template editor
fRegistry= new ContributionContextTypeRegistry();
fRegistry.addContextType(BuildFileContextType.BUILDFILE_CONTEXT_TYPE);
+ fRegistry.addContextType(TargetContextType.TARGET_CONTEXT_TYPE);
fRegistry.addContextType(TaskContextType.TASK_CONTEXT_TYPE);
}
return fRegistry;
diff --git a/ant/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/templates/TargetContextType.java b/ant/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/templates/TargetContextType.java
new file mode 100644
index 0000000..8dfa2b0
--- /dev/null
+++ b/ant/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/templates/TargetContextType.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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.ant.internal.ui.editor.templates;
+
+public class TargetContextType extends BuildFileContextType {
+ public static final String TARGET_CONTEXT_TYPE= "org.eclipse.ant.ui.templateContextType.target"; //$NON-NLS-1$
+}
diff --git a/ant/org.eclipse.ant.ui/plugin.properties b/ant/org.eclipse.ant.ui/plugin.properties
index 63752bf..d3d745f 100644
--- a/ant/org.eclipse.ant.ui/plugin.properties
+++ b/ant/org.eclipse.ant.ui/plugin.properties
@@ -24,7 +24,6 @@
AddTask.label=Add &Task...
AddTask.tooltip=Add Task...
-
CategoryView.antViews = Ant
View.antView = Ant
@@ -38,9 +37,9 @@
PreferencePage.antTemplatePreferences = Templates
PreferencePage.antCodeAssistPreferences = Content Assist
-
buildFile.contextType.name= Ant
task.contextType.name= Ant Task
+target.contextType.name= Ant Target
antDocumentSetupParticipant.name= Ant Document Setup Participant
diff --git a/ant/org.eclipse.ant.ui/plugin.xml b/ant/org.eclipse.ant.ui/plugin.xml
index ad871db..2ecbb22 100644
--- a/ant/org.eclipse.ant.ui/plugin.xml
+++ b/ant/org.eclipse.ant.ui/plugin.xml
@@ -529,6 +529,11 @@
id="org.eclipse.ant.ui.templateContextType.buildFile">
</contextType>
<contextType
+ name="%target.contextType.name"
+ class="org.eclipse.ant.internal.ui.editor.templates.TargetContextType"
+ id="org.eclipse.ant.ui.templateContextType.target">
+ </contextType>
+ <contextType
name="%task.contextType.name"
class="org.eclipse.ant.internal.ui.editor.templates.TaskContextType"
id="org.eclipse.ant.ui.templateContextType.task">
diff --git a/ant/org.eclipse.ant.ui/templates/ant.xml b/ant/org.eclipse.ant.ui/templates/ant.xml
index d824d43..6e9c90b 100644
--- a/ant/org.eclipse.ant.ui/templates/ant.xml
+++ b/ant/org.eclipse.ant.ui/templates/ant.xml
@@ -71,7 +71,7 @@
</template>
<template
- context="org.eclipse.ant.ui.templateContextType.task"
+ context="org.eclipse.ant.ui.templateContextType.target"
description="%targetTemplate1.description"
id="org.eclipse.ant.ui.templates.target1"
name="target"><![CDATA[<!-- =================================
@@ -83,7 +83,7 @@
]]></template>
<template
- context="org.eclipse.ant.ui.templateContextType.task"
+ context="org.eclipse.ant.ui.templateContextType.target"
description="%targetTemplate2.description"
id="org.eclipse.ant.ui.templates.target2"
name="target"><![CDATA[<!-- - - - - - - - - - - - - - - - - -