1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 17:05:26 +02:00

Bug 45203. Major milestone - Organize Includes command is ready for

alpha testing.
This commit is contained in:
Sergey Prigogin 2013-03-14 17:20:22 -07:00
parent 8691f9784c
commit 7ac4d43010
38 changed files with 2665 additions and 1232 deletions

View file

@ -59,7 +59,7 @@ Export-Package: org.eclipse.cdt.core,
org.eclipse.cdt.internal.core.dom.rewrite;x-friends:="org.eclipse.cdt.core.tests,org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.dom.rewrite.astwriter;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.dom.rewrite.changegenerator;x-internal:=true,
org.eclipse.cdt.internal.core.dom.rewrite.commenthandler;x-internal:=true,
org.eclipse.cdt.internal.core.dom.rewrite.commenthandler;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.dom.rewrite.util;x-internal:=true,
org.eclipse.cdt.internal.core.envvar;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.managedbuilder.core",
org.eclipse.cdt.internal.core.index;x-friends:="org.eclipse.cdt.ui",

View file

@ -74,6 +74,21 @@ public class CharArrayUtils {
return true;
}
/**
* Returns {@code true} if the contents of a section of a character array are the same as
* contents of a string.
* @since 5.5
*/
public static final boolean equals(char[] str1, int start1, int length1, String str2) {
if (length1 != str2.length() || str1.length < length1 + start1)
return false;
for (int i = 0; i < length1; ++i) {
if (str1[start1++] != str2.charAt(i))
return false;
}
return true;
}
/**
* Returns {@code true} if a prefix of the character array is the same as contents
* of a string.
@ -117,6 +132,10 @@ public class CharArrayUtils {
return str1.length - str2.length;
}
/**
* Returns {@code true} if the contents of a section of a character array are the same as
* contents of another character array.
*/
public static final boolean equals(char[] str1, int start1, int length1, char[] str2) {
if (length1 != str2.length || str1.length < length1 + start1)
return false;

View file

@ -485,4 +485,52 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
}
return fSizeofCalculator;
}
/**
* Returns the offset of the given node, or -1 if the node is not part of the translation
* unit file or doesn't have a file-location.
* @see IASTNode#getFileLocation()
*/
public static int getNodeOffset(IASTNode node) {
if (!node.isPartOfTranslationUnitFile())
return -1;
IASTFileLocation nodeLocation = node.getFileLocation();
return nodeLocation != null ? nodeLocation.getNodeOffset() : -1;
}
/**
* Returns the end offset of the given node, or -1 if the node is not part of the translation
* unit file or doesn't have a file-location.
* @see IASTNode#getFileLocation()
*/
public static int getNodeEndOffset(IASTNode node) {
if (!node.isPartOfTranslationUnitFile())
return -1;
IASTFileLocation nodeLocation = node.getFileLocation();
return nodeLocation != null ? nodeLocation.getNodeOffset() + nodeLocation.getNodeLength() : -1;
}
/**
* Returns the 1-based starting line number of the given node, or 0 if the node is not part of
* the translation unit file or doesn't have a file-location.
* @see IASTNode#getFileLocation()
*/
public static int getStartingLineNumber(IASTNode node) {
if (!node.isPartOfTranslationUnitFile())
return 0;
IASTFileLocation nodeLocation = node.getFileLocation();
return nodeLocation != null ? nodeLocation.getStartingLineNumber() : 0;
}
/**
* Returns the 1-based ending line number of the given node, or 0 if the node is not part of
* the translation unit file or doesn't have a file-location.
* @see IASTNode#getFileLocation()
*/
public static int getEndingLineNumber(IASTNode node) {
if (!node.isPartOfTranslationUnitFile())
return 0;
IASTFileLocation nodeLocation = node.getFileLocation();
return nodeLocation != null ? nodeLocation.getEndingLineNumber() : 0;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* Copyright (c) 2012, 2013 Google, Inc 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
@ -22,7 +22,6 @@ import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.TextSelection;
@ -56,8 +55,6 @@ import org.eclipse.cdt.internal.ui.refactoring.CRefactoringContext;
* Common base for refactoring tests.
*/
public abstract class RefactoringTestBase extends BaseTestCase {
protected static final NullProgressMonitor NULL_PROGRESS_MONITOR = new NullProgressMonitor();
/** Allows empty files to be created during test setup. */
protected boolean createEmptyFiles = true;
/** See {@link PreferenceConstants.CLASS_MEMBER_ASCENDING_VISIBILITY_ORDER} */
@ -137,7 +134,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
public void tearDown() throws Exception {
if (cproject != null) {
cproject.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT,
NULL_PROGRESS_MONITOR);
npm());
}
resetPreferences();
super.tearDown();
@ -175,7 +172,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
protected void executeRefactoring(Refactoring refactoring, RefactoringContext context,
boolean withUserInput, boolean expectedSuccess) throws CoreException, Exception {
try {
RefactoringStatus initialStatus = refactoring.checkInitialConditions(NULL_PROGRESS_MONITOR);
RefactoringStatus initialStatus = refactoring.checkInitialConditions(npm());
if (!expectedSuccess) {
assertStatusFatalError(initialStatus);
return;
@ -190,7 +187,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
if (withUserInput)
simulateUserInput();
RefactoringStatus finalStatus = refactoring.checkFinalConditions(NULL_PROGRESS_MONITOR);
RefactoringStatus finalStatus = refactoring.checkFinalConditions(npm());
if (expectedFinalWarnings != 0) {
assertStatusWarning(finalStatus, expectedFinalWarnings);
} else if (expectedFinalInfos != 0) {
@ -198,8 +195,8 @@ public abstract class RefactoringTestBase extends BaseTestCase {
} else {
assertStatusOk(finalStatus);
}
Change change = refactoring.createChange(NULL_PROGRESS_MONITOR);
change.perform(NULL_PROGRESS_MONITOR);
Change change = refactoring.createChange(npm());
change.perform(npm());
} finally {
if (context != null)
context.dispose();
@ -212,7 +209,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
RefactoringHistory history = RefactoringHistoryService.getInstance().readRefactoringHistory(
new ByteArrayInputStream(scriptSource.getBytes()), 0);
for (RefactoringDescriptorProxy proxy : history.getDescriptors()) {
RefactoringDescriptor descriptor = proxy.requestDescriptor(NULL_PROGRESS_MONITOR);
RefactoringDescriptor descriptor = proxy.requestDescriptor(npm());
RefactoringStatus status = new RefactoringStatus();
RefactoringContext context = descriptor.createRefactoringContext(status);
assertTrue(status.isOK());

View file

@ -22,6 +22,7 @@ import org.eclipse.cdt.ui.tests.refactoring.extractlocalvariable.ExtractLocalVar
import org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest;
import org.eclipse.cdt.ui.tests.refactoring.hidemethod.HideMethodRefactoringTest;
import org.eclipse.cdt.ui.tests.refactoring.implementmethod.ImplementMethodRefactoringTest;
import org.eclipse.cdt.ui.tests.refactoring.includes.IncludesTestSuite;
import org.eclipse.cdt.ui.tests.refactoring.rename.RenameRegressionTests;
import org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest;
import org.eclipse.cdt.ui.tests.refactoring.utils.UtilTestSuite;
@ -42,6 +43,7 @@ public class RefactoringTestSuite extends TestSuite {
suite.addTest(ImplementMethodRefactoringTest.suite());
suite.addTest(ExtractLocalVariableRefactoringTest.suite());
suite.addTest(ToggleRefactoringTest.suite());
suite.addTest(IncludesTestSuite.suite());
return suite;
}
}

View file

@ -1,11 +1,11 @@
/*******************************************************************************
* Rapperswil, University of applied sciences 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:
* 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:
* Institute for Software - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
@ -181,7 +181,6 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase {
assertRefactoringSuccess();
}
//A.h
//#ifndef A_H_
//#define A_H_
@ -308,7 +307,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase {
public void testLocalVariableDeclaration_3() throws Exception {
assertRefactoringSuccess();
}
//A.h
//#ifndef A_H_
//#define A_H_

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* Copyright (c) 2012, 2013 Google, Inc 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
@ -10,12 +10,16 @@
*******************************************************************************/
package org.eclipse.cdt.ui.tests.refactoring.includes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import junit.framework.TestSuite;
import com.ibm.icu.text.MessageFormat;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
@ -51,7 +55,8 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
fIndex.acquireReadLock();
ITranslationUnit tu = ast.getOriginatingTranslationUnit();
fContext = new InclusionContext(tu, fIndex);
fBindingClassifier = new BindingClassifier(fContext, ast);
fBindingClassifier = new BindingClassifier(fContext);
fBindingClassifier.classifyNodeContents(ast);
}
@Override
@ -69,15 +74,36 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
}
private void assertExpectedBindings(String[] expectedNames, Set<IBinding> bindings, String verb) {
Set<String> remaining = new HashSet<String>(Arrays.asList(expectedNames));
Set<String> expected = new TreeSet<String>(Arrays.asList(expectedNames));
Set<String> extra = new TreeSet<String>();
for (IBinding binding : bindings) {
String name = binding.getName();
if (!remaining.remove(name)) {
fail("Binding \"" + name + "\" should not be " + verb);
}
extra.add(binding.getName());
}
if (!remaining.isEmpty())
fail("Binding \"" + remaining.iterator().next() + "\" is not " + verb);
Set<String> missing = new TreeSet<String>(expected);
missing.removeAll(extra);
extra.removeAll(expected);
if (extra.isEmpty() && missing.isEmpty())
return;
List<String> errors = new ArrayList<String>(2);
if (!missing.isEmpty()) {
errors.add(MessageFormat.format("{0,choice,1#Binding|1<Bindings} \"{1}\" {0,choice,1#is|1<are} not {2}.",
missing.size(), join(missing, "\", \""), verb));
}
if (!extra.isEmpty()) {
errors.add(MessageFormat.format("{0,choice,1#Binding|1<Bindings} \"{1}\" should not be {2}.",
extra.size(), join(extra, "\", \""), verb));
}
fail(join(errors, " "));
}
private String join(Iterable<String> strings, String delimiter) {
StringBuilder buf = new StringBuilder();
for (String str : strings) {
if (buf.length() != 0)
buf.append(delimiter);
buf.append(str);
}
return buf.toString();
}
// class A;
@ -109,4 +135,46 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
public void testClassMember() throws Exception {
assertDefined("f", "A");
}
// class A { void m(); };
// void test(A* a) {
// a->m();
// }
public void testMethodCall() throws Exception {
assertDefined("A");
}
// struct A {};
// struct B {};
// struct C {
// A a;
// static B b;
// };
public void testFieldReference() throws Exception {
assertDefined("A");
assertDeclared("B");
}
// int a;
// void test() {
// void* x = &a;
// }
public void testVariableReference() throws Exception {
assertDefined("a"); // Forward declaration of variables is not allowed by default.
}
// struct A {
// void operator()(int p);
// };
// const A a;
// void test() {
// a(1);
// }
public void testCallOperator() throws Exception {
assertDefined("A", "a"); // Forward declaration of variables is not allowed by default.
}
}

View file

@ -0,0 +1,176 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.refactoring.includes;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.preference.IPreferenceStore;
import org.osgi.framework.Bundle;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
import org.eclipse.cdt.ui.tests.refactoring.TestSourceFile;
import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
/**
* Common base for include-related tests.
*/
public abstract class IncludesTestBase extends BaseTestCase {
protected final String LINE_DELIMITER = "\n";
protected static class FirstHeaderChooser implements IHeaderChooser {
@Override
public IPath chooseHeader(String bindingName, Collection<IPath> headers) {
return headers.isEmpty() ? null : headers.iterator().next();
}
}
/** Expected counts of errors, warnings and info messages */
protected int expectedInitialErrors;
protected int expectedInitialWarnings;
protected int expectedFinalWarnings;
protected int expectedFinalInfos;
protected IIndex index;
protected ICProject cproject;
protected IASTTranslationUnit ast;
protected TestSourceFile selectedFile;
private StringBuilder[] testData;
private boolean cpp = true;
private final Set<TestSourceFile> testFiles = new LinkedHashSet<TestSourceFile>();
protected IncludesTestBase() {
super();
}
protected IncludesTestBase(String name) {
super(name);
}
@Override
public void setUp() throws Exception {
super.setUp();
resetPreferences();
cproject = cpp ?
CProjectHelper.createCCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER) :
CProjectHelper.createCProject(getName() + System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER);
Bundle bundle = CTestPlugin.getDefault().getBundle();
CharSequence[] testData = TestSourceReader.getContentsForTest(bundle, "ui", getClass(), getName(), 0);
IFile sourceFile = null;
for (CharSequence contents : testData) {
TestSourceFile testFile = null;
boolean expectedResult = false;
BufferedReader reader = new BufferedReader(new StringReader(contents.toString()));
String line;
while ((line = reader.readLine()) != null) {
String trimmedLine = line.trim();
if (testFile == null) {
assertTrue("Invalid file name \"" + trimmedLine + "\"", trimmedLine.matches("^(\\w+/)*\\w+\\.\\w+$"));
testFile = new TestSourceFile(trimmedLine);
} else if (isResultDelimiter(trimmedLine)) {
expectedResult = true;
} else if (expectedResult) {
testFile.addLineToExpectedSource(line);
} else {
testFile.addLineToSource(line);
}
}
reader.close();
sourceFile = TestSourceReader.createFile(cproject.getProject(), new Path(testFile.getName()),
testFile.getSource());
testFiles.add(testFile);
selectedFile = testFile;
}
CCorePlugin.getIndexManager().setIndexerId(cproject, IPDOMManager.ID_FAST_INDEXER);
waitForIndexer(cproject);
index= CCorePlugin.getIndexManager().getIndex(cproject);
index.acquireReadLock();
ast = TestSourceReader.createIndexBasedAST(index, cproject, sourceFile);
}
@Override
public void tearDown() throws Exception {
if (cproject != null) {
cproject.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, npm());
}
resetPreferences();
super.tearDown();
}
protected ICProject getCProject() {
return cproject;
}
protected TestSourceFile getSelectedTestFile() {
return selectedFile;
}
protected IFile getSelectedFile() {
if (selectedFile == null)
return null;
return cproject.getProject().getFile(new Path(selectedFile.getName()));
}
protected ITranslationUnit getSelectedTranslationUnit() {
IFile file = getSelectedFile();
if (file == null)
return null;
return (ITranslationUnit) CoreModel.getDefault().create(file);
}
protected boolean isCpp() {
return cpp;
}
protected void setCpp(boolean cpp) {
this.cpp = cpp;
}
private boolean isResultDelimiter(String str) {
if (str.isEmpty())
return false;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) != '=')
return false;
}
return true;
}
protected void resetPreferences() {
}
protected IPreferenceStore getPreferenceStore() {
return CUIPlugin.getDefault().getPreferenceStore();
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* Copyright (c) 2013 Google, Inc 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
@ -8,18 +8,17 @@
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
package org.eclipse.cdt.ui.tests.refactoring.includes;
import org.eclipse.osgi.util.NLS;
import junit.framework.Test;
import junit.framework.TestSuite;
final class Messages extends NLS {
public static String IncludeOrganizer_ChooseHeader;
public class IncludesTestSuite extends TestSuite {
static {
NLS.initializeMessages(Messages.class.getName(), Messages.class);
}
// Do not instantiate
private Messages() {
public static Test suite() throws Exception {
IncludesTestSuite suite = new IncludesTestSuite();
suite.addTest(BindingClassifierTest.suite());
suite.addTest(OrganizeIncludesTest.suite());
return suite;
}
}

View file

@ -0,0 +1,298 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.refactoring.includes;
import java.util.List;
import junit.framework.Test;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeOrganizer;
/**
* Tests for Extract Function refactoring.
*/
public class OrganizeIncludesTest extends IncludesTestBase {
public OrganizeIncludesTest() {
super();
}
public OrganizeIncludesTest(String name) {
super(name);
}
public static Test suite() {
return suite(OrganizeIncludesTest.class);
}
@Override
protected void resetPreferences() {
super.resetPreferences();
getPreferenceStore().setToDefault(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_ENUMS);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_TEMPLATES);
getPreferenceStore().setToDefault(PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS);
getPreferenceStore().setToDefault(PreferenceConstants.INCLUDES_ALLOW_REORDERING);
}
private void assertExpectedResults() throws Exception {
String actual = organizeIncludes(ast.getOriginatingTranslationUnit());
assertEquals(selectedFile.getExpectedSource(), actual);
}
/**
* Invokes include organizer and returns the new contents of the translation unit.
*/
private String organizeIncludes(ITranslationUnit tu) throws Exception {
IHeaderChooser headerChooser = new FirstHeaderChooser();
IncludeOrganizer organizer = new IncludeOrganizer(tu, index, LINE_DELIMITER, headerChooser);
List<TextEdit> edits = organizer.organizeIncludes(ast);
IDocument document = new Document(new String(tu.getContents()));
if (!edits.isEmpty()) {
// Apply text edits.
MultiTextEdit edit = new MultiTextEdit();
edit.addChildren(edits.toArray(new TextEdit[edits.size()]));
edit.apply(document);
}
return document.get();
}
//h1.h
//typedef int my_type;
//A.h
//class A {
// my_type m1();
//};
//A.cpp
//// Comment line 1
//// Comment line 2
//
//// Comment for m1
//my_type A::m1() {
// return 0;
//}
//====================
//// Comment line 1
//// Comment line 2
//
//#include "A.h"
//
//#include "h1.h"
//
//// Comment for m1
//my_type A::m1() {
// return 0;
//}
public void testNoExistingIncludes() throws Exception {
assertExpectedResults();
}
//B.h
//class B {};
//C.h
//class C {};
//A.h
//#if !defined(INCLUDE_GUARD)
//#define INCLUDE_GUARD
//// Comment line 1
//// Comment line 2
//
//// Comment for A
//class A {
// B f;
// C m();
//};
//#endif // INCLUDE_GUARD
//====================
//#if !defined(INCLUDE_GUARD)
//#define INCLUDE_GUARD
//// Comment line 1
//// Comment line 2
//
//#include "B.h"
//
//class C;
//
//// Comment for A
//class A {
// B f;
// C m();
//};
//#endif // INCLUDE_GUARD
public void testIncludeGuards() throws Exception {
assertExpectedResults();
}
//B.h
//template <typename T> class B {};
//C.h
//class C {};
//A.h
//#pragma once
//namespace ns {
//// Comment line 1
//// Comment line 2
//
//// Comment for A
//class A : public B<C> {};
//} // namespace ns
//====================
//#pragma once
//
//#include "B.h"
//#include "C.h"
//
//namespace ns {
//// Comment line 1
//// Comment line 2
//
//// Comment for A
//class A : public B<C> {};
//} // namespace ns
public void testPragmaOnce() throws Exception {
assertExpectedResults();
}
//h1.h
//typedef int Type1;
//h2.h
//class Type2 {};
//h3.h
//enum Type3 { ONE, TWO };
//h4.h
//class Unrelated {};
//A.h
//#include "h1.h"
//class Type2;
//enum class Type3;
//extern Type1 f1();
//extern Type2 f2();
//extern Type3 f3();
//A.cpp
//// Comment
//
//#include "h2.h" /* Required */ // another comment
//#include "h1.h" // Unused
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
//====================
//// Comment
//
//#include "A.h"
//
////#include "h1.h" // Unused
//#include "h2.h" /* Required */ // another comment
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
public void testExistingIncludes() throws Exception {
assertExpectedResults();
}
//h1.h
//typedef int Type1;
//h2.h
//class Type2 {};
//h3.h
//enum class Type3 { ONE, TWO };
//h4.h
//class Unrelated {};
//A.h
//#include "h1.h"
//class Type2;
//enum class Type3;
//extern Type1 f1();
//extern Type2 f2();
//extern Type3 f3();
//A.cpp
//// Comment
//
//#include "h2.h" /* Required */ // another comment
//#include "h1.h" // Unused
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
//====================
//// Comment
//
//#include "h2.h" /* Required */ // another comment
////#include "h1.h" // Unused
//#include "h3.h"
//#include "h5.h" // Unresolved includes are preserved
//#include "A.h"
//
//#ifdef SOME_OTHER_TIME
//#include "h4.h" // Unused but unsafe to remove
//#endif
//
//void test() {
// f1();
// f2();
// f3();
//}
public void testExistingIncludesNoReordering() throws Exception {
getPreferenceStore().setValue(PreferenceConstants.INCLUDES_ALLOW_REORDERING, false);
assertExpectedResults();
}
}

View file

@ -276,6 +276,10 @@ ActionDefinition.openType.description= Open an element in an Editor
ActionDefinition.addInclude.name= Add Include
ActionDefinition.addInclude.description= Create include statement on selection
#Organize Includes
ActionDefinition.addInclude.name= Organize Includes
ActionDefinition.addInclude.description= Evaluates all required includes and replaces the current includes
#Sort Lines
ActionDefinition.sortLines.name= Sort Lines
ActionDefinition.sortLines.description= Sort selected lines alphabetically
@ -593,6 +597,7 @@ renameParticipant.name = Source Folder Rename
FormatAction.label= &Format
IndentAction.label= Correct &Indentation
OrganizeIncludesAction.label= Or&ganize Includes
AddIncludeAction.label= A&dd Include
SortLinesAction.label= Sor&t Lines
CommentAction.label= Co&mment

View file

@ -1884,6 +1884,13 @@
menubarPath="org.eclipse.jdt.ui.source.menu/importGroup"
id="org.eclipse.cdt.ui.actions.SortLines">
</action>
<action
definitionId="org.eclipse.cdt.ui.edit.text.c.organize.includes"
label="%OrganizeIncludesAction.label"
retarget="true"
menubarPath="org.eclipse.jdt.ui.source.menu/importGroup"
id="org.eclipse.cdt.ui.actions.OrganizeIncludes">
</action>
<action
definitionId="org.eclipse.cdt.ui.edit.text.c.add.include"
label="%AddIncludeAction.label"
@ -2451,6 +2458,11 @@
contextId="org.eclipse.cdt.ui.cViewScope"
commandId="org.eclipse.cdt.ui.navigate.open.type.in.hierarchy"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
<key
sequence="M1+M2+O"
contextId="org.eclipse.cdt.ui.cEditorScope"
commandId="org.eclipse.cdt.ui.edit.text.c.organize.includes"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
<key
sequence="M1+M2+N"
contextId="org.eclipse.cdt.ui.cEditorScope"
@ -2952,6 +2964,12 @@
categoryId="org.eclipse.cdt.ui.category.source"
id="org.eclipse.cdt.ui.edit.text.c.add.include">
</command>
<command
name="%ActionDefinition.organizeIncludes.name"
description="%ActionDefinition.OrganizeIncludes.description"
categoryId="org.eclipse.cdt.ui.category.source"
id="org.eclipse.cdt.ui.edit.text.c.organize.includes">
</command>
<command
name="%ActionDefinition.sortLines.name"
description="%ActionDefinition.sortLines.description"
@ -4606,6 +4624,7 @@
<key name="removeTrailingWhitespaceEditedLines"/>
<key name="Refactoring.savealleditors"/>
<key name="Refactor.lightweight"/>
<key name="organizeIncludes." match="prefix"/>
<key name="spelling_" match="prefix"/>
<key name="org.eclipse.cdt.ui.add_comments"/>
<key name="codetemplates.includeGuardGenerationScheme"/>
@ -4628,6 +4647,9 @@
<entry node="org.eclipse.cdt.ui">
<key name="codetemplates." match="prefix"/>
<key name="nameStyle." match="prefix"/>
<key name="includeStyle." match="prefix"/>
<key name="forwardDeclare." match="prefix"/>
<key name="includes.partnerFileSuffixes"/>
<key name="formatter_profile"/>
<key name="class_member_ascending_visibility_order"/>
<key name="function_output_parameters_before_input"/>

View file

@ -0,0 +1,145 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.cdt.ui.CUIPlugin;
/**
* Synchronously executes a {@link Job} while allowing user to cancel it if it takes too long.
*/
public final class BusyCursorJobRunner {
/**
* Adapts a {@link Job} to be an {@link IRunnableWithProgress}.
*/
private static class JobRunnableWithProgressAdapter implements IRunnableWithProgress {
private final Job job;
/**
* Creates the {@link IRunnableWithProgress} from the {@link Job}.
*/
public JobRunnableWithProgressAdapter(Job job) {
this.job = job;
}
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
IStatus result;
try {
monitor.beginTask(job.getName(), IProgressMonitor.UNKNOWN);
result = executeAndWait(job, monitor);
} catch (RuntimeException e) {
throw new InvocationTargetException(e);
}
switch (result.getSeverity()) {
case IStatus.CANCEL:
throw new InterruptedException();
case IStatus.ERROR:
if (result.getException() instanceof OperationCanceledException) {
throw new InterruptedException();
}
throw new InvocationTargetException(new CoreException(result));
}
}
}
/**
* Runs the given job and waits for it to finish. If executing in the UI thread, sets the cursor
* to busy while the job is being executed.
*
* @param job the job to execute
* @return the status reflecting the result of the job execution
*/
public static IStatus execute(Job job) {
boolean inUiThread = Thread.currentThread() == Display.getDefault().getThread();
if (inUiThread) {
return busyCursorWhile(job);
}
return executeAndWait(job, new NullProgressMonitor());
}
private static IStatus busyCursorWhile(Job job) {
try {
IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
progressService.busyCursorWhile(new JobRunnableWithProgressAdapter(job));
} catch (InterruptedException e) {
return Status.CANCEL_STATUS; // Operation was cancelled.
} catch (InvocationTargetException e) {
Throwable targetException = e.getTargetException();
if (targetException instanceof CoreException) {
return ((CoreException) targetException).getStatus();
}
return new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, e.getMessage(), e);
}
return Status.OK_STATUS;
}
private static IStatus executeAndWait(final Job job, IProgressMonitor monitor) {
final IStatus[] statusHolder = new IStatus[1];
IJobManager jobManager = Job.getJobManager();
JobChangeAdapter listener = new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
super.done(event);
if (event.getJob() == job) {
synchronized (statusHolder) {
statusHolder[0] = event.getResult();
statusHolder.notifyAll();
}
}
}
};
jobManager.addJobChangeListener(listener);
job.schedule();
try {
synchronized (statusHolder) {
while (statusHolder[0] == null) {
try {
statusHolder.wait(100);
if (monitor.isCanceled()) {
job.cancel();
}
} catch (InterruptedException e) {
job.cancel();
return Status.CANCEL_STATUS;
}
}
return statusHolder[0];
}
} finally {
monitor.done();
jobManager.removeJobChangeListener(listener);
}
}
private BusyCursorJobRunner() {}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 IBM Corporation and others.
* Copyright (c) 2006, 2013 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
@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* QNX Software System
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui;
@ -19,7 +20,6 @@ import org.eclipse.cdt.ui.CUIPlugin;
* <p>
* This interface contains constants only; it is not intended to be implemented or extended.
* </p>
*
*/
public interface ICHelpContextIds {
public static final String PREFIX = CUIPlugin.PLUGIN_ID + "."; //$NON-NLS-1$
@ -33,9 +33,10 @@ public interface ICHelpContextIds {
public static final String OPEN_PROJECT_WIZARD_ACTION = PREFIX + "open_project_wizard_action"; //$NON-NLS-1$
public static final String CONVERT_TO_CCPP_WIZARD_PAGE = PREFIX + "cdt_t_conv_proj_context"; //$NON-NLS-1$
public static final String NEW_C_FILE_WIZARD_PAGE = PREFIX + "cdt_creating_cpp_file_context"; //$NON-NLS-1$
// Actions
// Actions
public static final String ADD_INCLUDE_ON_SELECTION_ACTION = PREFIX + "add_includes_on_selection_action_context"; //$NON-NLS-1$;
public static final String ORGANIZE_INCLUDES_ACTION = PREFIX + "organize_includes_action"; //$NON-NLS-1$;
public static final String FILTER_PUBLIC_ACTION= PREFIX + "filter_public_action"; //$NON-NLS-1$
public static final String FILTER_FIELDS_ACTION= PREFIX + "filter_fields_action"; //$NON-NLS-1$
public static final String FILTER_STATIC_ACTION= PREFIX + "filter_static_action"; //$NON-NLS-1$

View file

@ -33,14 +33,14 @@ import org.eclipse.ui.texteditor.RetargetTextEditorAction;
import org.eclipse.cdt.ui.actions.CdtActionConstants;
import org.eclipse.cdt.internal.ui.IContextMenuConstants;
import org.eclipse.cdt.internal.ui.actions.FindWordAction;
import org.eclipse.cdt.internal.ui.actions.GoToNextPreviousMemberAction;
import org.eclipse.cdt.internal.ui.actions.GotoNextBookmarkAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectEnclosingAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectHistoryAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectNextAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectPreviousAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectionAction;
import org.eclipse.cdt.internal.ui.actions.StructureSelectEnclosingAction;
import org.eclipse.cdt.internal.ui.actions.FindWordAction;
import org.eclipse.cdt.internal.ui.actions.GoToNextPreviousMemberAction;
import org.eclipse.cdt.internal.ui.actions.GotoNextBookmarkAction;
public class CEditorActionContributor extends TextEditorActionContributor {
@ -229,6 +229,7 @@ public class CEditorActionContributor extends TextEditorActionContributor {
bars.setGlobalActionHandler(CdtActionConstants.REMOVE_BLOCK_COMMENT, getAction(textEditor, "RemoveBlockComment")); //$NON-NLS-1$
bars.setGlobalActionHandler(CdtActionConstants.INDENT, getAction(textEditor, "Indent")); //$NON-NLS-1$
bars.setGlobalActionHandler(CdtActionConstants.ADD_INCLUDE, getAction(textEditor, "AddIncludeOnSelection")); //$NON-NLS-1$
bars.setGlobalActionHandler(CdtActionConstants.ORGANIZE_INCLUDES, getAction(textEditor, "OrganizeIncludes")); //$NON-NLS-1$
bars.setGlobalActionHandler(CdtActionConstants.SORT_LINES, getAction(textEditor, "SortLines")); //$NON-NLS-1$
IAction action= getAction(textEditor, ITextEditorActionConstants.REFRESH);

View file

@ -38,10 +38,12 @@ public final class CEditorMessages extends NLS {
public static String AddIncludesOperation_description;
public static String OrganizeIncludes_label;
public static String OrganizeIncludes_description;
public static String OrganizeIncludes_action;
public static String OrganizeIncludes_error_title;
public static String OrganizeIncludes_insertion_failed;
public static String OrganizeIncludes_help_provider_error;
public static String OrganizeIncludes_failed;
public static String OrganizeIncludes_choose_header;
public static String OrganizeIncludesOperation_description;
public static String ShowInCView_description;
public static String ShowInCView_label;

View file

@ -24,10 +24,12 @@ AddIncludesOperation_description=Adding include statement
OrganizeIncludes_label=Organize Includes
OrganizeIncludes_description=Organize includes for current file
OrganizeIncludes_action=Organizing includes
OrganizeIncludes_error_title=Error Organizing Includes
OrganizeIncludes_insertion_failed=Adding include statements failed
OrganizeIncludes_help_provider_error=Help provider error
OrganizeIncludes_failed=Organize Includes operation failed
OrganizeIncludes_choose_header=Choose a header file to include for symbol ''{0}''
OrganizeIncludesOperation_description=Organizing include statements
ShowInCView_description=Show the current resource in the C/C++ Projects view

View file

@ -72,6 +72,12 @@ public interface ICEditorActionDefinitionIds extends ITextEditorActionDefinition
*/
public static final String ADD_INCLUDE= "org.eclipse.cdt.ui.edit.text.c.add.include"; //$NON-NLS-1$
/**
* Action definition ID of the source -> organize includes action
* (value <code>"org.eclipse.cdt.ui.edit.text.c.organize.includes"</code>).
*/
public static final String ORGANIZE_INCLUDES= "org.eclipse.cdt.ui.edit.text.c.organize.includes"; //$NON-NLS-1$
/**
* Action definition ID of the open declaration action
* (value <code>"org.eclipse.cdt.ui.edit.opendecl"</code>).

View file

@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
/**
* Dialog-based header chooser.
*/
public class InteractiveHeaderChooser implements IHeaderChooser {
private final Shell shell;
Map<Collection<IPath>, IPath> userChoiceCache;
public InteractiveHeaderChooser(Shell shell) {
this.shell = shell;
userChoiceCache = new HashMap<Collection<IPath>, IPath>();
}
@Override
public IPath chooseHeader(final String bindingName, Collection<IPath> headers) {
if (headers.isEmpty())
return null;
if (headers.size() == 1)
return headers.iterator().next();
Set<IPath> cacheKey = new HashSet<IPath>(headers);
// Check the decision cache. If the cache doesn't help, ask the user.
// Query the cache.
if (userChoiceCache.containsKey(cacheKey)) {
return userChoiceCache.get(cacheKey);
}
// Ask the user.
final IPath[] elemArray = headers.toArray(new IPath[headers.size()]);
final IPath[] selectedElement = new IPath[1];
runInUIThread(new Runnable() {
@Override
public void run() {
if (!shell.isDisposed()) {
ElementListSelectionDialog dialog =
new ElementListSelectionDialog(shell, new LabelProvider());
dialog.setElements(elemArray);
dialog.setTitle(CEditorMessages.OrganizeIncludes_label);
dialog.setMessage(NLS.bind(CEditorMessages.OrganizeIncludes_choose_header, bindingName));
if (dialog.open() == Window.OK) {
selectedElement[0] = (IPath) dialog.getFirstResult();
}
}
}
});
IPath selectedHeader = selectedElement[0];
if (selectedHeader != null)
userChoiceCache.put(headers, selectedHeader); // Remember user's choice.
return selectedHeader;
}
private void runInUIThread(Runnable runnable) {
if (Display.getCurrent() != null) {
runnable.run();
} else {
Display.getDefault().syncExec(runnable);
}
}
}

View file

@ -7,12 +7,25 @@
*
* Contributors:
* Mathias Kunter - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.text.undo.DocumentUndoManagerRegistry;
import org.eclipse.text.undo.IDocumentUndoManager;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.TextEditorAction;
@ -25,7 +38,9 @@ import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.SharedASTJob;
import org.eclipse.cdt.internal.ui.BusyCursorJobRunner;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeOrganizer;
/**
@ -37,9 +52,84 @@ public class OrganizeIncludesAction extends TextEditorAction {
* @param editor The editor on which this organize includes action should operate.
*/
public OrganizeIncludesAction(ITextEditor editor) {
// TODO Fix ID's
super(CEditorMessages.getBundleForConstructedKeys(), "OrganizeIncludes.", editor); //$NON-NLS-1$
CUIPlugin.getDefault().getWorkbench().getHelpSystem().setHelp(this, ICHelpContextIds.ADD_INCLUDE_ON_SELECTION_ACTION);
CUIPlugin.getDefault().getWorkbench().getHelpSystem().setHelp(this, ICHelpContextIds.ORGANIZE_INCLUDES_ACTION);
}
@Override
public void run() {
final ITextEditor editor = getTextEditor();
final ITranslationUnit tu = getTranslationUnit(editor);
if (tu == null) {
return;
}
if (!validateEditorInputState()) {
return;
}
final IHeaderChooser headerChooser = new InteractiveHeaderChooser(editor.getSite().getShell());
final String lineDelimiter = getLineDelimiter(editor);
final List<TextEdit> edits = new ArrayList<TextEdit>();
SharedASTJob job = new SharedASTJob(CEditorMessages.OrganizeIncludes_action, tu) {
@Override
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
IIndex index= CCorePlugin.getIndexManager().getIndex(tu.getCProject(),
IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_EXTENSION_FRAGMENTS_ADD_IMPORT);
try {
index.acquireReadLock();
IncludeOrganizer organizer = new IncludeOrganizer(tu, index, lineDelimiter, headerChooser);
edits.addAll(organizer.organizeIncludes(ast));
return Status.OK_STATUS;
} catch (InterruptedException e) {
return Status.CANCEL_STATUS;
} finally {
index.releaseReadLock();
}
}
};
IStatus status = BusyCursorJobRunner.execute(job);
if (status.isOK()) {
if (!edits.isEmpty()) {
// Apply text edits.
MultiTextEdit edit = new MultiTextEdit();
edit.addChildren(edits.toArray(new TextEdit[edits.size()]));
IEditorInput editorInput = editor.getEditorInput();
IDocument document = editor.getDocumentProvider().getDocument(editorInput);
IDocumentUndoManager manager= DocumentUndoManagerRegistry.getDocumentUndoManager(document);
manager.beginCompoundChange();
try {
edit.apply(document);
} catch (MalformedTreeException e) {
CUIPlugin.log(e);
} catch (BadLocationException e) {
CUIPlugin.log(e);
}
manager.endCompoundChange();
}
} else if (status.matches(IStatus.ERROR)) {
ErrorDialog.openError(editor.getEditorSite().getShell(),
CEditorMessages.OrganizeIncludes_error_title,
CEditorMessages.OrganizeIncludes_insertion_failed, status);
}
}
private static String getLineDelimiter(ITextEditor editor) {
try {
IEditorInput editorInput = editor.getEditorInput();
IDocument document = editor.getDocumentProvider().getDocument(editorInput);
String delim= document.getLineDelimiter(0);
if (delim != null) {
return delim;
}
} catch (BadLocationException e) {
}
return System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$
}
@Override
public void update() {
ITextEditor editor = getTextEditor();
setEnabled(editor != null && getTranslationUnit(editor) != null);
}
/**
@ -53,46 +143,4 @@ public class OrganizeIncludesAction extends TextEditorAction {
}
return CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput());
}
@Override
public void run() {
final ITextEditor editor = getTextEditor();
final ITranslationUnit tu = getTranslationUnit(editor);
if (tu == null) {
return;
}
try {
if (!validateEditorInputState()) {
return;
}
SharedASTJob job = new SharedASTJob(CEditorMessages.OrganizeIncludes_label, tu) {
@Override
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
IIndex index= CCorePlugin.getIndexManager().getIndex(tu.getCProject(),
IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_EXTENSION_FRAGMENTS_ADD_IMPORT);
try {
index.acquireReadLock();
IncludeOrganizer organizer = new IncludeOrganizer(editor, tu, index);
organizer.organizeIncludes(ast);
return Status.OK_STATUS;
} catch (InterruptedException e) {
return Status.CANCEL_STATUS;
} finally {
index.releaseReadLock();
}
}
};
job.schedule();
job.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
@Override
public void update() {
ITextEditor editor = getTextEditor();
setEnabled(editor != null && getTranslationUnit(editor) != null);
}
}

View file

@ -19,27 +19,28 @@ import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle.IncludeKind;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences;
/**
* The preference block for configuring style of include statements.
*/
public class IncludeStyleBlock extends TabConfigurationBlock {
static final Key KEY_STYLE_RELATED = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_RELATED);
static final Key KEY_STYLE_PARTNER = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_PARTNER);
static final Key KEY_STYLE_SAME_FOLDER = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_SAME_FOLDER);
static final Key KEY_STYLE_SUBFOLDER = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_SUBFOLDER);
static final Key KEY_STYLE_SYSTEM = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_SYSTEM);
static final Key KEY_STYLE_SYSTEM_WITH_EXTENSION = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_SYSTEM_WITH_EXTENSION);
static final Key KEY_STYLE_SYSTEM_WITHOUT_EXTENSION = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION);
static final Key KEY_STYLE_OTHER = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_OTHER);
static final Key KEY_STYLE_SAME_PROJECT = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_SAME_PROJECT);
static final Key KEY_STYLE_OTHER_PROJECT = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_OTHER_PROJECT);
static final Key KEY_STYLE_EXTERNAL = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_EXTERNAL);
static final Key KEY_STYLE_MATCHING_PATTERN = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_MATCHING_PATTERN);
static final Key KEY_STYLE_RELATED = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_RELATED);
static final Key KEY_STYLE_PARTNER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_PARTNER);
static final Key KEY_STYLE_SAME_FOLDER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SAME_FOLDER);
static final Key KEY_STYLE_SUBFOLDER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SUBFOLDER);
static final Key KEY_STYLE_SYSTEM = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SYSTEM);
static final Key KEY_STYLE_SYSTEM_WITH_EXTENSION = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITH_EXTENSION);
static final Key KEY_STYLE_SYSTEM_WITHOUT_EXTENSION = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION);
static final Key KEY_STYLE_OTHER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_OTHER);
static final Key KEY_STYLE_SAME_PROJECT = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SAME_PROJECT);
static final Key KEY_STYLE_OTHER_PROJECT = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_OTHER_PROJECT);
static final Key KEY_STYLE_EXTERNAL = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_EXTERNAL);
static final Key KEY_STYLE_MATCHING_PATTERN = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_MATCHING_PATTERN);
static final Map<IncludeKind, Key> KEY_MAP = createKeyMap();
static final Key[] STYLE_KEYS = KEY_MAP.values().toArray(new Key[KEY_MAP.size()]);

