1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 456099. Added change description.

This commit is contained in:
Sergey Prigogin 2014-12-30 17:12:33 -08:00
parent fb6cf9f410
commit 7eb2e1340a
5 changed files with 198 additions and 170 deletions

View file

@ -277,47 +277,47 @@ public class RenameMoveHeaderRefactoringTest extends RefactoringTestBase {
compareFiles(); compareFiles();
} }
// original-class.h // my-class.h
//#ifndef ORIGINAL_CLASS_H_ //#ifndef MY_CLASS_H_
//#define ORIGINAL_CLASS_H_ //#define MY_CLASS_H_
// //
//class OriginalClass {}; //class MyClass {};
// //
//#endif // ORIGINAL_CLASS_H_ //#endif // MY_CLASS_H_
//==================== //====================
// renamed-class.h // my-new-class.h
//#ifndef RENAMED_CLASS_H_ //#ifndef MY_NEW_CLASS_H_
//#define RENAMED_CLASS_H_ //#define MY_NEW_CLASS_H_
// //
//class RenamedClass {}; //class MyNewClass {};
// //
//#endif // RENAMED_CLASS_H_ //#endif // MY_NEW_CLASS_H_
// original-class.cpp // my-class.cpp
//#include "original-class.h" //#include "my-class.h"
// //
//#include <cstdio> //#include <cstdio>
//==================== //====================
// renamed-class.cpp // my-new-class.cpp
//#include "renamed-class.h" //#include "my-new-class.h"
// //
//#include <cstdio> //#include <cstdio>
// original-class_test.cpp // my-class_test.cpp
//#include "original-class.h" //#include "my-class.h"
//==================== //====================
// renamed-class_test.cpp // my-new-class_test.cpp
//#include "renamed-class.h" //#include "my-new-class.h"
// some-other-file.cpp // some-other-file.cpp
//#include "original-class.h" //#include "my-class.h"
///*$*/OriginalClass/*$$*/ a; ///*$*/MyClass/*$$*/ a;
//==================== //====================
// some-other-file.cpp // some-other-file.cpp
//#include "renamed-class.h" //#include "my-new-class.h"
//RenamedClass a; //MyNewClass a;
public void testClassRename() throws Exception { public void testClassRename() throws Exception {
executeRenameRefactoring("RenamedClass", true); executeRenameRefactoring("MyNewClass", true);
compareFiles(); compareFiles();
} }
} }

View file

