1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 06:32:10 +02:00

Fix for Bug 128361 - templates depending on line or word selection don't work

This commit is contained in:
Anton Leherbauer 2007-02-02 14:38:30 +00:00
parent 6a3d9e2e9e
commit c2146c6d14
9 changed files with 239 additions and 111 deletions

View file

@ -15,6 +15,7 @@ package org.eclipse.cdt.internal.corext.template.c;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateBuffer;
@ -47,81 +48,68 @@ public class CContext extends TranslationUnitContext {
super(type, document, completionOffset, completionLength, translationUnit);
}
/**
* Creates a C/C++ code template context.
*
* @param type the context type.
* @param document the document.
* @param completionPosition the completion position within the document
* @param translationUnit the translation unit (may be <code>null</code>).
*/
public CContext(TemplateContextType type, IDocument document,
Position completionPosition, ITranslationUnit translationUnit) {
super(type, document, completionPosition, translationUnit);
}
/*
* @see DocumentTemplateContext#getStart()
*/
public int getStart() {
if (fIsManaged && getCompletionLength() > 0)
return super.getStart();
try {
IDocument document= getDocument();
if (getCompletionLength() == 0) {
int start= getCompletionOffset();
while ((start != 0) && Character.isUnicodeIdentifierPart(document.getChar(start - 1)))
start--;
if ((start != 0) && Character.isUnicodeIdentifierStart(document.getChar(start - 1)))
start--;
return start;
}
int start= getCompletionOffset();
int end= getCompletionOffset() + getCompletionLength();
while (start != 0 && Character.isUnicodeIdentifierPart(document.getChar(start - 1))) {
while (start != 0 && !Character.isWhitespace(document.getChar(start - 1)))
start--;
}
while (start != end && Character.isWhitespace(document.getChar(start))) {
while (start != end && Character.isWhitespace(document.getChar(start)))
start++;
}
if (start == end) {
start= getCompletionOffset();
}
if (start == end)
start= getCompletionOffset();
return start;
return start;
} catch (BadLocationException e) {
return super.getStart();
}
}
public int getEnd() {
if (getCompletionLength() == 0)
if (fIsManaged || getCompletionLength() == 0)
return super.getEnd();
try {
try {
IDocument document= getDocument();
int start= getCompletionOffset();
int end= getCompletionOffset() + getCompletionLength();
while (start != end && Character.isWhitespace(document.getChar(end - 1))) {
while (start != end && Character.isWhitespace(document.getChar(end - 1)))
end--;
}
return end;
} catch (BadLocationException e) {
return super.getEnd();
}
}
/*
* @see TemplateContext#canEvaluate(Template templates)
*/
public boolean canEvaluate(Template template) {
if (fForceEvaluation)
return true;
String key= getKey();
return template.matches(key, getContextType().getId())
&& key.length() != 0 && template.getName().toLowerCase().startsWith(key.toLowerCase());
}
/*
* @see TemplateContext#evaluate(Template)
*/

View file

@ -13,6 +13,7 @@
package org.eclipse.cdt.internal.corext.template.c;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
import org.eclipse.cdt.core.model.ITranslationUnit;
@ -27,7 +28,7 @@ public class CContextType extends TranslationUnitContextType {
super();
}
/* (non-Javadoc)
/*
* @see org.eclipse.cdt.internal.corext.template.c.TranslationUnitContextType#createContext(org.eclipse.jface.text.IDocument, int, int, org.eclipse.cdt.core.model.ITranslationUnit)
*/
public TranslationUnitContext createContext(IDocument document, int offset,
@ -35,4 +36,12 @@ public class CContextType extends TranslationUnitContextType {
return new CContext(this, document, offset, length, translationUnit);
}
/*
* @see org.eclipse.cdt.internal.corext.template.c.TranslationUnitContextType#createContext(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.Position, org.eclipse.cdt.core.model.ITranslationUnit)
*/
public TranslationUnitContext createContext(IDocument document,
Position position, ITranslationUnit translationUnit) {
return new CContext(this, document, position, translationUnit);
}
}

View file

@ -19,15 +19,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.formatter.CodeFormatter;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.cdt.internal.ui.editor.IndentUtil;
import org.eclipse.cdt.internal.ui.text.FastCPartitionScanner;
import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
@ -48,6 +39,16 @@ import org.eclipse.text.edits.RangeMarker;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.formatter.CodeFormatter;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.cdt.internal.ui.editor.IndentUtil;
import org.eclipse.cdt.internal.ui.text.FastCPartitionScanner;
/**
* A template editor using the C/C++ formatter to format a template buffer.
@ -94,7 +95,7 @@ public class CFormatter {
internalFormat(document, context);
convertLineDelimiters(document);
if (!isReplacedAreaEmpty(context))
if (isReplacedAreaEmpty(context))
trimStart(document);
tracker.updateBuffer();
@ -142,19 +143,19 @@ public class CFormatter {
}
private boolean isReplacedAreaEmpty(TemplateContext context) {
// don't trim the buffer if the replacement area is empty
// case: surrounding empty lines with block
if (context instanceof DocumentTemplateContext) {
DocumentTemplateContext dtc= (DocumentTemplateContext) context;
if (dtc.getStart() == dtc.getCompletionOffset())
try {
if (dtc.getDocument().get(dtc.getStart(), dtc.getEnd() - dtc.getStart()).trim().length() == 0)
return true;
} catch (BadLocationException x) {
// ignore - this may happen when the document was modified after the initial invocation, and the
// context does not track the changes properly - don't trim in that case
if (dtc.getCompletionLength() == 0) {
return true;
}
try {
if (dtc.getDocument().get(dtc.getStart(), dtc.getEnd() - dtc.getStart()).trim().length() == 0)
return true;
}
} catch (BadLocationException x) {
// ignore - this may happen when the document was modified after the initial invocation, and the
// context does not track the changes properly - don't trim in that case
return false;
}
}
return false;
}
@ -319,7 +320,7 @@ public class CFormatter {
private boolean isWhitespaceVariable(String value) {
int length= value.length();
return length == 0 || Character.isWhitespace(value.charAt(0)) || Character.isWhitespace(value.charAt(length - 1));
return length == 0 || value.trim().length() == 0;
}
private void removeRangeMarkers(List positions, IDocument document, TemplateVariable[] variables) throws MalformedTreeException, BadLocationException, BadPositionCategoryException {

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.corext.template.c;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateBuffer;
@ -44,25 +45,24 @@ public class CommentContext extends TranslationUnitContext {
super(type, document, completionOffset, completionLength, translationUnit);
}
/*
* @see TemplateContext#canEvaluate(Template templates)
/**
* Creates a comment template context.
*
* @param type the context type.
* @param document the document.
* @param completionPosition the completion position within the document
* @param translationUnit the translation unit (may be <code>null</code>).
*/
public boolean canEvaluate(Template template) {
String key= getKey();
if (fForceEvaluation)
return true;
return
template.matches(key, getContextType().getId()) &&
(key.length() != 0) && template.getName().toLowerCase().startsWith(key.toLowerCase());
public CommentContext(TemplateContextType type, IDocument document,
Position completionPosition, ITranslationUnit translationUnit) {
super(type, document, completionPosition, translationUnit);
}
/*
* @see DocumentTemplateContext#getStart()
*/
public int getStart() {
if (/*fIsManaged &&*/ getCompletionLength() > 0)
if (fIsManaged && getCompletionLength() > 0)
return super.getStart();
try {
@ -105,8 +105,7 @@ public class CommentContext extends TranslationUnitContext {
* @see org.eclipse.jdt.internal.corext.template.DocumentTemplateContext#getEnd()
*/
public int getEnd() {
if (/*fIsManaged ||*/ getCompletionLength() == 0)
if (fIsManaged || getCompletionLength() == 0)
return super.getEnd();
try {
@ -125,28 +124,6 @@ public class CommentContext extends TranslationUnitContext {
}
}
/*
* @see org.eclipse.jdt.internal.corext.template.DocumentTemplateContext#getKey()
*/
public String getKey() {
if (getCompletionLength() == 0)
return super.getKey();
try {
IDocument document= getDocument();
int start= getStart();
int end= getCompletionOffset();
return start <= end
? document.get(start, end - start)
: ""; //$NON-NLS-1$
} catch (BadLocationException e) {
return super.getKey();
}
}
/*
* @see TemplateContext#evaluate(Template)
*/

View file

@ -12,6 +12,7 @@
package org.eclipse.cdt.internal.corext.template.c;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
import org.eclipse.cdt.core.model.ITranslationUnit;
@ -39,4 +40,12 @@ public class CommentContextType extends TranslationUnitContextType {
return new CommentContext(this, document, offset, length, translationUnit);
}
/*
* @see org.eclipse.cdt.internal.corext.template.c.TranslationUnitContextType#createContext(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.Position, org.eclipse.cdt.core.model.ITranslationUnit)
*/
public TranslationUnitContext createContext(IDocument document,
Position position, ITranslationUnit translationUnit) {
return new CommentContext(this, document, position, translationUnit);
}
}

View file

@ -16,7 +16,9 @@ package org.eclipse.cdt.internal.corext.template.c;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.templates.DocumentTemplateContext;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateContextType;
import org.eclipse.cdt.core.model.CModelException;
@ -37,6 +39,8 @@ public abstract class TranslationUnitContext extends DocumentTemplateContext {
private final ITranslationUnit fTranslationUnit;
/** A flag to force evaluation in head-less mode. */
protected boolean fForceEvaluation;
/** <code>true</code> if the context has a managed (i.e. added to the document) position, <code>false</code> otherwise. */
protected final boolean fIsManaged;
/**
* Creates a translation unit context.
@ -48,10 +52,60 @@ public abstract class TranslationUnitContext extends DocumentTemplateContext {
* @param translationUnit the translation unit represented by the document
*/
protected TranslationUnitContext(TemplateContextType type, IDocument document, int completionOffset,
int completionLength, ITranslationUnit translationUnit)
{
int completionLength, ITranslationUnit translationUnit) {
super(type, document, completionOffset, completionLength);
fTranslationUnit= translationUnit;
fIsManaged= false;
}
/**
* Creates a translation unit context.
*
* @param type the context type
* @param document the document
* @param completionPosition the completion position within the document
* @param translationUnit the translation unit represented by the document
*/
protected TranslationUnitContext(TemplateContextType type, IDocument document,
Position completionPosition, ITranslationUnit translationUnit) {
super(type, document, completionPosition);
fTranslationUnit= translationUnit;
fIsManaged= true;
}
/*
* @see org.eclipse.jface.text.templates.DocumentTemplateContext#canEvaluate(org.eclipse.jface.text.templates.Template)
*/
public boolean canEvaluate(Template template) {
if (fForceEvaluation)
return true;
String key= getKey();
return template.matches(key, getContextType().getId())
&& key.length() != 0 && template.getName().startsWith(key);
}
/*
* @see org.eclipse.jdt.internal.corext.template.DocumentTemplateContext#getKey()
*/
public String getKey() {
if (getCompletionLength() == 0)
return super.getKey();
try {
IDocument document= getDocument();
int start= getStart();
int end= getCompletionOffset();
return start <= end
? document.get(start, end - start)
: ""; //$NON-NLS-1$
} catch (BadLocationException e) {
return super.getKey();
}
}
/**

View file

@ -17,6 +17,7 @@ import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.IFunctionDeclaration;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.templates.GlobalTemplateVariables;
import org.eclipse.jface.text.templates.TemplateContext;
import org.eclipse.jface.text.templates.TemplateContextType;
@ -167,7 +168,7 @@ public abstract class TranslationUnitContextType extends TemplateContextType {
}
public abstract TranslationUnitContext createContext(IDocument document, int offset, int length, ITranslationUnit translationUnit);
public abstract TranslationUnitContext createContext(IDocument document, Position position, ITranslationUnit translationUnit);
}

View file

@ -13,15 +13,22 @@
package org.eclipse.cdt.internal.ui.text.template;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.templates.GlobalTemplateVariables;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateContext;
import org.eclipse.jface.text.templates.TemplateContextType;
@ -44,8 +51,15 @@ import org.eclipse.cdt.internal.ui.text.c.hover.SourceViewerInformationControl;
public class TemplateEngine {
private static final String $_LINE_SELECTION= "${" + GlobalTemplateVariables.LineSelection.NAME + "}"; //$NON-NLS-1$ //$NON-NLS-2$
private static final String $_WORD_SELECTION= "${" + GlobalTemplateVariables.WordSelection.NAME + "}"; //$NON-NLS-1$ //$NON-NLS-2$
/** The context type. */
private TemplateContextType fContextType;
/** The result proposals. */
private ArrayList fProposals= new ArrayList();
/** Positions created on the key documents to remove in reset. */
private final Map fPositions= new HashMap();
public class CTemplateProposal extends TemplateProposal implements ICCompletionProposal {
@ -101,6 +115,13 @@ public class TemplateEngine {
*/
public void reset() {
fProposals.clear();
for (Iterator it= fPositions.entrySet().iterator(); it.hasNext();) {
Entry entry= (Entry) it.next();
IDocument doc= (IDocument) entry.getKey();
Position position= (Position) entry.getValue();
doc.removePosition(position);
}
fPositions.clear();
}
/**
@ -120,23 +141,91 @@ public class TemplateEngine {
*/
public void complete(ITextViewer viewer, int completionPosition, ITranslationUnit translationUnit)
{
IDocument document= viewer.getDocument();
if (!(fContextType instanceof TranslationUnitContextType))
return;
IDocument document= viewer.getDocument();
Point selection= viewer.getSelectedRange();
boolean multipleLinesSelected= areMultipleLinesSelected(viewer);
if (multipleLinesSelected) {
// adjust line selection to start at column 1 and end at line delimiter
try {
IRegion startLine = document.getLineInformationOfOffset(selection.x);
IRegion endLine = document.getLineInformationOfOffset(selection.x + selection.y - 1);
completionPosition= selection.x= startLine.getOffset();
selection.y= endLine.getOffset() + endLine.getLength() - startLine.getOffset();
} catch (BadLocationException exc) {
}
}
Position position= new Position(completionPosition, selection.y);
TranslationUnitContext context= ((TranslationUnitContextType) fContextType).createContext(document, completionPosition, selection.y, translationUnit);
// remember selected text
String selectedText= null;
if (selection.y != 0) {
try {
selectedText= document.get(selection.x, selection.y);
document.addPosition(position);
fPositions.put(document, position);
} catch (BadLocationException e) {}
}
TranslationUnitContext context= ((TranslationUnitContextType) fContextType).createContext(document, position, translationUnit);
context.setVariable("selection", selectedText); //$NON-NLS-1$
int start= context.getStart();
int end= context.getEnd();
IRegion region= new Region(start, end - start);
Template[] templates= CUIPlugin.getDefault().getTemplateStore().getTemplates();
for (int i= 0; i != templates.length; i++)
if (context.canEvaluate(templates[i]))
fProposals.add(new CTemplateProposal(templates[i], context, region, CPluginImages.get(CPluginImages.IMG_OBJS_TEMPLATE)));
if (selection.y == 0) {
for (int i= 0; i != templates.length; i++)
if (context.canEvaluate(templates[i]))
fProposals.add(new CTemplateProposal(templates[i], context, region, CPluginImages.get(CPluginImages.IMG_OBJS_TEMPLATE)));
} else {
if (multipleLinesSelected || context.getKey().length() == 0)
context.setForceEvaluation(true);
for (int i= 0; i != templates.length; i++) {
Template template= templates[i];
if (context.canEvaluate(template) &&
template.getContextTypeId().equals(context.getContextType().getId()) &&
(!multipleLinesSelected && template.getPattern().indexOf($_WORD_SELECTION) != -1 || (multipleLinesSelected && template.getPattern().indexOf($_LINE_SELECTION) != -1)))
{
fProposals.add(new CTemplateProposal(templates[i], context, region, CPluginImages.get(CPluginImages.IMG_OBJS_TEMPLATE)));
}
}
}
}
/**
* Returns <code>true</code> if one line is completely selected or if multiple lines are selected.
* Being completely selected means that all characters except the new line characters are
* selected.
*
* @return <code>true</code> if one or multiple lines are selected
*/
private boolean areMultipleLinesSelected(ITextViewer viewer) {
if (viewer == null)
return false;
Point s= viewer.getSelectedRange();
if (s.y == 0)
return false;
try {
IDocument document= viewer.getDocument();
int startLine= document.getLineOfOffset(s.x);
int endLine= document.getLineOfOffset(s.x + s.y);
IRegion line= document.getLineInformation(startLine);
return startLine != endLine || (s.x == line.getOffset() && s.y == line.getLength());
} catch (BadLocationException x) {
return false;
}
}
}

View file

@ -21,14 +21,14 @@
<templates>
<template name="for" description="for loop" context="org.eclipse.cdt.ui.text.templates.c" id="org.eclipse.cdt.ui.text.templates.c.for" enabled="true">for (${var} = 0; ${var} &lt; ${max}; ++${var}) {
${cursor}
${line_selection}${cursor}
}</template>
<template name="for" description="for loop %withtempvar" context="org.eclipse.cdt.ui.text.templates.c" id="org.eclipse.cdt.ui.text.templates.cpp.for" enabled="true">for (int ${var} = 0; ${var} &lt; ${max}; ++${var}) {
${cursor}
${line_selection}${cursor}
}</template>
<template name="do" description="do while %statement" context="org.eclipse.cdt.ui.text.templates.c" id="org.eclipse.cdt.ui.text.templates.c.do" enabled="true">do {
${cursor}
${line_selection}${cursor}
} while (${condition});</template>
<template name="switch" description="switch case %statement" context="org.eclipse.cdt.ui.text.templates.c" id="org.eclipse.cdt.ui.text.templates.c.switch" enabled="true">switch (${key}) {
case ${value}:
@ -39,7 +39,7 @@
}</template>
<template name="if" description="if %statement" context="org.eclipse.cdt.ui.text.templates.c" id="org.eclipse.cdt.ui.text.templates.c.if" enabled="true">if (${condition}) {
${cursor}
${line_selection}${cursor}
}</template>
<template name="ifelse" description="if else %statement" context="org.eclipse.cdt.ui.text.templates.c" id="org.eclipse.cdt.ui.text.templates.c.ifelse" enabled="true">if (${condition}) {
${cursor}
@ -53,7 +53,7 @@
${cursor}
}</template>
<template name="try" description="try catch %block" context="org.eclipse.cdt.ui.text.templates.c" id="org.eclipse.cdt.ui.text.templates.cpp.try" enabled="true">try {
${cursor}
${line_selection}${cursor}
} catch (${Exception} e) {
}</template>
<template name="catch" description="catch %block" context="org.eclipse.cdt.ui.text.templates.c" id="org.eclipse.cdt.ui.text.templates.cpp.catch" enabled="true">catch (${Exception} e) {