View file

@ -17,9 +17,10 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences;
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences.UnusedStatementDisposition;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil;
@ -27,13 +28,14 @@ import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil;
* The preference block for configuring Organize Includes command.
*/
public class OrganizeIncludesBlock extends OptionsConfigurationBlock {
private static final Key KEY_HEURISTIC_HEADER_SUBSTITUTION = getCDTUIKey(IncludePreferences.PREF_HEURISTIC_HEADER_SUBSTITUTION);
private static final Key KEY_INCLUDES_REORDERING = getCDTUIKey(IncludePreferences.PREF_INCLUDES_REORDERING);
private static final Key KEY_UNUSED_STATEMENTS_DISPOSITION = getCDTUIKey(IncludePreferences.PREF_UNUSED_STATEMENTS_DISPOSITION);
private static final Key KEY_FORWARD_DECLARE_COMPOSITE_TYPES = getCDTUIKey(IncludePreferences.PREF_FORWARD_DECLARE_COMPOSITE_TYPES);
private static final Key KEY_FORWARD_DECLARE_ENUMS = getCDTUIKey(IncludePreferences.PREF_FORWARD_DECLARE_ENUMS);
private static final Key KEY_FORWARD_DECLARE_FUNCTIONS = getCDTUIKey(IncludePreferences.PREF_FORWARD_DECLARE_FUNCTIONS);
private static final Key KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS = getCDTUIKey(IncludePreferences.PREF_FORWARD_DECLARE_NAMESPACE_ELEMENTS);
private static final Key KEY_HEURISTIC_HEADER_SUBSTITUTION = getCDTUIKey(PreferenceConstants.INCLUDES_HEURISTIC_HEADER_SUBSTITUTION);
private static final Key KEY_INCLUDES_REORDERING = getCDTUIKey(PreferenceConstants.INCLUDES_ALLOW_REORDERING);
private static final Key KEY_UNUSED_STATEMENTS_DISPOSITION = getCDTUIKey(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION);
private static final Key KEY_FORWARD_DECLARE_COMPOSITE_TYPES = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES);
private static final Key KEY_FORWARD_DECLARE_ENUMS = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_ENUMS);
private static final Key KEY_FORWARD_DECLARE_FUNCTIONS = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS);
private static final Key KEY_FORWARD_DECLARE_TEMPLATES = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_TEMPLATES);
private static final Key KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS);
private static final String[] DISPOSITION_VALUES = {
UnusedStatementDisposition.REMOVE.toString(),
@ -53,6 +55,7 @@ public class OrganizeIncludesBlock extends OptionsConfigurationBlock {
KEY_FORWARD_DECLARE_COMPOSITE_TYPES,
KEY_FORWARD_DECLARE_ENUMS,
KEY_FORWARD_DECLARE_FUNCTIONS,
KEY_FORWARD_DECLARE_TEMPLATES,
KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS,
};
@ -87,6 +90,9 @@ public class OrganizeIncludesBlock extends OptionsConfigurationBlock {
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_forward_declare_functions,
KEY_FORWARD_DECLARE_FUNCTIONS, TRUE_FALSE, 0);
LayoutUtil.setHorizontalSpan(control, 2);
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_forward_declare_templates,
KEY_FORWARD_DECLARE_TEMPLATES, TRUE_FALSE, 0);
LayoutUtil.setHorizontalSpan(control, 2);
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_forward_declare_namespace_elements,
KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS, TRUE_FALSE, 0);
LayoutUtil.setHorizontalSpan(control, 2);