@ -25,11 +25,11 @@ public class CRefactoringMatch {
public static final int IN_COMMENT = 4; public static final int IN_COMMENT = 4;
private static String[] LABELS= { private static String[] LABELS= {
RenameMessages.CRefactoringMatch_label_potentialOccurrence, RenameMessages.CRefactoringMatch_label_potentialOccurrences,
RenameMessages.CRefactoringMatch_label_occurrence, RenameMessages.CRefactoringMatch_label_occurrences,
"", //$NON-NLS-1$ "", //$NON-NLS-1$
RenameMessages.CRefactoringMatch_label_potentialOccurrence, RenameMessages.CRefactoringMatch_label_potentialOccurrences,
RenameMessages.CRefactoringMatch_label_comment }; RenameMessages.CRefactoringMatch_label_inComment };
private IFile fFile; private IFile fFile;
private int fOffset; private int fOffset;

View file

@ -46,6 +46,7 @@ import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit; import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit; import org.eclipse.text.edits.TextEdit;
import org.eclipse.text.edits.TextEditGroup;
import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTComment;
@ -183,16 +184,25 @@ public class HeaderFileReferenceAdjuster {
private void addFileChange(ITranslationUnit tu, List<Change> changes, ValidateEditChecker checker, private void addFileChange(ITranslationUnit tu, List<Change> changes, ValidateEditChecker checker,
IProgressMonitor pm) throws CoreException { IProgressMonitor pm) throws CoreException {
TextEdit edit = createEdit(tu, pm); TextEditGroup editGroup = createEdit(tu, pm);
if (edit != null) { if (editGroup != null) {
CTextFileChange fileChange = new CTextFileChange(tu.getElementName(), tu); CTextFileChange fileChange = new CTextFileChange(tu.getElementName(), tu);
fileChange.setEdit(edit); TextEdit[] edits = editGroup.getTextEdits();
if (edits.length == 1) {
fileChange.setEdit(edits[0]);
} else {
fileChange.setEdit(new MultiTextEdit());
for (TextEdit edit : edits) {
fileChange.addEdit(edit);
}
}
fileChange.addTextEditGroup(editGroup);
changes.add(fileChange); changes.add(fileChange);
checker.addFile(fileChange.getFile()); checker.addFile(fileChange.getFile());
} }
} }
private TextEdit createEdit(ITranslationUnit tu, IProgressMonitor pm) private TextEditGroup createEdit(ITranslationUnit tu, IProgressMonitor pm)
throws CoreException, OperationCanceledException { throws CoreException, OperationCanceledException {
checkCanceled(pm); checkCanceled(pm);
@ -205,7 +215,7 @@ public class HeaderFileReferenceAdjuster {
} }
} }
private TextEdit createEdit(IASTTranslationUnit ast, ITranslationUnit tu, IProgressMonitor pm) private TextEditGroup createEdit(IASTTranslationUnit ast, ITranslationUnit tu, IProgressMonitor pm)
throws CoreException, OperationCanceledException { throws CoreException, OperationCanceledException {
IncludeCreationContext context = new IncludeCreationContext(tu, index); IncludeCreationContext context = new IncludeCreationContext(tu, index);
// Adjust the translation unit location in the inclusion context. // Adjust the translation unit location in the inclusion context.
@ -216,6 +226,7 @@ public class HeaderFileReferenceAdjuster {
String contents = context.getSourceContents(); String contents = context.getSourceContents();
MultiTextEdit rootEdit = createIncludeGuardEdit(ast, tu, contents); MultiTextEdit rootEdit = createIncludeGuardEdit(ast, tu, contents);
int numIncludeGuardEdits = rootEdit == null ? 0 : rootEdit.getChildrenSize();
Map<IASTPreprocessorIncludeStatement, IPath> affectedIncludes = new IdentityHashMap<>(); Map<IASTPreprocessorIncludeStatement, IPath> affectedIncludes = new IdentityHashMap<>();
IASTPreprocessorIncludeStatement[] existingIncludes = ast.getIncludeDirectives(); IASTPreprocessorIncludeStatement[] existingIncludes = ast.getIncludeDirectives();
@ -240,152 +251,163 @@ public class HeaderFileReferenceAdjuster {
} }
} }
} }
if (affectedIncludes.isEmpty()) if (!affectedIncludes.isEmpty()) {
return rootEdit; NodeCommentMap commentedNodeMap = ASTCommenter.getCommentedNodeMap(ast);
IRegion includeRegion =
IncludeUtil.getSafeIncludeReplacementRegion(contents, ast, commentedNodeMap);
NodeCommentMap commentedNodeMap = ASTCommenter.getCommentedNodeMap(ast); IncludePreferences preferences = context.getPreferences();
IRegion includeRegion =
IncludeUtil.getSafeIncludeReplacementRegion(contents, ast, commentedNodeMap);
IncludePreferences preferences = context.getPreferences(); if (rootEdit == null)
rootEdit = new MultiTextEdit();
if (rootEdit == null) context.addHeadersIncludedPreviously(existingIncludes);
rootEdit = new MultiTextEdit();
context.addHeadersIncludedPreviously(existingIncludes); if (preferences.allowReordering) {
List<StyledInclude> modifiedIncludes = new ArrayList<>();
if (preferences.allowReordering) { // Put the changed includes into modifiedIncludes.
List<StyledInclude> modifiedIncludes = new ArrayList<>(); for (Entry<IASTPreprocessorIncludeStatement, IPath> entry : affectedIncludes.entrySet()) {
// Put the changed includes into modifiedIncludes. IASTPreprocessorIncludeStatement existingInclude = entry.getKey();
for (Entry<IASTPreprocessorIncludeStatement, IPath> entry : affectedIncludes.entrySet()) { if (IncludeUtil.isContainedInRegion(existingInclude, includeRegion)) {
IASTPreprocessorIncludeStatement existingInclude = entry.getKey(); IPath header = entry.getValue();
if (IncludeUtil.isContainedInRegion(existingInclude, includeRegion)) { IncludeGroupStyle style = context.getIncludeStyle(header);
IPath header = entry.getValue(); IncludeInfo includeInfo = context.createIncludeInfo(header, style);
IncludeGroupStyle style = context.getIncludeStyle(header); StyledInclude include = new StyledInclude(header, includeInfo, style, existingInclude);
IncludeInfo includeInfo = context.createIncludeInfo(header, style); modifiedIncludes.add(include);
StyledInclude include = new StyledInclude(header, includeInfo, style, existingInclude);
modifiedIncludes.add(include);
}
}
Collections.sort(modifiedIncludes, preferences);
// Populate a list of the existing unchanged includes in the include insertion region.
List<StyledInclude> mergedIncludes =
IncludeUtil.getIncludesInRegion(existingIncludes, includeRegion, context);
Deque<DeleteEdit> deletes = new ArrayDeque<>();
// Create text deletes for old locations of the includes that will be changed.
int deleteOffset = -1;
boolean emptyLineEncountered = false;
int j = 0;
for (int i = 0; i < mergedIncludes.size(); i++) {
StyledInclude include = mergedIncludes.get(i);
IASTPreprocessorIncludeStatement existingInclude = include.getExistingInclude();
int offset = ASTNodes.offset(existingInclude);
boolean previousLineBlank = TextUtil.isPreviousLineBlank(contents, offset);
if (affectedIncludes.containsKey(existingInclude)) {
if (deleteOffset < 0) {
deleteOffset = offset;
} else if (!emptyLineEncountered && previousLineBlank) {
// Preserve the first encountered blank line.
deletes.add(new DeleteEdit(deleteOffset, offset - deleteOffset));
deleteOffset = -1;
} }
emptyLineEncountered |= previousLineBlank; }
} else {
if (deleteOffset >= 0) { Collections.sort(modifiedIncludes, preferences);
if (!emptyLineEncountered && previousLineBlank) {
offset = TextUtil.getPreviousLineStart(contents, offset); // Populate a list of the existing unchanged includes in the include insertion region.
List<StyledInclude> mergedIncludes =
IncludeUtil.getIncludesInRegion(existingIncludes, includeRegion, context);
Deque<DeleteEdit> deletes = new ArrayDeque<>();
// Create text deletes for old locations of the includes that will be changed.
int deleteOffset = -1;
boolean emptyLineEncountered = false;
int j = 0;
for (int i = 0; i < mergedIncludes.size(); i++) {
StyledInclude include = mergedIncludes.get(i);
IASTPreprocessorIncludeStatement existingInclude = include.getExistingInclude();
int offset = ASTNodes.offset(existingInclude);
boolean previousLineBlank = TextUtil.isPreviousLineBlank(contents, offset);
if (affectedIncludes.containsKey(existingInclude)) {
if (deleteOffset < 0) {
deleteOffset = offset;
} else if (!emptyLineEncountered && previousLineBlank) {
// Preserve the first encountered blank line.
deletes.add(new DeleteEdit(deleteOffset, offset - deleteOffset));
deleteOffset = -1;
} }
deletes.add(new DeleteEdit(deleteOffset, offset - deleteOffset)); emptyLineEncountered |= previousLineBlank;
deleteOffset = -1; } else {
if (deleteOffset >= 0) {
if (!emptyLineEncountered && previousLineBlank) {
offset = TextUtil.getPreviousLineStart(contents, offset);
}
deletes.add(new DeleteEdit(deleteOffset, offset - deleteOffset));
deleteOffset = -1;
}
emptyLineEncountered = false;
if (j < i)
mergedIncludes.set(j, include);
j++;
} }
emptyLineEncountered = false;
if (j < i)
mergedIncludes.set(j, include);
j++;
} }
} while (j < mergedIncludes.size()) {
while (j < mergedIncludes.size()) { mergedIncludes.remove(mergedIncludes.size() - 1);
mergedIncludes.remove(mergedIncludes.size() - 1);
}
if (deleteOffset >= 0)
deletes.add(new DeleteEdit(deleteOffset, includeRegion.getOffset() + includeRegion.getLength() - deleteOffset));
// Since the order of existing include statements may not match the include order
// preferences, we find positions for the new include statements by pushing them up
// from the bottom of the include insertion region.
for (StyledInclude include : modifiedIncludes) {
if (IncludeUtil.isContainedInRegion(include.getExistingInclude(), includeRegion)) {
int i = mergedIncludes.size();
while (--i >= 0 && preferences.compare(include, mergedIncludes.get(i)) < 0) {}
mergedIncludes.add(i + 1, include);
} }
} if (deleteOffset >= 0)
deletes.add(new DeleteEdit(deleteOffset, includeRegion.getOffset() + includeRegion.getLength() - deleteOffset));
int offset = includeRegion.getOffset(); // Since the order of existing include statements may not match the include order
StringBuilder text = new StringBuilder(); // preferences, we find positions for the new include statements by pushing them up
StyledInclude previousInclude = null; // from the bottom of the include insertion region.
for (StyledInclude include : mergedIncludes) { for (StyledInclude include : modifiedIncludes) {
IASTPreprocessorIncludeStatement existingInclude = include.getExistingInclude(); if (IncludeUtil.isContainedInRegion(include.getExistingInclude(), includeRegion)) {
if (affectedIncludes.containsKey(existingInclude)) { int i = mergedIncludes.size();
if (previousInclude != null) { while (--i >= 0 && preferences.compare(include, mergedIncludes.get(i)) < 0) {}
IASTNode previousNode = previousInclude.getExistingInclude(); mergedIncludes.add(i + 1, include);
if (!affectedIncludes.containsKey(previousNode)) { }
offset = ASTNodes.skipToNextLineAfterNode(contents, previousNode); }
flushEditBuffer(offset, text, deletes, rootEdit);
if (contents.charAt(offset - 1) != '\n') int offset = includeRegion.getOffset();
text.append(context.getLineDelimiter()); StringBuilder text = new StringBuilder();
} StyledInclude previousInclude = null;
if (isBlankLineNeededBetween(previousInclude, include, preferences)) { for (StyledInclude include : mergedIncludes) {
if (TextUtil.isLineBlank(contents, offset)) { IASTPreprocessorIncludeStatement existingInclude = include.getExistingInclude();
int oldOffset = offset; if (affectedIncludes.containsKey(existingInclude)) {
offset = TextUtil.skipToNextLine(contents, offset); if (previousInclude != null) {
if (offset == oldOffset || contents.charAt(offset - 1) != '\n') IASTNode previousNode = previousInclude.getExistingInclude();
if (!affectedIncludes.containsKey(previousNode)) {
offset = ASTNodes.skipToNextLineAfterNode(contents, previousNode);
flushEditBuffer(offset, text, deletes, rootEdit);
if (contents.charAt(offset - 1) != '\n')
text.append(context.getLineDelimiter()); text.append(context.getLineDelimiter());
} else { }
text.append(context.getLineDelimiter()); if (isBlankLineNeededBetween(previousInclude, include, preferences)) {
if (TextUtil.isLineBlank(contents, offset)) {
int oldOffset = offset;
offset = TextUtil.skipToNextLine(contents, offset);
if (offset == oldOffset || contents.charAt(offset - 1) != '\n')
text.append(context.getLineDelimiter());
} else {
text.append(context.getLineDelimiter());
}
} }
} }
} text.append(include.getIncludeInfo().composeIncludeStatement());
text.append(include.getIncludeInfo().composeIncludeStatement()); List<IASTComment> comments = commentedNodeMap.getTrailingCommentsForNode(existingInclude);
List<IASTComment> comments = commentedNodeMap.getTrailingCommentsForNode(existingInclude); for (IASTComment comment : comments) {
for (IASTComment comment : comments) { text.append(ASTNodes.getPrecedingWhitespaceInLine(contents, comment));
text.append(ASTNodes.getPrecedingWhitespaceInLine(contents, comment)); text.append(comment.getRawSignature());
text.append(comment.getRawSignature()); }
}
text.append(context.getLineDelimiter());
} else {
if (previousInclude != null && affectedIncludes.containsKey(previousInclude.getExistingInclude()) &&
isBlankLineNeededBetween(previousInclude, include, preferences) &&
TextUtil.findBlankLine(contents, skipDeletedRegion(offset, deletes), ASTNodes.offset(existingInclude)) < 0) {
text.append(context.getLineDelimiter()); text.append(context.getLineDelimiter());
} else {
if (previousInclude != null && affectedIncludes.containsKey(previousInclude.getExistingInclude()) &&
isBlankLineNeededBetween(previousInclude, include, preferences) &&
TextUtil.findBlankLine(contents, skipDeletedRegion(offset, deletes), ASTNodes.offset(existingInclude)) < 0) {
text.append(context.getLineDelimiter());
}
flushEditBuffer(offset, text, deletes, rootEdit);
} }
flushEditBuffer(offset, text, deletes, rootEdit); previousInclude = include;
} }
previousInclude = include; if (includeRegion.getLength() == 0 && !TextUtil.isLineBlank(contents, includeRegion.getOffset())) {
text.append(context.getLineDelimiter());
}
offset = includeRegion.getOffset() + includeRegion.getLength();
flushEditBuffer(offset, text, deletes, rootEdit);
} }
if (includeRegion.getLength() == 0 && !TextUtil.isLineBlank(contents, includeRegion.getOffset())) {
text.append(context.getLineDelimiter());
}
offset = includeRegion.getOffset() + includeRegion.getLength();
flushEditBuffer(offset, text, deletes, rootEdit);
}
for (IASTPreprocessorIncludeStatement existingInclude : existingIncludes) { for (IASTPreprocessorIncludeStatement existingInclude : existingIncludes) {
IPath header = affectedIncludes.get(existingInclude); IPath header = affectedIncludes.get(existingInclude);
if (header != null && if (header != null &&
(!preferences.allowReordering || !IncludeUtil.isContainedInRegion(existingInclude, includeRegion))) { (!preferences.allowReordering || !IncludeUtil.isContainedInRegion(existingInclude, includeRegion))) {
IncludeGroupStyle style = context.getIncludeStyle(header); IncludeGroupStyle style = context.getIncludeStyle(header);
IncludeInfo includeInfo = context.createIncludeInfo(header, style); IncludeInfo includeInfo = context.createIncludeInfo(header, style);
IASTName name = existingInclude.getName(); IASTName name = existingInclude.getName();
int offset = ASTNodes.offset(name) - 1; int offset = ASTNodes.offset(name) - 1;
int length = ASTNodes.endOffset(name) + 1 - offset; int length = ASTNodes.endOffset(name) + 1 - offset;
rootEdit.addChild(new ReplaceEdit(offset, length, includeInfo.toString())); rootEdit.addChild(new ReplaceEdit(offset, length, includeInfo.toString()));
}
} }
} }
return rootEdit; if (rootEdit == null)
return null;
int numEdits = rootEdit.getChildrenSize();
String message =
numEdits == numIncludeGuardEdits ?
RenameMessages.HeaderReferenceAdjuster_update_include_guards :
numIncludeGuardEdits == 0 ?
RenameMessages.HeaderReferenceAdjuster_update_includes :
RenameMessages.HeaderReferenceAdjuster_update_include_guards_and_includes;
TextEditGroup editGroup= new TextEditGroup(message, rootEdit);
return editGroup;
} }
private static boolean isBlankLineNeededBetween(StyledInclude include1, StyledInclude include2, private static boolean isBlankLineNeededBetween(StyledInclude include1, StyledInclude include2,

View file

@ -22,9 +22,9 @@ class RenameMessages extends NLS {
public static String ASTManager_warning_parsingError_withFile; public static String ASTManager_warning_parsingError_withFile;
public static String ASTManager_warning_parsingError_withFileAndLine; public static String ASTManager_warning_parsingError_withFileAndLine;
public static String ASTManager_warning_parsingError; public static String ASTManager_warning_parsingError;
public static String CRefactoringMatch_label_comment; public static String CRefactoringMatch_label_inComment;
public static String CRefactoringMatch_label_occurrence; public static String CRefactoringMatch_label_occurrences;
public static String CRefactoringMatch_label_potentialOccurrence; public static String CRefactoringMatch_label_potentialOccurrences;
public static String CRefactory_title_rename; public static String CRefactory_title_rename;
public static String CRenameIncludeProcessor_includeDirective; public static String CRenameIncludeProcessor_includeDirective;
public static String CRenameLocalProcessor_constructor; public static String CRenameLocalProcessor_constructor;
@ -99,6 +99,9 @@ class RenameMessages extends NLS {
public static String CRenameTopProcessor_wizard_title; public static String CRenameTopProcessor_wizard_title;
public static String HeaderFileMoveParticipant_name; public static String HeaderFileMoveParticipant_name;
public static String HeaderFileRenameParticipant_name; public static String HeaderFileRenameParticipant_name;
public static String HeaderReferenceAdjuster_update_include_guards;
public static String HeaderReferenceAdjuster_update_includes;
public static String HeaderReferenceAdjuster_update_include_guards_and_includes;
public static String RenameCSourceFolderChange_ErrorMsg; public static String RenameCSourceFolderChange_ErrorMsg;
public static String RenameCSourceFolderChange_Name0; public static String RenameCSourceFolderChange_Name0;
public static String SourceFolderRenameParticipant_name; public static String SourceFolderRenameParticipant_name;
@ -124,7 +127,7 @@ class RenameMessages extends NLS {
NLS.initializeMessages(RenameMessages.class.getName(), RenameMessages.class); NLS.initializeMessages(RenameMessages.class.getName(), RenameMessages.class);
} }
// Do not instantiate // Do not instantiate.
private RenameMessages() { private RenameMessages() {
} }
} }

View file

@ -18,9 +18,9 @@ ASTManager_warning_parsingError_detailed=Parsing error - {0} -
ASTManager_warning_parsingError_withFile={0} in file ''{1}'' ASTManager_warning_parsingError_withFile={0} in file ''{1}''
ASTManager_warning_parsingError_withFileAndLine={0} in file ''{1}'' at line ''{2}'' ASTManager_warning_parsingError_withFileAndLine={0} in file ''{1}'' at line ''{2}''
ASTManager_warning_parsingError=Parsing error ASTManager_warning_parsingError=Parsing error
CRefactoringMatch_label_comment=Rename in comment CRefactoringMatch_label_inComment=Rename in comment
CRefactoringMatch_label_occurrence=Rename occurrence CRefactoringMatch_label_occurrences=Rename occurrences
CRefactoringMatch_label_potentialOccurrence=Rename potential occurrence CRefactoringMatch_label_potentialOccurrences=Rename potential occurrences
CRefactory_title_rename=Rename CRefactory_title_rename=Rename
CRenameIncludeProcessor_includeDirective=include directive CRenameIncludeProcessor_includeDirective=include directive
CRenameLocalProcessor_constructor=Constructor CRenameLocalProcessor_constructor=Constructor
@ -95,6 +95,9 @@ CRenameTopProcessor_wizard_backup_title=Rename
CRenameTopProcessor_wizard_title=Rename ''{0}'' CRenameTopProcessor_wizard_title=Rename ''{0}''
HeaderFileMoveParticipant_name=Header File Move HeaderFileMoveParticipant_name=Header File Move
HeaderFileRenameParticipant_name=Header File Rename HeaderFileRenameParticipant_name=Header File Rename
HeaderReferenceAdjuster_update_include_guards=Update include guards
HeaderReferenceAdjuster_update_includes=Update includes
HeaderReferenceAdjuster_update_include_guards_and_includes=Update include guards and includes
RenameCSourceFolderChange_ErrorMsg=Folder {0} does not exist RenameCSourceFolderChange_ErrorMsg=Folder {0} does not exist
RenameCSourceFolderChange_Name0=Rename source folder {0} to {1} RenameCSourceFolderChange_Name0=Rename source folder {0} to {1}
SourceFolderRenameParticipant_name=Rename C/C++ Source Folder SourceFolderRenameParticipant_name=Rename C/C++ Source Folder