mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 17:56:01 +02:00
Fix for 180531: [editor] pasted text loses formatting
This commit is contained in:
parent
f69868567c
commit
39d2e909be
5 changed files with 70 additions and 31 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2006 Wind River Systems, Inc. and others.
|
* Copyright (c) 2006, 2007 Wind River Systems, Inc. and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -26,12 +26,13 @@ import org.eclipse.jface.text.IAutoEditStrategy;
|
||||||
import org.eclipse.jface.text.IDocument;
|
import org.eclipse.jface.text.IDocument;
|
||||||
import org.eclipse.jface.text.IRegion;
|
import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.jface.text.TextUtilities;
|
import org.eclipse.jface.text.TextUtilities;
|
||||||
import org.eclipse.swt.widgets.Shell;
|
|
||||||
import org.eclipse.ui.PlatformUI;
|
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.ui.CUIPlugin;
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
import org.eclipse.cdt.ui.text.ICPartitions;
|
import org.eclipse.cdt.ui.text.ICPartitions;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.formatter.DefaultCodeFormatterOptions;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.text.CAutoIndentStrategy;
|
import org.eclipse.cdt.internal.ui.text.CAutoIndentStrategy;
|
||||||
import org.eclipse.cdt.internal.ui.text.CCommentAutoIndentStrategy;
|
import org.eclipse.cdt.internal.ui.text.CCommentAutoIndentStrategy;
|
||||||
import org.eclipse.cdt.internal.ui.text.CTextTools;
|
import org.eclipse.cdt.internal.ui.text.CTextTools;
|
||||||
|
@ -228,6 +229,8 @@ public class CAutoIndentTest extends TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HashMap fOptions;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param name
|
* @param name
|
||||||
|
@ -242,21 +245,28 @@ public class CAutoIndentTest extends TestCase {
|
||||||
|
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
|
// Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
|
||||||
shell.forceActive();
|
// shell.forceActive();
|
||||||
shell.forceFocus();
|
// shell.forceFocus();
|
||||||
|
fOptions= CCorePlugin.getOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see junit.framework.TestCase#tearDown()
|
||||||
|
*/
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
CCorePlugin.setOptions(fOptions);
|
||||||
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private AutoEditTester createAutoEditTester() {
|
private AutoEditTester createAutoEditTester() {
|
||||||
CTextTools textTools = CUIPlugin.getDefault().getTextTools();
|
CTextTools textTools = CUIPlugin.getDefault().getTextTools();
|
||||||
IDocument doc = new Document();
|
IDocument doc = new Document();
|
||||||
textTools.setupCDocument(doc);
|
textTools.setupCDocument(doc);
|
||||||
AutoEditTester tester = new AutoEditTester(doc, textTools.getDocumentPartitioning());
|
AutoEditTester tester = new AutoEditTester(doc, ICPartitions.C_PARTITIONING);
|
||||||
tester.setAutoEditStrategy(IDocument.DEFAULT_CONTENT_TYPE,
|
tester.setAutoEditStrategy(IDocument.DEFAULT_CONTENT_TYPE, new CAutoIndentStrategy(ICPartitions.C_PARTITIONING, null));
|
||||||
new CAutoIndentStrategy(textTools.getDocumentPartitioning(), null));
|
|
||||||
tester.setAutoEditStrategy(ICPartitions.C_MULTI_LINE_COMMENT, new CCommentAutoIndentStrategy());
|
tester.setAutoEditStrategy(ICPartitions.C_MULTI_LINE_COMMENT, new CCommentAutoIndentStrategy());
|
||||||
tester.setAutoEditStrategy(ICPartitions.C_PREPROCESSOR,
|
tester.setAutoEditStrategy(ICPartitions.C_PREPROCESSOR, new CAutoIndentStrategy(ICPartitions.C_PARTITIONING, null));
|
||||||
new CAutoIndentStrategy(textTools.getDocumentPartitioning(), null));
|
|
||||||
return tester;
|
return tester;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,5 +497,22 @@ public class CAutoIndentTest extends TestCase {
|
||||||
tester.type("for (;;) /*class*/ {\n"); //$NON-NLS-1$
|
tester.type("for (;;) /*class*/ {\n"); //$NON-NLS-1$
|
||||||
assertEquals("for (;;) /*class*/ {\n\t\r\n}", tester.fDoc.get()); //$NON-NLS-1$
|
assertEquals("for (;;) /*class*/ {\n\t\r\n}", tester.fDoc.get()); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSmartPasteWhitesmiths_Bug180531() throws Exception {
|
||||||
|
DefaultCodeFormatterOptions whitesmiths= DefaultCodeFormatterOptions.getWhitesmithsSettings();
|
||||||
|
CCorePlugin.setOptions(new HashMap(whitesmiths.getMap()));
|
||||||
|
AutoEditTester tester = createAutoEditTester(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
tester.type("A::~A()\n{");
|
||||||
|
assertEquals("A::~A()\n {", tester.fDoc.get());
|
||||||
|
tester.type("\ndelete x;");
|
||||||
|
assertEquals("A::~A()\n {\n delete x;\n }", tester.fDoc.get());
|
||||||
|
|
||||||
|
tester.setCaretOffset(tester.fDoc.getLength());
|
||||||
|
tester.type('\n');
|
||||||
|
String copy= tester.fDoc.get();
|
||||||
|
tester.paste(copy);
|
||||||
|
assertEquals(copy+copy, tester.fDoc.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -213,11 +213,11 @@ public class CAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {
|
||||||
scanner = new CHeuristicScanner(d, fPartitioning, ICPartitions.C_PREPROCESSOR);
|
scanner = new CHeuristicScanner(d, fPartitioning, ICPartitions.C_PREPROCESSOR);
|
||||||
}
|
}
|
||||||
// current line
|
// current line
|
||||||
int line = d.getLineOfOffset(p);
|
int line = d.getLineOfOffset(c.offset);
|
||||||
int lineOffset = d.getLineOffset(line);
|
int lineOffset = d.getLineOffset(line);
|
||||||
|
|
||||||
// make sure we don't have any leading comments etc.
|
// make sure we don't have any leading comments etc.
|
||||||
if (d.get(lineOffset, p - lineOffset).trim().length() != 0)
|
if (d.get(lineOffset, c.offset - lineOffset).trim().length() != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Line of last C code
|
// Line of last C code
|
||||||
|
|
|
@ -60,6 +60,7 @@ public final class CHeuristicScanner implements Symbols {
|
||||||
private static final char RANGLE= '>';
|
private static final char RANGLE= '>';
|
||||||
private static final char DOT= '.';
|
private static final char DOT= '.';
|
||||||
private static final char MINUS= '-';
|
private static final char MINUS= '-';
|
||||||
|
private static final char TILDE= '~';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the stop condition, upon which the <code>scanXXX</code> methods will decide whether
|
* Specifies the stop condition, upon which the <code>scanXXX</code> methods will decide whether
|
||||||
|
@ -407,6 +408,8 @@ public final class CHeuristicScanner implements Symbols {
|
||||||
return TokenDOT;
|
return TokenDOT;
|
||||||
case MINUS:
|
case MINUS:
|
||||||
return TokenMINUS;
|
return TokenMINUS;
|
||||||
|
case TILDE:
|
||||||
|
return TokenTILDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// else
|
// else
|
||||||
|
@ -754,8 +757,8 @@ public final class CHeuristicScanner implements Symbols {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the highest position in <code>fDocument</code> such that the position is <= <code>position</code>
|
* Finds the highest position in <code>fDocument</code> such that the position is <= <code>position</code>
|
||||||
* and > <code>bound</code> and <code>fDocument.getChar(position) == ch</code> evaluates to <code>true</code> for at least one
|
* and > <code>bound</code> and <code>fDocument.getChar(position) == ch</code> evaluates to <code>true</code>
|
||||||
* ch in <code>chars</code> and the position is in the default partition.
|
* and the position is in the default partition.
|
||||||
*
|
*
|
||||||
* @param position the first character position in <code>fDocument</code> to be considered
|
* @param position the first character position in <code>fDocument</code> to be considered
|
||||||
* @param bound the first position in <code>fDocument</code> to not consider any more, with <code>bound</code> < <code>position</code>, or <code>UNBOUND</code>
|
* @param bound the first position in <code>fDocument</code> to not consider any more, with <code>bound</code> < <code>position</code>, or <code>UNBOUND</code>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2000, 2006 IBM Corporation and others.
|
* Copyright (c) 2000, 2007 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -220,7 +220,7 @@ public final class CIndenter {
|
||||||
// ignore and return default
|
// ignore and return default
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int prefMethodDeclIndent() {
|
private int prefMethodDeclIndent() {
|
||||||
|
@ -883,8 +883,8 @@ public final class CIndenter {
|
||||||
return matchCaseAlignment();
|
return matchCaseAlignment();
|
||||||
}
|
}
|
||||||
|
|
||||||
// the only reliable way to get case labels aligned (due to many different styles of using braces in a block)
|
// the only reliable way to get access specifiers aligned (due to many different styles of using braces in a block)
|
||||||
// is to go for another case statement, or the scope opening brace
|
// is to go for another access specifier, or the scope opening brace
|
||||||
if (matchAccessSpecifier) {
|
if (matchAccessSpecifier) {
|
||||||
return matchAccessSpecifierAlignment();
|
return matchAccessSpecifierAlignment();
|
||||||
}
|
}
|
||||||
|
@ -1194,8 +1194,9 @@ public final class CIndenter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns as a reference any previous <code>switch</code> labels (<code>case</code>
|
* Returns as a reference any previous access specifiers (<code>public</code>,
|
||||||
* or <code>default</code>) or the offset of the brace that scopes the class body.
|
* <code>protected</code> or <code>default</code>) or the offset of the brace that
|
||||||
|
* scopes the class body.
|
||||||
* Sets <code>fIndent</code> to <code>prefAccessSpecifierIndent</code> upon
|
* Sets <code>fIndent</code> to <code>prefAccessSpecifierIndent</code> upon
|
||||||
* a match.
|
* a match.
|
||||||
*
|
*
|
||||||
|
@ -1205,7 +1206,7 @@ public final class CIndenter {
|
||||||
while (true) {
|
while (true) {
|
||||||
nextToken();
|
nextToken();
|
||||||
switch (fToken) {
|
switch (fToken) {
|
||||||
// invalid cases: another case label or an LBRACE must come before a case
|
// invalid cases: another access specifier or an LBRACE must come before an access specifier
|
||||||
// -> bail out with the current position
|
// -> bail out with the current position
|
||||||
case Symbols.TokenLPAREN:
|
case Symbols.TokenLPAREN:
|
||||||
case Symbols.TokenLBRACKET:
|
case Symbols.TokenLBRACKET:
|
||||||
|
@ -1213,14 +1214,14 @@ public final class CIndenter {
|
||||||
return fPosition;
|
return fPosition;
|
||||||
|
|
||||||
case Symbols.TokenLBRACE:
|
case Symbols.TokenLBRACE:
|
||||||
// opening brace of switch statement
|
// opening brace of class body
|
||||||
fIndent= fPrefs.prefAccessSpecifierIndent;
|
fIndent= fPrefs.prefAccessSpecifierIndent;
|
||||||
return fPosition;
|
return fPosition;
|
||||||
|
|
||||||
case Symbols.TokenPUBLIC:
|
case Symbols.TokenPUBLIC:
|
||||||
case Symbols.TokenPROTECTED:
|
case Symbols.TokenPROTECTED:
|
||||||
case Symbols.TokenPRIVATE:
|
case Symbols.TokenPRIVATE:
|
||||||
// align with previous label
|
// align with previous access specifier
|
||||||
fIndent= 0;
|
fIndent= 0;
|
||||||
return fPosition;
|
return fPosition;
|
||||||
|
|
||||||
|
@ -1634,9 +1635,7 @@ public final class CIndenter {
|
||||||
* Returns <code>true</code> if the current tokens look like a method
|
* Returns <code>true</code> if the current tokens look like a method
|
||||||
* declaration header (i.e. only the return type and method name). The
|
* declaration header (i.e. only the return type and method name). The
|
||||||
* heuristic calls <code>nextToken</code> and expects an identifier
|
* heuristic calls <code>nextToken</code> and expects an identifier
|
||||||
* (method name) and a type declaration (an identifier with optional
|
* (method name) and an optional retrun type declaration.
|
||||||
* brackets) which also covers the visibility modifier of constructors; it
|
|
||||||
* does not recognize package visible constructors.
|
|
||||||
*
|
*
|
||||||
* @return <code>true</code> if the current position looks like a method
|
* @return <code>true</code> if the current position looks like a method
|
||||||
* declaration header.
|
* declaration header.
|
||||||
|
@ -1644,10 +1643,19 @@ public final class CIndenter {
|
||||||
private boolean looksLikeMethodDecl() {
|
private boolean looksLikeMethodDecl() {
|
||||||
nextToken();
|
nextToken();
|
||||||
if (fToken == Symbols.TokenIDENT) { // method name
|
if (fToken == Symbols.TokenIDENT) { // method name
|
||||||
do nextToken();
|
nextToken();
|
||||||
while (skipBrackets() || skipQualifiers()); // optional brackets for array valued return types
|
// check destructor tilde
|
||||||
|
if (fToken == Symbols.TokenTILDE) {
|
||||||
return fToken == Symbols.TokenIDENT; // return type name
|
return true;
|
||||||
|
}
|
||||||
|
if (skipQualifiers()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// optional brackets for array valued return types
|
||||||
|
while (skipBrackets()) {
|
||||||
|
nextToken();
|
||||||
|
}
|
||||||
|
return fToken == Symbols.TokenIDENT;
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -33,6 +33,7 @@ public interface Symbols {
|
||||||
int TokenGREATERTHAN= 14;
|
int TokenGREATERTHAN= 14;
|
||||||
int TokenDOT= 15;
|
int TokenDOT= 15;
|
||||||
int TokenMINUS= 16;
|
int TokenMINUS= 16;
|
||||||
|
int TokenTILDE= 17;
|
||||||
int TokenIF= 109;
|
int TokenIF= 109;
|
||||||
int TokenDO= 1010;
|
int TokenDO= 1010;
|
||||||
int TokenFOR= 1011;
|
int TokenFOR= 1011;
|
||||||
|
|
Loading…
Add table
Reference in a new issue