View file

@ -443,6 +443,7 @@ public final class PreferencesMessages extends NLS {
public static String OrganizeIncludesBlock_forward_declare_composite_types;
public static String OrganizeIncludesBlock_forward_declare_enums;
public static String OrganizeIncludesBlock_forward_declare_functions;
public static String OrganizeIncludesBlock_forward_declare_templates;
public static String OrganizeIncludesBlock_forward_declare_namespace_elements;
public static String OrganizeIncludesBlock_heuristic_header_substitution;
public static String OrganizeIncludesBlock_unused_statements;

View file

@ -499,6 +499,7 @@ OrganizeIncludesBlock_allow_reordering= Allow &reordering of includes
OrganizeIncludesBlock_forward_declare_composite_types= Forward declare &classes, structs and unions
OrganizeIncludesBlock_forward_declare_enums= Forward declare &enums when possible
OrganizeIncludesBlock_forward_declare_functions= Forward declare &functions
OrganizeIncludesBlock_forward_declare_templates= Forward declare &templates
OrganizeIncludesBlock_forward_declare_namespace_elements= Forward declare &namespace elements
OrganizeIncludesBlock_heuristic_header_substitution= Allow &heuristic header file substitution
OrganizeIncludesBlock_unused_statements= &Unused Includes and Forward Declarations:

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* Copyright (c) 2012, 2013 Google, Inc 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

View file

@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
import java.util.Collection;
import org.eclipse.core.runtime.IPath;
/**
* Interface for selecting one of alternative headers.
*/
public interface IHeaderChooser {
/**
* Chooses one header out of multiple alternatives.
*
* @param bindingName the name of the binding for which the header is selected
* @param headers absolute file system locations of the headers defining the binding
* @return the chosen header or {@code null} if nothing was selected
*/
public IPath chooseHeader(String bindingName, Collection<IPath> headers);
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* Copyright (c) 2012, 2013 Google, Inc 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

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* Copyright (c) 2012, 2013 Google, Inc 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

View file

@ -34,26 +34,30 @@ public class IncludePreferences {
public final Map<IncludeKind, IncludeGroupStyle> includeStyles;
public final boolean allowReordering;
public final boolean heuristicHeaderSubstitution;
public final boolean allowPartnerIndirectInclusion;
public final boolean forwardDeclareCompositeTypes;
public final boolean forwardDeclareEnums;
public final boolean forwardDeclareFunctions;
// TODO(sprigogin): Create a preference.
public final boolean forwardDeclareExternalVariables = false;
public final boolean forwardDeclareTemplates;
public final boolean forwardDeclareNamespaceElements;
public final UnusedStatementDisposition unusedStatementsDisposition;
public final String[] partnerFileSuffixes;
public IncludePreferences(ICProject project) {
includeStyles = new HashMap<IncludeKind, IncludeGroupStyle>();
loadStyle(IncludeKind.RELATED, PREF_INCLUDE_STYLE_RELATED, project);
loadStyle(IncludeKind.PARTNER, PREF_INCLUDE_STYLE_PARTNER, project);
loadStyle(IncludeKind.IN_SAME_FOLDER, PREF_INCLUDE_STYLE_SAME_FOLDER, project);
loadStyle(IncludeKind.IN_SUBFOLDER, PREF_INCLUDE_STYLE_SUBFOLDER, project);
loadStyle(IncludeKind.SYSTEM, PREF_INCLUDE_STYLE_SYSTEM, project);
loadStyle(IncludeKind.SYSTEM_WITH_EXTENSION, PREF_INCLUDE_STYLE_SYSTEM_WITH_EXTENSION, project);
loadStyle(IncludeKind.SYSTEM_WITHOUT_EXTENSION, PREF_INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION, project);
loadStyle(IncludeKind.OTHER, PREF_INCLUDE_STYLE_OTHER, project);
loadStyle(IncludeKind.IN_SAME_PROJECT, PREF_INCLUDE_STYLE_SAME_PROJECT, project);
loadStyle(IncludeKind.IN_OTHER_PROJECT, PREF_INCLUDE_STYLE_OTHER_PROJECT, project);
loadStyle(IncludeKind.EXTERNAL, PREF_INCLUDE_STYLE_EXTERNAL, project);
loadStyle(IncludeKind.RELATED, PreferenceConstants.INCLUDE_STYLE_RELATED, project);
loadStyle(IncludeKind.PARTNER, PreferenceConstants.INCLUDE_STYLE_PARTNER, project);
loadStyle(IncludeKind.IN_SAME_FOLDER, PreferenceConstants.INCLUDE_STYLE_SAME_FOLDER, project);
loadStyle(IncludeKind.IN_SUBFOLDER, PreferenceConstants.INCLUDE_STYLE_SUBFOLDER, project);
loadStyle(IncludeKind.SYSTEM, PreferenceConstants.INCLUDE_STYLE_SYSTEM, project);
loadStyle(IncludeKind.SYSTEM_WITH_EXTENSION, PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITH_EXTENSION, project);
loadStyle(IncludeKind.SYSTEM_WITHOUT_EXTENSION, PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION, project);
loadStyle(IncludeKind.OTHER, PreferenceConstants.INCLUDE_STYLE_OTHER, project);
loadStyle(IncludeKind.IN_SAME_PROJECT, PreferenceConstants.INCLUDE_STYLE_SAME_PROJECT, project);
loadStyle(IncludeKind.IN_OTHER_PROJECT, PreferenceConstants.INCLUDE_STYLE_OTHER_PROJECT, project);
loadStyle(IncludeKind.EXTERNAL, PreferenceConstants.INCLUDE_STYLE_EXTERNAL, project);
// Unclassified includes are always kept together.
includeStyles.get(IncludeKind.OTHER).setKeepTogether(true);
// Normalize order property of the styles to make sure that the numbers are sequential.
@ -65,26 +69,31 @@ public class IncludePreferences {
// TODO(sprigogin): Load styles for headers matching patterns.
forwardDeclareCompositeTypes = PreferenceConstants.getPreference(
PREF_FORWARD_DECLARE_COMPOSITE_TYPES, project, true);
PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES, project, true);
forwardDeclareEnums = PreferenceConstants.getPreference(
PREF_FORWARD_DECLARE_ENUMS, project, false);
PreferenceConstants.FORWARD_DECLARE_ENUMS, project, false);
forwardDeclareFunctions = PreferenceConstants.getPreference(
PREF_FORWARD_DECLARE_FUNCTIONS, project, false);
PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, project, false);
forwardDeclareTemplates = PreferenceConstants.getPreference(
PreferenceConstants.FORWARD_DECLARE_TEMPLATES, project, false);
forwardDeclareNamespaceElements = PreferenceConstants.getPreference(
PREF_FORWARD_DECLARE_NAMESPACE_ELEMENTS, project, true);
PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS, project, true);
String value = PreferenceConstants.getPreference(
PREF_PARTNER_FILE_SUFFIXES, project, DEFAULT_PARTNER_FILE_SUFFIXES);
PreferenceConstants.INCLUDES_PARTNER_FILE_SUFFIXES, project, DEFAULT_PARTNER_FILE_SUFFIXES);
partnerFileSuffixes = value.split(","); //$NON-NLS-1$
heuristicHeaderSubstitution = PreferenceConstants.getPreference(
PREF_HEURISTIC_HEADER_SUBSTITUTION, project, true);
PreferenceConstants.INCLUDES_HEURISTIC_HEADER_SUBSTITUTION, project, true);
allowReordering = PreferenceConstants.getPreference(
PREF_INCLUDES_REORDERING, project, true);
PreferenceConstants.INCLUDES_ALLOW_REORDERING, project, true);
// TODO(sprigogin): Create a preference for this.
allowPartnerIndirectInclusion = false;
// Unused include handling preferences
value = PreferenceConstants.getPreference(PREF_UNUSED_STATEMENTS_DISPOSITION, project, null);
value = PreferenceConstants.getPreference(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION, project, null);
UnusedStatementDisposition disposition = null;
if (value != null)
disposition = UnusedStatementDisposition.valueOf(value);
@ -103,148 +112,6 @@ public class IncludePreferences {
includeStyles.put(includeKind, style);
}
// TODO(sprigogin): Move the constants and defaults to PreferenceConstants.
/**
* Whether composite types should be forward declared if possible.
*
* Examples:
* class X;
* struct Y;
* union Z;
*/
public static final String PREF_FORWARD_DECLARE_COMPOSITE_TYPES = "forward_declare_composite_types"; //$NON-NLS-1$
/**
* Whether C++11-style enums should be forward declared if possible.
*
* Example:
* enum class X;
*/
public static final String PREF_FORWARD_DECLARE_ENUMS = "forward_declare_enums"; //$NON-NLS-1$
/**
* Whether C-style functions should be forward declared if possible.
*
* Example:
* void foo();
*/
public static final String PREF_FORWARD_DECLARE_FUNCTIONS = "forward_declare_functions"; //$NON-NLS-1$
/**
* Whether elements nested within namespaces should be forward declared if possible.
*
* Examples:
* namespace N { class X; }
*/
public static final String PREF_FORWARD_DECLARE_NAMESPACE_ELEMENTS = "forward_declare_namespace_elements"; //$NON-NLS-1$
/**
* Defines a list of file name suffixes. A header file and the including file are considered
* partners if their file names without extensions are either identical or differ by one of
* these suffixes.
*/
public static final String PREF_PARTNER_FILE_SUFFIXES = "include_partner_file_suffixes"; //$NON-NLS-1$
/**
* Whether a heuristic approach should be used to decide which C++ header files to include.
* The heuristic prefers headers which have no file extension and / or are named like the symbol
* which should be defined. This often works out nicely since it's a commonly used naming
* convention for C++ library headers.
*/
public static final String PREF_HEURISTIC_HEADER_SUBSTITUTION = "organize_includes_heuristic_header_substitution"; //$NON-NLS-1$
/**
* Whether it's allowed to reorder existing include directives. If this preference is set to
* false, the original order is kept as far as possible. This may be necessary to avoid breaking
* code which makes assumptions about the order of the include directives. If this is set to
* true, a different sort order can be applied. Groups of includes are ordered according to
* the values returned by
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle#getOrder()} method.
* Includes within each group are ordered alphabetically.
*/
public static final String PREF_INCLUDES_REORDERING = "organize_includes_allow_reordering"; //$NON-NLS-1$
/**
* Determines what should be done with any unused include directives and forward declarations.
* This preference may have one of the three values defined by
* {@link UnusedStatementDisposition} enumeration ("REMOVE", "COMMENT_OUT", "KEEP").
*/
public static final String PREF_UNUSED_STATEMENTS_DISPOSITION = "organize_includes_unused_statements"; //$NON-NLS-1$
/**
* Include style for headers closely related to the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*/
public static final String PREF_INCLUDE_STYLE_RELATED = "include_style_related"; //$NON-NLS-1$
/**
* Include style for the header with the same name as the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*/
public static final String PREF_INCLUDE_STYLE_PARTNER = "include_style_partner"; //$NON-NLS-1$
/**
* Include style for headers in the same folder as the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*/
public static final String PREF_INCLUDE_STYLE_SAME_FOLDER = "include_style_same_folder"; //$NON-NLS-1$
/**
* Include style for headers in subfolders of the folder containing the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*/
public static final String PREF_INCLUDE_STYLE_SUBFOLDER = "include_style_subfolder"; //$NON-NLS-1$
/**
* Include style for system headers.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*/
public static final String PREF_INCLUDE_STYLE_SYSTEM = "include_style_system"; //$NON-NLS-1$
/**
* Include style for C-style system headers with a file name extension.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*/
public static final String PREF_INCLUDE_STYLE_SYSTEM_WITH_EXTENSION = "include_style_system_with_extension"; //$NON-NLS-1$
/**
* Include style for C++-style system headers without a file name extension.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*/
public static final String PREF_INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION = "include_style_system_without_extension"; //$NON-NLS-1$
/**
* Include style for headers not closely related to the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*/
public static final String PREF_INCLUDE_STYLE_OTHER = "include_style_other"; //$NON-NLS-1$
/**
* Include style for headers in the same project as the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*/
public static final String PREF_INCLUDE_STYLE_SAME_PROJECT = "include_style_in_same_project"; //$NON-NLS-1$
/**
* Include style for headers in a different project than the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*/
public static final String PREF_INCLUDE_STYLE_OTHER_PROJECT = "include_style_in_other_project"; //$NON-NLS-1$
/**
* Include style for headers outside Eclipse workspace.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*/
public static final String PREF_INCLUDE_STYLE_EXTERNAL = "include_style_external"; //$NON-NLS-1$
/**
* Include styles for headers matching user-defined patterns.
* The value of the preference is an XML representation of one or more
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}s.
*/
public static final String PREF_INCLUDE_STYLE_MATCHING_PATTERN = "include_style_matching_pattern"; //$NON-NLS-1$
/**
* Initializes the given preference store with the default values.
*
@ -252,50 +119,51 @@ public class IncludePreferences {
*/
public static void initializeDefaultValues(IPreferenceStore store) {
IncludeGroupStyle style = new IncludeGroupStyle(IncludeKind.RELATED);
store.setDefault(PREF_INCLUDE_STYLE_RELATED, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_RELATED, style.toString());
style = new IncludeGroupStyle(IncludeKind.PARTNER);
style.setKeepTogether(true);
style.setBlankLineBefore(true);
style.setOrder(0);
store.setDefault(PREF_INCLUDE_STYLE_PARTNER, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_PARTNER, style.toString());
style = new IncludeGroupStyle(IncludeKind.IN_SAME_FOLDER);
store.setDefault(PREF_INCLUDE_STYLE_SAME_FOLDER, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SAME_FOLDER, style.toString());
style = new IncludeGroupStyle(IncludeKind.IN_SUBFOLDER);
store.setDefault(PREF_INCLUDE_STYLE_SUBFOLDER, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SUBFOLDER, style.toString());
style = new IncludeGroupStyle(IncludeKind.SYSTEM);
style.setKeepTogether(true);
style.setBlankLineBefore(true);
store.setDefault(PREF_INCLUDE_STYLE_SYSTEM, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SYSTEM, style.toString());
style = new IncludeGroupStyle(IncludeKind.SYSTEM_WITH_EXTENSION);
style.setKeepTogether(true);
style.setAngleBrackets(true);
style.setOrder(1);
store.setDefault(PREF_INCLUDE_STYLE_SYSTEM_WITH_EXTENSION, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITH_EXTENSION, style.toString());
style = new IncludeGroupStyle(IncludeKind.SYSTEM_WITHOUT_EXTENSION);
style.setKeepTogether(true);
style.setAngleBrackets(true);
style.setOrder(2);
store.setDefault(PREF_INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION, style.toString());
style = new IncludeGroupStyle(IncludeKind.OTHER);
style.setKeepTogether(true);
style.setBlankLineBefore(true);
style.setOrder(3);
store.setDefault(PREF_INCLUDE_STYLE_OTHER, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_OTHER, style.toString());
style = new IncludeGroupStyle(IncludeKind.IN_SAME_PROJECT);
store.setDefault(PREF_INCLUDE_STYLE_SAME_PROJECT, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_SAME_PROJECT, style.toString());
style = new IncludeGroupStyle(IncludeKind.IN_OTHER_PROJECT);
store.setDefault(PREF_INCLUDE_STYLE_OTHER_PROJECT, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_OTHER_PROJECT, style.toString());
style = new IncludeGroupStyle(IncludeKind.EXTERNAL);
store.setDefault(PREF_INCLUDE_STYLE_EXTERNAL, style.toString());
store.setDefault(PREF_INCLUDE_STYLE_MATCHING_PATTERN, ""); //$NON-NLS-1$
store.setDefault(PreferenceConstants.INCLUDE_STYLE_EXTERNAL, style.toString());
store.setDefault(PreferenceConstants.INCLUDE_STYLE_MATCHING_PATTERN, ""); //$NON-NLS-1$
store.setDefault(PREF_PARTNER_FILE_SUFFIXES, DEFAULT_PARTNER_FILE_SUFFIXES);
store.setDefault(PREF_HEURISTIC_HEADER_SUBSTITUTION, true);
store.setDefault(PREF_INCLUDES_REORDERING, true);
store.setDefault(PREF_FORWARD_DECLARE_COMPOSITE_TYPES, true);
store.setDefault(PREF_FORWARD_DECLARE_ENUMS, false);
store.setDefault(PREF_FORWARD_DECLARE_FUNCTIONS, false);
store.setDefault(PREF_FORWARD_DECLARE_NAMESPACE_ELEMENTS, true);
store.setDefault(PREF_UNUSED_STATEMENTS_DISPOSITION, UnusedStatementDisposition.COMMENT_OUT.toString());
store.setDefault(PreferenceConstants.INCLUDES_PARTNER_FILE_SUFFIXES, DEFAULT_PARTNER_FILE_SUFFIXES);
store.setDefault(PreferenceConstants.INCLUDES_HEURISTIC_HEADER_SUBSTITUTION, true);
store.setDefault(PreferenceConstants.INCLUDES_ALLOW_REORDERING, true);
store.setDefault(PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES, true);
store.setDefault(PreferenceConstants.FORWARD_DECLARE_ENUMS, false);
store.setDefault(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, false);
store.setDefault(PreferenceConstants.FORWARD_DECLARE_TEMPLATES, false);
store.setDefault(PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS, true);
store.setDefault(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION, UnusedStatementDisposition.COMMENT_OUT.toString());
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* Copyright (c) 2012, 2013 Google, Inc 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

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* Copyright (c) 2012, 2013 Google, Inc 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
@ -34,7 +34,7 @@ import org.eclipse.cdt.internal.core.parser.scanner.ScannerUtility;
* Context for managing include statements.
*/
public class InclusionContext {
private static final IPath UNRESOLVED_INCLUDE = new Path(""); //$NON-NLS-1$
private static final IPath UNRESOLVED_INCLUDE = Path.EMPTY;
private final ITranslationUnit fTu;
private final IProject fProject;
@ -132,22 +132,19 @@ public class InclusionContext {
String headerLocation = fullPath.toOSString();
String shortestInclude = null;
boolean isSystem = false;
int count = 0; //XXX
for (IncludeSearchPathElement pathElement : fIncludeSearchPath.getElements()) {
String includeDirective = pathElement.getIncludeDirective(headerLocation);
if (includeDirective != null &&
(shortestInclude == null || shortestInclude.length() > includeDirective.length())) {
shortestInclude = includeDirective;
isSystem = !pathElement.isForQuoteIncludesOnly();
if (count < 1) //XXX
isSystem = false; //XXX Hack to introduce non-system includes
}
count++; //XXX
}
if (shortestInclude == null)
return null;
include = new IncludeInfo(shortestInclude, isSystem);
fIncludeResolutionCache.put(include, fullPath);
// Don't put an include to fullPath to fIncludeResolutionCache since it may be wrong
// if the header was included by #include_next.
fInverseIncludeResolutionCache.put(fullPath, include);
return include;
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* Copyright (c) 2012, 2013 Google, Inc 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

View file

@ -1,11 +0,0 @@
###############################################################################
# Copyright (c) 2012 Google, Inc 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:
# Sergey Prigogin (Google) - initial API and implementation
###############################################################################
IncludeOrganizer_ChooseHeader=Choose a header file to include for symbol ''{0}''

View file

@ -1953,6 +1953,197 @@ public class PreferenceConstants {
*/
public static final String FUNCTION_PASS_OUTPUT_PARAMETERS_BY_POINTER = "function_pass_output_parameters_by_pointer"; //$NON-NLS-1$
/**
* Whether composite types should be forward declared if possible.
*
* Examples:
* class X;
* struct Y;
* union Z;
*
* @since 5.6
*/
public static final String FORWARD_DECLARE_COMPOSITE_TYPES = "forwardDeclare.compositeTypes"; //$NON-NLS-1$
/**
* Whether C++11-style enums should be forward declared if possible.
*
* Example:
* enum class X;
*
* @since 5.6
*/
public static final String FORWARD_DECLARE_ENUMS = "forwardDeclare.enums"; //$NON-NLS-1$
/**
* Whether C-style functions should be forward declared if possible.
*
* Example:
* void foo();
*
* @since 5.6
*/
public static final String FORWARD_DECLARE_FUNCTIONS = "forwardDeclare.functions"; //$NON-NLS-1$
/**
* Whether C++ templates should be forward declared if possible.
*
* Examples:
* template<typename T> class foo;
* template<typename T> void bar(T p);
*
* @since 5.6
*/
public static final String FORWARD_DECLARE_TEMPLATES = "forwardDeclare.templates"; //$NON-NLS-1$
/**
* Whether elements nested within namespaces should be forward declared if possible.
*
* Examples:
* namespace N { class X; }
*
* @since 5.6
*/
public static final String FORWARD_DECLARE_NAMESPACE_ELEMENTS = "forwardDeclare.namespaceElements"; //$NON-NLS-1$
/**
* Defines a list of file name suffixes. A header file and the including file are considered
* partners if their file names without extensions are either identical or differ by one of
* these suffixes.
*
* @since 5.6
*/
public static final String INCLUDES_PARTNER_FILE_SUFFIXES = "includes.partnerFileSuffixes"; //$NON-NLS-1$
/**
* Whether a heuristic approach should be used to decide which C++ header files to include.
* The heuristic prefers headers which have no file extension and / or are named like the symbol
* which should be defined. This often works out nicely since it's a commonly used naming
* convention for C++ library headers.
*
* @since 5.6
*/
public static final String INCLUDES_HEURISTIC_HEADER_SUBSTITUTION = "organizeIncludes.heuristicHeader_substitution"; //$NON-NLS-1$
/**
* Whether it's allowed to reorder existing include directives. If this preference is set to
* false, the original order is kept as far as possible. This may be necessary to avoid breaking
* code which makes assumptions about the order of the include directives. If this is set to
* true, a different sort order can be applied. Groups of includes are ordered according to
* the values returned by
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle#getOrder()} method.
* Includes within each group are ordered alphabetically.
*
* @since 5.6
*/
public static final String INCLUDES_ALLOW_REORDERING = "organizeIncludes.allowReordering"; //$NON-NLS-1$
/**
* Determines what should be done with any unused include directives and forward declarations.
* This preference may have one of the three values defined by
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences.UnusedStatementDisposition}
* enumeration ("REMOVE", "COMMENT_OUT", "KEEP").
*
* @since 5.6
*/
public static final String INCLUDES_UNUSED_STATEMENTS_DISPOSITION = "organizeIncludes.unusedStatements"; //$NON-NLS-1$
/**
* Include style for headers closely related to the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_RELATED = "includeStyle.related"; //$NON-NLS-1$
/**
* Include style for the header with the same name as the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_PARTNER = "includeStyle.partner"; //$NON-NLS-1$
/**
* Include style for headers in the same folder as the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SAME_FOLDER = "includeStyle.sameFolder"; //$NON-NLS-1$
/**
* Include style for headers in subfolders of the folder containing the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SUBFOLDER = "includeStyle.subfolder"; //$NON-NLS-1$
/**
* Include style for system headers.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SYSTEM = "includeStyle.system"; //$NON-NLS-1$
/**
* Include style for C-style system headers with a file name extension.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SYSTEM_WITH_EXTENSION = "includeStyle.systemWithExtension"; //$NON-NLS-1$
/**
* Include style for C++-style system headers without a file name extension.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION = "includeStyle.systemWithoutExtension"; //$NON-NLS-1$
/**
* Include style for headers not closely related to the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_OTHER = "includeStyle.other"; //$NON-NLS-1$
/**
* Include style for headers in the same project as the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_SAME_PROJECT = "includeStyle.inSameProject"; //$NON-NLS-1$
/**
* Include style for headers in a different project than the including file.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_OTHER_PROJECT = "includeStyle.inOtherProject"; //$NON-NLS-1$
/**
* Include style for headers outside Eclipse workspace.
* The value of the preference is an XML representation of
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_EXTERNAL = "includeStyle.external"; //$NON-NLS-1$
/**
* Include styles for headers matching user-defined patterns.
* The value of the preference is an XML representation of one or more
* {@link org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle}s.
*
* @since 5.6
*/
public static final String INCLUDE_STYLE_MATCHING_PATTERN = "includeStyle.matchingPattern"; //$NON-NLS-1$
/**
* Returns the CDT-UI preference store.

View file

@ -139,6 +139,13 @@ public class CdtActionConstants {
*/
public static final String ADD_INCLUDE= "org.eclipse.cdt.ui.actions.AddInclude"; //$NON-NLS-1$
/**
* Source menu: name of standard Organize Includes global action
* (value <code>"org.eclipse.cdt.ui.actions.OrganizeIncludes"</code>).
* @since 5.6
*/
public static final String ORGANIZE_INCLUDES= "org.eclipse.cdt.ui.actions.OrganizeIncludes"; //$NON-NLS-1$
/**
* Source menu: name of standard Sort Lines global action
* (value <code>"org.eclipse.cdt.ui.actions.SortLines"</code>).

View file

@ -160,7 +160,7 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange
editor.setAction("AddIncludeOnSelection", fAddInclude); //$NON-NLS-1$
fOrganizeIncludes= new OrganizeIncludesAction(editor);
// TODO: fOrganizeIncludes.setActionDefinitionId(ICEditorActionDefinitionIds.ORGANIZE_INCLUDES);
fOrganizeIncludes.setActionDefinitionId(ICEditorActionDefinitionIds.ORGANIZE_INCLUDES);
editor.setAction("OrganizeIncludes", fOrganizeIncludes); //$NON-NLS-1$
// fSortMembers= new SortMembersAction(editor);