mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-13 11:15:38 +02:00
Bug 45203. Major milestone - Organize Includes command is ready for
alpha testing.
This commit is contained in:
parent
8691f9784c
commit
7ac4d43010
38 changed files with 2665 additions and 1232 deletions
|
@ -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;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.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.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.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.envvar;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.managedbuilder.core",
|
||||||
org.eclipse.cdt.internal.core.index;x-friends:="org.eclipse.cdt.ui",
|
org.eclipse.cdt.internal.core.index;x-friends:="org.eclipse.cdt.ui",
|
||||||
|
|
|
@ -74,6 +74,21 @@ public class CharArrayUtils {
|
||||||
return true;
|
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
|
* Returns {@code true} if a prefix of the character array is the same as contents
|
||||||
* of a string.
|
* of a string.
|
||||||
|
@ -117,6 +132,10 @@ public class CharArrayUtils {
|
||||||
return str1.length - str2.length;
|
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) {
|
public static final boolean equals(char[] str1, int start1, int length1, char[] str2) {
|
||||||
if (length1 != str2.length || str1.length < length1 + start1)
|
if (length1 != str2.length || str1.length < length1 + start1)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -485,4 +485,52 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
|
||||||
}
|
}
|
||||||
return fSizeofCalculator;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -22,7 +22,6 @@ import org.eclipse.core.filesystem.URIUtil;
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.resources.IResource;
|
import org.eclipse.core.resources.IResource;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
|
||||||
import org.eclipse.core.runtime.Path;
|
import org.eclipse.core.runtime.Path;
|
||||||
import org.eclipse.jface.preference.IPreferenceStore;
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
import org.eclipse.jface.text.TextSelection;
|
import org.eclipse.jface.text.TextSelection;
|
||||||
|
@ -56,8 +55,6 @@ import org.eclipse.cdt.internal.ui.refactoring.CRefactoringContext;
|
||||||
* Common base for refactoring tests.
|
* Common base for refactoring tests.
|
||||||
*/
|
*/
|
||||||
public abstract class RefactoringTestBase extends BaseTestCase {
|
public abstract class RefactoringTestBase extends BaseTestCase {
|
||||||
protected static final NullProgressMonitor NULL_PROGRESS_MONITOR = new NullProgressMonitor();
|
|
||||||
|
|
||||||
/** Allows empty files to be created during test setup. */
|
/** Allows empty files to be created during test setup. */
|
||||||
protected boolean createEmptyFiles = true;
|
protected boolean createEmptyFiles = true;
|
||||||
/** See {@link PreferenceConstants.CLASS_MEMBER_ASCENDING_VISIBILITY_ORDER} */
|
/** See {@link PreferenceConstants.CLASS_MEMBER_ASCENDING_VISIBILITY_ORDER} */
|
||||||
|
@ -137,7 +134,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
if (cproject != null) {
|
if (cproject != null) {
|
||||||
cproject.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT,
|
cproject.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT,
|
||||||
NULL_PROGRESS_MONITOR);
|
npm());
|
||||||
}
|
}
|
||||||
resetPreferences();
|
resetPreferences();
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
|
@ -175,7 +172,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
|
||||||
protected void executeRefactoring(Refactoring refactoring, RefactoringContext context,
|
protected void executeRefactoring(Refactoring refactoring, RefactoringContext context,
|
||||||
boolean withUserInput, boolean expectedSuccess) throws CoreException, Exception {
|
boolean withUserInput, boolean expectedSuccess) throws CoreException, Exception {
|
||||||
try {
|
try {
|
||||||
RefactoringStatus initialStatus = refactoring.checkInitialConditions(NULL_PROGRESS_MONITOR);
|
RefactoringStatus initialStatus = refactoring.checkInitialConditions(npm());
|
||||||
if (!expectedSuccess) {
|
if (!expectedSuccess) {
|
||||||
assertStatusFatalError(initialStatus);
|
assertStatusFatalError(initialStatus);
|
||||||
return;
|
return;
|
||||||
|
@ -190,7 +187,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
|
||||||
|
|
||||||
if (withUserInput)
|
if (withUserInput)
|
||||||
simulateUserInput();
|
simulateUserInput();
|
||||||
RefactoringStatus finalStatus = refactoring.checkFinalConditions(NULL_PROGRESS_MONITOR);
|
RefactoringStatus finalStatus = refactoring.checkFinalConditions(npm());
|
||||||
if (expectedFinalWarnings != 0) {
|
if (expectedFinalWarnings != 0) {
|
||||||
assertStatusWarning(finalStatus, expectedFinalWarnings);
|
assertStatusWarning(finalStatus, expectedFinalWarnings);
|
||||||
} else if (expectedFinalInfos != 0) {
|
} else if (expectedFinalInfos != 0) {
|
||||||
|
@ -198,8 +195,8 @@ public abstract class RefactoringTestBase extends BaseTestCase {
|
||||||
} else {
|
} else {
|
||||||
assertStatusOk(finalStatus);
|
assertStatusOk(finalStatus);
|
||||||
}
|
}
|
||||||
Change change = refactoring.createChange(NULL_PROGRESS_MONITOR);
|
Change change = refactoring.createChange(npm());
|
||||||
change.perform(NULL_PROGRESS_MONITOR);
|
change.perform(npm());
|
||||||
} finally {
|
} finally {
|
||||||
if (context != null)
|
if (context != null)
|
||||||
context.dispose();
|
context.dispose();
|
||||||
|
@ -212,7 +209,7 @@ public abstract class RefactoringTestBase extends BaseTestCase {
|
||||||
RefactoringHistory history = RefactoringHistoryService.getInstance().readRefactoringHistory(
|
RefactoringHistory history = RefactoringHistoryService.getInstance().readRefactoringHistory(
|
||||||
new ByteArrayInputStream(scriptSource.getBytes()), 0);
|
new ByteArrayInputStream(scriptSource.getBytes()), 0);
|
||||||
for (RefactoringDescriptorProxy proxy : history.getDescriptors()) {
|
for (RefactoringDescriptorProxy proxy : history.getDescriptors()) {
|
||||||
RefactoringDescriptor descriptor = proxy.requestDescriptor(NULL_PROGRESS_MONITOR);
|
RefactoringDescriptor descriptor = proxy.requestDescriptor(npm());
|
||||||
RefactoringStatus status = new RefactoringStatus();
|
RefactoringStatus status = new RefactoringStatus();
|
||||||
RefactoringContext context = descriptor.createRefactoringContext(status);
|
RefactoringContext context = descriptor.createRefactoringContext(status);
|
||||||
assertTrue(status.isOK());
|
assertTrue(status.isOK());
|
||||||
|
|
|
@ -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.gettersandsetters.GenerateGettersAndSettersTest;
|
||||||
import org.eclipse.cdt.ui.tests.refactoring.hidemethod.HideMethodRefactoringTest;
|
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.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.rename.RenameRegressionTests;
|
||||||
import org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest;
|
import org.eclipse.cdt.ui.tests.refactoring.togglefunction.ToggleRefactoringTest;
|
||||||
import org.eclipse.cdt.ui.tests.refactoring.utils.UtilTestSuite;
|
import org.eclipse.cdt.ui.tests.refactoring.utils.UtilTestSuite;
|
||||||
|
@ -42,6 +43,7 @@ public class RefactoringTestSuite extends TestSuite {
|
||||||
suite.addTest(ImplementMethodRefactoringTest.suite());
|
suite.addTest(ImplementMethodRefactoringTest.suite());
|
||||||
suite.addTest(ExtractLocalVariableRefactoringTest.suite());
|
suite.addTest(ExtractLocalVariableRefactoringTest.suite());
|
||||||
suite.addTest(ToggleRefactoringTest.suite());
|
suite.addTest(ToggleRefactoringTest.suite());
|
||||||
|
suite.addTest(IncludesTestSuite.suite());
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,7 +181,6 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase {
|
||||||
assertRefactoringSuccess();
|
assertRefactoringSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//A.h
|
//A.h
|
||||||
//#ifndef A_H_
|
//#ifndef A_H_
|
||||||
//#define A_H_
|
//#define A_H_
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -10,12 +10,16 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.ui.tests.refactoring.includes;
|
package org.eclipse.cdt.ui.tests.refactoring.includes;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import com.ibm.icu.text.MessageFormat;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
@ -51,7 +55,8 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
|
||||||
fIndex.acquireReadLock();
|
fIndex.acquireReadLock();
|
||||||
ITranslationUnit tu = ast.getOriginatingTranslationUnit();
|
ITranslationUnit tu = ast.getOriginatingTranslationUnit();
|
||||||
fContext = new InclusionContext(tu, fIndex);
|
fContext = new InclusionContext(tu, fIndex);
|
||||||
fBindingClassifier = new BindingClassifier(fContext, ast);
|
fBindingClassifier = new BindingClassifier(fContext);
|
||||||
|
fBindingClassifier.classifyNodeContents(ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -69,15 +74,36 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertExpectedBindings(String[] expectedNames, Set<IBinding> bindings, String verb) {
|
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) {
|
for (IBinding binding : bindings) {
|
||||||
String name = binding.getName();
|
extra.add(binding.getName());
|
||||||
if (!remaining.remove(name)) {
|
|
||||||
fail("Binding \"" + name + "\" should not be " + 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 (!remaining.isEmpty())
|
if (!extra.isEmpty()) {
|
||||||
fail("Binding \"" + remaining.iterator().next() + "\" is not " + verb);
|
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;
|
// class A;
|
||||||
|
@ -109,4 +135,46 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
|
||||||
public void testClassMember() throws Exception {
|
public void testClassMember() throws Exception {
|
||||||
assertDefined("f", "A");
|
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.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -8,18 +8,17 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Sergey Prigogin (Google) - initial API and implementation
|
* 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 class IncludesTestSuite extends TestSuite {
|
||||||
public static String IncludeOrganizer_ChooseHeader;
|
|
||||||
|
|
||||||
static {
|
public static Test suite() throws Exception {
|
||||||
NLS.initializeMessages(Messages.class.getName(), Messages.class);
|
IncludesTestSuite suite = new IncludesTestSuite();
|
||||||
}
|
suite.addTest(BindingClassifierTest.suite());
|
||||||
|
suite.addTest(OrganizeIncludesTest.suite());
|
||||||
// Do not instantiate
|
return suite;
|
||||||
private Messages() {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -276,6 +276,10 @@ ActionDefinition.openType.description= Open an element in an Editor
|
||||||
ActionDefinition.addInclude.name= Add Include
|
ActionDefinition.addInclude.name= Add Include
|
||||||
ActionDefinition.addInclude.description= Create include statement on selection
|
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
|
#Sort Lines
|
||||||
ActionDefinition.sortLines.name= Sort Lines
|
ActionDefinition.sortLines.name= Sort Lines
|
||||||
ActionDefinition.sortLines.description= Sort selected lines alphabetically
|
ActionDefinition.sortLines.description= Sort selected lines alphabetically
|
||||||
|
@ -593,6 +597,7 @@ renameParticipant.name = Source Folder Rename
|
||||||
|
|
||||||
FormatAction.label= &Format
|
FormatAction.label= &Format
|
||||||
IndentAction.label= Correct &Indentation
|
IndentAction.label= Correct &Indentation
|
||||||
|
OrganizeIncludesAction.label= Or&ganize Includes
|
||||||
AddIncludeAction.label= A&dd Include
|
AddIncludeAction.label= A&dd Include
|
||||||
SortLinesAction.label= Sor&t Lines
|
SortLinesAction.label= Sor&t Lines
|
||||||
CommentAction.label= Co&mment
|
CommentAction.label= Co&mment
|
||||||
|
|
|
@ -1884,6 +1884,13 @@
|
||||||
menubarPath="org.eclipse.jdt.ui.source.menu/importGroup"
|
menubarPath="org.eclipse.jdt.ui.source.menu/importGroup"
|
||||||
id="org.eclipse.cdt.ui.actions.SortLines">
|
id="org.eclipse.cdt.ui.actions.SortLines">
|
||||||
</action>
|
</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
|
<action
|
||||||
definitionId="org.eclipse.cdt.ui.edit.text.c.add.include"
|
definitionId="org.eclipse.cdt.ui.edit.text.c.add.include"
|
||||||
label="%AddIncludeAction.label"
|
label="%AddIncludeAction.label"
|
||||||
|
@ -2451,6 +2458,11 @@
|
||||||
contextId="org.eclipse.cdt.ui.cViewScope"
|
contextId="org.eclipse.cdt.ui.cViewScope"
|
||||||
commandId="org.eclipse.cdt.ui.navigate.open.type.in.hierarchy"
|
commandId="org.eclipse.cdt.ui.navigate.open.type.in.hierarchy"
|
||||||
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
|
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
|
<key
|
||||||
sequence="M1+M2+N"
|
sequence="M1+M2+N"
|
||||||
contextId="org.eclipse.cdt.ui.cEditorScope"
|
contextId="org.eclipse.cdt.ui.cEditorScope"
|
||||||
|
@ -2952,6 +2964,12 @@
|
||||||
categoryId="org.eclipse.cdt.ui.category.source"
|
categoryId="org.eclipse.cdt.ui.category.source"
|
||||||
id="org.eclipse.cdt.ui.edit.text.c.add.include">
|
id="org.eclipse.cdt.ui.edit.text.c.add.include">
|
||||||
</command>
|
</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
|
<command
|
||||||
name="%ActionDefinition.sortLines.name"
|
name="%ActionDefinition.sortLines.name"
|
||||||
description="%ActionDefinition.sortLines.description"
|
description="%ActionDefinition.sortLines.description"
|
||||||
|
@ -4606,6 +4624,7 @@
|
||||||
<key name="removeTrailingWhitespaceEditedLines"/>
|
<key name="removeTrailingWhitespaceEditedLines"/>
|
||||||
<key name="Refactoring.savealleditors"/>
|
<key name="Refactoring.savealleditors"/>
|
||||||
<key name="Refactor.lightweight"/>
|
<key name="Refactor.lightweight"/>
|
||||||
|
<key name="organizeIncludes." match="prefix"/>
|
||||||
<key name="spelling_" match="prefix"/>
|
<key name="spelling_" match="prefix"/>
|
||||||
<key name="org.eclipse.cdt.ui.add_comments"/>
|
<key name="org.eclipse.cdt.ui.add_comments"/>
|
||||||
<key name="codetemplates.includeGuardGenerationScheme"/>
|
<key name="codetemplates.includeGuardGenerationScheme"/>
|
||||||
|
@ -4628,6 +4647,9 @@
|
||||||
<entry node="org.eclipse.cdt.ui">
|
<entry node="org.eclipse.cdt.ui">
|
||||||
<key name="codetemplates." match="prefix"/>
|
<key name="codetemplates." match="prefix"/>
|
||||||
<key name="nameStyle." 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="formatter_profile"/>
|
||||||
<key name="class_member_ascending_visibility_order"/>
|
<key name="class_member_ascending_visibility_order"/>
|
||||||
<key name="function_output_parameters_before_input"/>
|
<key name="function_output_parameters_before_input"/>
|
||||||
|
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -9,6 +9,7 @@
|
||||||
* IBM Corporation - initial API and implementation
|
* IBM Corporation - initial API and implementation
|
||||||
* QNX Software System
|
* QNX Software System
|
||||||
* Anton Leherbauer (Wind River Systems)
|
* Anton Leherbauer (Wind River Systems)
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui;
|
package org.eclipse.cdt.internal.ui;
|
||||||
|
|
||||||
|
@ -19,7 +20,6 @@ import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
* <p>
|
* <p>
|
||||||
* This interface contains constants only; it is not intended to be implemented or extended.
|
* This interface contains constants only; it is not intended to be implemented or extended.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface ICHelpContextIds {
|
public interface ICHelpContextIds {
|
||||||
public static final String PREFIX = CUIPlugin.PLUGIN_ID + "."; //$NON-NLS-1$
|
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 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 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$
|
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 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_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_FIELDS_ACTION= PREFIX + "filter_fields_action"; //$NON-NLS-1$
|
||||||
public static final String FILTER_STATIC_ACTION= PREFIX + "filter_static_action"; //$NON-NLS-1$
|
public static final String FILTER_STATIC_ACTION= PREFIX + "filter_static_action"; //$NON-NLS-1$
|
||||||
|
|
|
@ -33,14 +33,14 @@ import org.eclipse.ui.texteditor.RetargetTextEditorAction;
|
||||||
import org.eclipse.cdt.ui.actions.CdtActionConstants;
|
import org.eclipse.cdt.ui.actions.CdtActionConstants;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.IContextMenuConstants;
|
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.StructureSelectHistoryAction;
|
||||||
import org.eclipse.cdt.internal.ui.actions.StructureSelectNextAction;
|
import org.eclipse.cdt.internal.ui.actions.StructureSelectNextAction;
|
||||||
import org.eclipse.cdt.internal.ui.actions.StructureSelectPreviousAction;
|
import org.eclipse.cdt.internal.ui.actions.StructureSelectPreviousAction;
|
||||||
import org.eclipse.cdt.internal.ui.actions.StructureSelectionAction;
|
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 {
|
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.REMOVE_BLOCK_COMMENT, getAction(textEditor, "RemoveBlockComment")); //$NON-NLS-1$
|
||||||
bars.setGlobalActionHandler(CdtActionConstants.INDENT, getAction(textEditor, "Indent")); //$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.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$
|
bars.setGlobalActionHandler(CdtActionConstants.SORT_LINES, getAction(textEditor, "SortLines")); //$NON-NLS-1$
|
||||||
|
|
||||||
IAction action= getAction(textEditor, ITextEditorActionConstants.REFRESH);
|
IAction action= getAction(textEditor, ITextEditorActionConstants.REFRESH);
|
||||||
|
|
|
@ -38,10 +38,12 @@ public final class CEditorMessages extends NLS {
|
||||||
public static String AddIncludesOperation_description;
|
public static String AddIncludesOperation_description;
|
||||||
public static String OrganizeIncludes_label;
|
public static String OrganizeIncludes_label;
|
||||||
public static String OrganizeIncludes_description;
|
public static String OrganizeIncludes_description;
|
||||||
|
public static String OrganizeIncludes_action;
|
||||||
public static String OrganizeIncludes_error_title;
|
public static String OrganizeIncludes_error_title;
|
||||||
public static String OrganizeIncludes_insertion_failed;
|
public static String OrganizeIncludes_insertion_failed;
|
||||||
public static String OrganizeIncludes_help_provider_error;
|
public static String OrganizeIncludes_help_provider_error;
|
||||||
public static String OrganizeIncludes_failed;
|
public static String OrganizeIncludes_failed;
|
||||||
|
public static String OrganizeIncludes_choose_header;
|
||||||
public static String OrganizeIncludesOperation_description;
|
public static String OrganizeIncludesOperation_description;
|
||||||
public static String ShowInCView_description;
|
public static String ShowInCView_description;
|
||||||
public static String ShowInCView_label;
|
public static String ShowInCView_label;
|
||||||
|
|
|
@ -24,10 +24,12 @@ AddIncludesOperation_description=Adding include statement
|
||||||
|
|
||||||
OrganizeIncludes_label=Organize Includes
|
OrganizeIncludes_label=Organize Includes
|
||||||
OrganizeIncludes_description=Organize includes for current file
|
OrganizeIncludes_description=Organize includes for current file
|
||||||
|
OrganizeIncludes_action=Organizing includes
|
||||||
OrganizeIncludes_error_title=Error Organizing Includes
|
OrganizeIncludes_error_title=Error Organizing Includes
|
||||||
OrganizeIncludes_insertion_failed=Adding include statements failed
|
OrganizeIncludes_insertion_failed=Adding include statements failed
|
||||||
OrganizeIncludes_help_provider_error=Help provider error
|
OrganizeIncludes_help_provider_error=Help provider error
|
||||||
OrganizeIncludes_failed=Organize Includes operation failed
|
OrganizeIncludes_failed=Organize Includes operation failed
|
||||||
|
OrganizeIncludes_choose_header=Choose a header file to include for symbol ''{0}''
|
||||||
OrganizeIncludesOperation_description=Organizing include statements
|
OrganizeIncludesOperation_description=Organizing include statements
|
||||||
|
|
||||||
ShowInCView_description=Show the current resource in the C/C++ Projects view
|
ShowInCView_description=Show the current resource in the C/C++ Projects view
|
||||||
|
|
|
@ -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$
|
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
|
* Action definition ID of the open declaration action
|
||||||
* (value <code>"org.eclipse.cdt.ui.edit.opendecl"</code>).
|
* (value <code>"org.eclipse.cdt.ui.edit.opendecl"</code>).
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,12 +7,25 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Mathias Kunter - initial API and implementation
|
* Mathias Kunter - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.editor;
|
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.CoreException;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
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.ITextEditor;
|
||||||
import org.eclipse.ui.texteditor.TextEditorAction;
|
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.CUIPlugin;
|
||||||
import org.eclipse.cdt.ui.text.SharedASTJob;
|
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.ICHelpContextIds;
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.includes.IHeaderChooser;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeOrganizer;
|
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.
|
* @param editor The editor on which this organize includes action should operate.
|
||||||
*/
|
*/
|
||||||
public OrganizeIncludesAction(ITextEditor editor) {
|
public OrganizeIncludesAction(ITextEditor editor) {
|
||||||
// TODO Fix ID's
|
|
||||||
super(CEditorMessages.getBundleForConstructedKeys(), "OrganizeIncludes.", editor); //$NON-NLS-1$
|
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());
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,27 +19,28 @@ import java.util.Map;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
|
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.IStatusChangeListener;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle;
|
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.IncludeGroupStyle.IncludeKind;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludePreferences;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The preference block for configuring style of include statements.
|
* The preference block for configuring style of include statements.
|
||||||
*/
|
*/
|
||||||
public class IncludeStyleBlock extends TabConfigurationBlock {
|
public class IncludeStyleBlock extends TabConfigurationBlock {
|
||||||
static final Key KEY_STYLE_RELATED = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_RELATED);
|
static final Key KEY_STYLE_RELATED = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_RELATED);
|
||||||
static final Key KEY_STYLE_PARTNER = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_PARTNER);
|
static final Key KEY_STYLE_PARTNER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_PARTNER);
|
||||||
static final Key KEY_STYLE_SAME_FOLDER = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_SAME_FOLDER);
|
static final Key KEY_STYLE_SAME_FOLDER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SAME_FOLDER);
|
||||||
static final Key KEY_STYLE_SUBFOLDER = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_SUBFOLDER);
|
static final Key KEY_STYLE_SUBFOLDER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SUBFOLDER);
|
||||||
static final Key KEY_STYLE_SYSTEM = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_SYSTEM);
|
static final Key KEY_STYLE_SYSTEM = getCDTUIKey(PreferenceConstants.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_WITH_EXTENSION = getCDTUIKey(PreferenceConstants.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_SYSTEM_WITHOUT_EXTENSION = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION);
|
||||||
static final Key KEY_STYLE_OTHER = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_OTHER);
|
static final Key KEY_STYLE_OTHER = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_OTHER);
|
||||||
static final Key KEY_STYLE_SAME_PROJECT = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_SAME_PROJECT);
|
static final Key KEY_STYLE_SAME_PROJECT = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_SAME_PROJECT);
|
||||||
static final Key KEY_STYLE_OTHER_PROJECT = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_OTHER_PROJECT);
|
static final Key KEY_STYLE_OTHER_PROJECT = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_OTHER_PROJECT);
|
||||||
static final Key KEY_STYLE_EXTERNAL = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_EXTERNAL);
|
static final Key KEY_STYLE_EXTERNAL = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_EXTERNAL);
|
||||||
static final Key KEY_STYLE_MATCHING_PATTERN = getCDTUIKey(IncludePreferences.PREF_INCLUDE_STYLE_MATCHING_PATTERN);
|
static final Key KEY_STYLE_MATCHING_PATTERN = getCDTUIKey(PreferenceConstants.INCLUDE_STYLE_MATCHING_PATTERN);
|
||||||
|
|
||||||
static final Map<IncludeKind, Key> KEY_MAP = createKeyMap();
|
static final Map<IncludeKind, Key> KEY_MAP = createKeyMap();
|
||||||
static final Key[] STYLE_KEYS = KEY_MAP.values().toArray(new Key[KEY_MAP.size()]);
|
static final Key[] STYLE_KEYS = KEY_MAP.values().toArray(new Key[KEY_MAP.size()]);
|
||||||
|
|
|
@ -17,9 +17,10 @@ import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Control;
|
import org.eclipse.swt.widgets.Control;
|
||||||
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
|
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.IStatusChangeListener;
|
||||||
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
|
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.refactoring.includes.IncludePreferences.UnusedStatementDisposition;
|
||||||
import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil;
|
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.
|
* The preference block for configuring Organize Includes command.
|
||||||
*/
|
*/
|
||||||
public class OrganizeIncludesBlock extends OptionsConfigurationBlock {
|
public class OrganizeIncludesBlock extends OptionsConfigurationBlock {
|
||||||
private static final Key KEY_HEURISTIC_HEADER_SUBSTITUTION = getCDTUIKey(IncludePreferences.PREF_HEURISTIC_HEADER_SUBSTITUTION);
|
private static final Key KEY_HEURISTIC_HEADER_SUBSTITUTION = getCDTUIKey(PreferenceConstants.INCLUDES_HEURISTIC_HEADER_SUBSTITUTION);
|
||||||
private static final Key KEY_INCLUDES_REORDERING = getCDTUIKey(IncludePreferences.PREF_INCLUDES_REORDERING);
|
private static final Key KEY_INCLUDES_REORDERING = getCDTUIKey(PreferenceConstants.INCLUDES_ALLOW_REORDERING);
|
||||||
private static final Key KEY_UNUSED_STATEMENTS_DISPOSITION = getCDTUIKey(IncludePreferences.PREF_UNUSED_STATEMENTS_DISPOSITION);
|
private static final Key KEY_UNUSED_STATEMENTS_DISPOSITION = getCDTUIKey(PreferenceConstants.INCLUDES_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_COMPOSITE_TYPES = getCDTUIKey(PreferenceConstants.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_ENUMS = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_ENUMS);
|
||||||
private static final Key KEY_FORWARD_DECLARE_FUNCTIONS = getCDTUIKey(IncludePreferences.PREF_FORWARD_DECLARE_FUNCTIONS);
|
private static final Key KEY_FORWARD_DECLARE_FUNCTIONS = getCDTUIKey(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS);
|
||||||
private static final Key KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS = getCDTUIKey(IncludePreferences.PREF_FORWARD_DECLARE_NAMESPACE_ELEMENTS);
|
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 = {
|
private static final String[] DISPOSITION_VALUES = {
|
||||||
UnusedStatementDisposition.REMOVE.toString(),
|
UnusedStatementDisposition.REMOVE.toString(),
|
||||||
|
@ -53,6 +55,7 @@ public class OrganizeIncludesBlock extends OptionsConfigurationBlock {
|
||||||
KEY_FORWARD_DECLARE_COMPOSITE_TYPES,
|
KEY_FORWARD_DECLARE_COMPOSITE_TYPES,
|
||||||
KEY_FORWARD_DECLARE_ENUMS,
|
KEY_FORWARD_DECLARE_ENUMS,
|
||||||
KEY_FORWARD_DECLARE_FUNCTIONS,
|
KEY_FORWARD_DECLARE_FUNCTIONS,
|
||||||
|
KEY_FORWARD_DECLARE_TEMPLATES,
|
||||||
KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS,
|
KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,6 +90,9 @@ public class OrganizeIncludesBlock extends OptionsConfigurationBlock {
|
||||||
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_forward_declare_functions,
|
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_forward_declare_functions,
|
||||||
KEY_FORWARD_DECLARE_FUNCTIONS, TRUE_FALSE, 0);
|
KEY_FORWARD_DECLARE_FUNCTIONS, TRUE_FALSE, 0);
|
||||||
LayoutUtil.setHorizontalSpan(control, 2);
|
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,
|
control = addCheckBox(composite, PreferencesMessages.OrganizeIncludesBlock_forward_declare_namespace_elements,
|
||||||
KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS, TRUE_FALSE, 0);
|
KEY_FORWARD_DECLARE_NAMESPACE_ELEMENTS, TRUE_FALSE, 0);
|
||||||
LayoutUtil.setHorizontalSpan(control, 2);
|
LayoutUtil.setHorizontalSpan(control, 2);
|
||||||
|
|
|
@ -443,6 +443,7 @@ public final class PreferencesMessages extends NLS {
|
||||||
public static String OrganizeIncludesBlock_forward_declare_composite_types;
|
public static String OrganizeIncludesBlock_forward_declare_composite_types;
|
||||||
public static String OrganizeIncludesBlock_forward_declare_enums;
|
public static String OrganizeIncludesBlock_forward_declare_enums;
|
||||||
public static String OrganizeIncludesBlock_forward_declare_functions;
|
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_forward_declare_namespace_elements;
|
||||||
public static String OrganizeIncludesBlock_heuristic_header_substitution;
|
public static String OrganizeIncludesBlock_heuristic_header_substitution;
|
||||||
public static String OrganizeIncludesBlock_unused_statements;
|
public static String OrganizeIncludesBlock_unused_statements;
|
||||||
|
|
|
@ -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_composite_types= Forward declare &classes, structs and unions
|
||||||
OrganizeIncludesBlock_forward_declare_enums= Forward declare &enums when possible
|
OrganizeIncludesBlock_forward_declare_enums= Forward declare &enums when possible
|
||||||
OrganizeIncludesBlock_forward_declare_functions= Forward declare &functions
|
OrganizeIncludesBlock_forward_declare_functions= Forward declare &functions
|
||||||
|
OrganizeIncludesBlock_forward_declare_templates= Forward declare &templates
|
||||||
OrganizeIncludesBlock_forward_declare_namespace_elements= Forward declare &namespace elements
|
OrganizeIncludesBlock_forward_declare_namespace_elements= Forward declare &namespace elements
|
||||||
OrganizeIncludesBlock_heuristic_header_substitution= Allow &heuristic header file substitution
|
OrganizeIncludesBlock_heuristic_header_substitution= Allow &heuristic header file substitution
|
||||||
OrganizeIncludesBlock_unused_statements= &Unused Includes and Forward Declarations:
|
OrganizeIncludesBlock_unused_statements= &Unused Includes and Forward Declarations:
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -11,8 +11,13 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.refactoring.includes;
|
package org.eclipse.cdt.internal.ui.refactoring.includes;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getEndingLineNumber;
|
||||||
|
import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getNodeEndOffset;
|
||||||
|
import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getNodeOffset;
|
||||||
|
import static org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit.getStartingLineNumber;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -24,23 +29,29 @@ import java.util.Set;
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IAdaptable;
|
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.core.runtime.OperationCanceledException;
|
import org.eclipse.core.runtime.OperationCanceledException;
|
||||||
import org.eclipse.jface.text.BadLocationException;
|
import org.eclipse.core.runtime.Path;
|
||||||
import org.eclipse.jface.text.IDocument;
|
import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.jface.viewers.LabelProvider;
|
import org.eclipse.jface.text.Region;
|
||||||
import org.eclipse.jface.window.Window;
|
import org.eclipse.text.edits.DeleteEdit;
|
||||||
import org.eclipse.osgi.util.NLS;
|
import org.eclipse.text.edits.InsertEdit;
|
||||||
import org.eclipse.swt.widgets.Display;
|
import org.eclipse.text.edits.ReplaceEdit;
|
||||||
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
|
import org.eclipse.text.edits.TextEdit;
|
||||||
import org.eclipse.ui.texteditor.ITextEditor;
|
|
||||||
|
|
||||||
import com.ibm.icu.text.Collator;
|
import com.ibm.icu.text.Collator;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.IName;
|
import org.eclipse.cdt.core.dom.IName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.EScopeKind;
|
import org.eclipse.cdt.core.dom.ast.EScopeKind;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTComment;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorPragmaStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||||
|
@ -62,25 +73,105 @@ import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||||
import org.eclipse.cdt.core.index.IIndexInclude;
|
import org.eclipse.cdt.core.index.IIndexInclude;
|
||||||
import org.eclipse.cdt.core.index.IIndexName;
|
import org.eclipse.cdt.core.index.IIndexName;
|
||||||
import org.eclipse.cdt.core.index.IndexLocationFactory;
|
import org.eclipse.cdt.core.index.IndexLocationFactory;
|
||||||
import org.eclipse.cdt.core.model.IBuffer;
|
|
||||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.parser.Keywords;
|
||||||
|
import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
|
||||||
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.ui.CUIPlugin;
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
import org.eclipse.cdt.utils.PathUtil;
|
import org.eclipse.cdt.utils.PathUtil;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.ASTCommenter;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.CharArray;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.IncludeGuardDetection;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||||
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
|
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.editor.CEditorMessages;
|
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle.IncludeKind;
|
import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle.IncludeKind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Organizes the include directives and forward declarations of a source or header file.
|
* Organizes the include directives and forward declarations of a source or header file.
|
||||||
*/
|
*/
|
||||||
public class IncludeOrganizer {
|
public class IncludeOrganizer {
|
||||||
|
|
||||||
|
private static class IncludePrototype {
|
||||||
|
final IPath header; // null for existing unresolved includes
|
||||||
|
final IncludeInfo includeInfo; // never null
|
||||||
|
IASTPreprocessorIncludeStatement existingInclude; // null for newly added includes
|
||||||
|
final boolean required; // true if the header has to be included
|
||||||
|
final IncludeGroupStyle style;
|
||||||
|
|
||||||
|
/** Initializes an include prototype for a new include */
|
||||||
|
IncludePrototype(IPath header, IncludeInfo includeInfo, IncludeGroupStyle style) {
|
||||||
|
this.header = header;
|
||||||
|
this.includeInfo = includeInfo;
|
||||||
|
this.style = style;
|
||||||
|
this.required = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes an include prototype for an existing include. {@code header} may be
|
||||||
|
* {@code null} if the include was not resolved.
|
||||||
|
*/
|
||||||
|
IncludePrototype(IASTPreprocessorIncludeStatement include, IPath header,
|
||||||
|
IncludeInfo includeInfo, IncludeGroupStyle style) {
|
||||||
|
this.existingInclude = include;
|
||||||
|
this.header = header;
|
||||||
|
this.includeInfo = includeInfo;
|
||||||
|
this.style = style;
|
||||||
|
this.required = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateFrom(IncludePrototype other) {
|
||||||
|
this.existingInclude = other.existingInclude;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
if (header != null)
|
||||||
|
return header.hashCode(); // includeInfo is ignored if header is not null
|
||||||
|
return includeInfo.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
IncludePrototype other = (IncludePrototype) obj;
|
||||||
|
if (header != null)
|
||||||
|
return header.equals(other.header); // includeInfo is ignored if header is not null
|
||||||
|
if (other.header != null)
|
||||||
|
return false;
|
||||||
|
if (includeInfo == null) {
|
||||||
|
if (other.includeInfo != null)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return includeInfo.equals(other.includeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** For debugging only */
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return header != null ? header.toPortableString() : includeInfo.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final Collator COLLATOR = Collator.getInstance();
|
private static final Collator COLLATOR = Collator.getInstance();
|
||||||
|
|
||||||
private static final Comparator<IPath> PATH_COMPARATOR = new Comparator<IPath>() {
|
private static final Comparator<IncludePrototype> INCLUDE_COMPARATOR = new Comparator<IncludePrototype>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(IPath path1, IPath path2) {
|
public int compare(IncludePrototype include1, IncludePrototype include2) {
|
||||||
|
IncludeInfo includeInfo1 = include1.includeInfo;
|
||||||
|
IncludeInfo includeInfo2 = include2.includeInfo;
|
||||||
|
if (includeInfo1.isSystem() != includeInfo2.isSystem()) {
|
||||||
|
return includeInfo1.isSystem() ? -1 : 1;
|
||||||
|
}
|
||||||
|
IPath path1 = Path.fromOSString(includeInfo1.getName());
|
||||||
|
IPath path2 = Path.fromOSString(includeInfo2.getName());
|
||||||
int length1 = path1.segmentCount();
|
int length1 = path1.segmentCount();
|
||||||
int length2 = path2.segmentCount();
|
int length2 = path2.segmentCount();
|
||||||
for (int i = 0; i < length1 && i < length2; i++) {
|
for (int i = 0; i < length1 && i < length2; i++) {
|
||||||
|
@ -92,16 +183,14 @@ public class IncludeOrganizer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final ITextEditor fEditor;
|
private final IHeaderChooser fHeaderChooser;
|
||||||
private final InclusionContext fContext;
|
private final InclusionContext fContext;
|
||||||
|
private final String fLineDelimiter;
|
||||||
|
|
||||||
/**
|
public IncludeOrganizer(ITranslationUnit tu, IIndex index, String lineDelimiter,
|
||||||
* Constructor
|
IHeaderChooser headerChooser) {
|
||||||
* @param editor The editor on which this organize includes action should operate.
|
fLineDelimiter = lineDelimiter;
|
||||||
* @param index
|
fHeaderChooser = headerChooser;
|
||||||
*/
|
|
||||||
public IncludeOrganizer(ITextEditor editor, ITranslationUnit tu, IIndex index) {
|
|
||||||
fEditor = editor;
|
|
||||||
fContext = new InclusionContext(tu, index);
|
fContext = new InclusionContext(tu, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,10 +199,19 @@ public class IncludeOrganizer {
|
||||||
* @param ast The AST translation unit to process.
|
* @param ast The AST translation unit to process.
|
||||||
* @throws CoreException
|
* @throws CoreException
|
||||||
*/
|
*/
|
||||||
public void organizeIncludes(IASTTranslationUnit ast) throws CoreException {
|
public List<TextEdit> organizeIncludes(IASTTranslationUnit ast) throws CoreException {
|
||||||
// Process the given translation unit with the inclusion resolver.
|
// Process the given translation unit with the inclusion resolver.
|
||||||
BindingClassifier resolver = new BindingClassifier(fContext, ast);
|
BindingClassifier bindingClassifier = new BindingClassifier(fContext);
|
||||||
Set<IBinding> bindingsToDefine = resolver.getBindingsToDefine();
|
bindingClassifier.classifyNodeContents(ast);
|
||||||
|
Set<IBinding> bindingsToDefine = bindingClassifier.getBindingsToDefine();
|
||||||
|
|
||||||
|
// Stores the forward declarations for composite types and enumerations as text.
|
||||||
|
List<String> typeForwardDeclarations = new ArrayList<String>();
|
||||||
|
// Stores the forward declarations for C-style functions as text.
|
||||||
|
List<String> functionForwardDeclarations = new ArrayList<String>();
|
||||||
|
|
||||||
|
createForwardDeclarations(ast, bindingClassifier, typeForwardDeclarations, functionForwardDeclarations,
|
||||||
|
bindingsToDefine);
|
||||||
|
|
||||||
HeaderSubstitutor headerSubstitutor = new HeaderSubstitutor(fContext);
|
HeaderSubstitutor headerSubstitutor = new HeaderSubstitutor(fContext);
|
||||||
// Create the list of header files which have to be included by examining the list of
|
// Create the list of header files which have to be included by examining the list of
|
||||||
|
@ -123,16 +221,166 @@ public class IncludeOrganizer {
|
||||||
List<InclusionRequest> requests = createInclusionRequests(bindingsToDefine, reachableHeaders);
|
List<InclusionRequest> requests = createInclusionRequests(bindingsToDefine, reachableHeaders);
|
||||||
processInclusionRequests(requests, headerSubstitutor);
|
processInclusionRequests(requests, headerSubstitutor);
|
||||||
|
|
||||||
// Stores the forward declarations for composite types and enumerations as text.
|
// Use a map instead of a set to be able to retrieve existing elements using equal elements.
|
||||||
List<String> forwardDeclarations = new ArrayList<String>();
|
// Maps each element to itself.
|
||||||
|
Map<IncludePrototype, IncludePrototype> includePrototypes =
|
||||||
|
new HashMap<IncludePrototype, IncludePrototype>();
|
||||||
|
// Put the new includes into includePrototypes.
|
||||||
|
for (IPath header : fContext.getHeadersToInclude()) {
|
||||||
|
IncludeGroupStyle style = getIncludeStyle(header);
|
||||||
|
IncludeInfo includeInfo = createIncludeInfo(header, style);
|
||||||
|
IncludePrototype prototype = new IncludePrototype(header, includeInfo, style);
|
||||||
|
updateIncludePrototypes(includePrototypes, prototype);
|
||||||
|
}
|
||||||
|
// Put the existing includes into includePrototypes.
|
||||||
|
IASTPreprocessorIncludeStatement[] existingIncludes = ast.getIncludeDirectives();
|
||||||
|
for (IASTPreprocessorIncludeStatement include : existingIncludes) {
|
||||||
|
if (include.isPartOfTranslationUnitFile()) {
|
||||||
|
String name = new String(include.getName().getSimpleID());
|
||||||
|
IncludeInfo includeInfo = new IncludeInfo(name, include.isSystemInclude());
|
||||||
|
String path = include.getPath();
|
||||||
|
IPath header = path.isEmpty() ? null : Path.fromPortableString(path);
|
||||||
|
IncludeGroupStyle style =
|
||||||
|
header != null ? getIncludeStyle(header) : getIncludeStyle(includeInfo);
|
||||||
|
IncludePrototype prototype = new IncludePrototype(include, header, includeInfo, style);
|
||||||
|
updateIncludePrototypes(includePrototypes, prototype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stores the forward declarations for C-style functions as text.
|
NodeCommentMap commentedNodeMap = ASTCommenter.getCommentedNodeMap(ast);
|
||||||
List<String> functionForwardDeclarations = new ArrayList<String>();
|
IRegion includeReplacementRegion = getSafeIncludeReplacementRegion(ast, commentedNodeMap);
|
||||||
|
|
||||||
// Create the forward declarations by examining the list of bindings which have to be
|
IncludePreferences preferences = fContext.getPreferences();
|
||||||
// declared.
|
boolean allowReordering = preferences.allowReordering || existingIncludes.length == 0;
|
||||||
|
|
||||||
|
List<TextEdit> edits = new ArrayList<TextEdit>();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<IncludePrototype>[] groupedPrototypes =
|
||||||
|
(List<IncludePrototype>[]) new List<?>[preferences.includeStyles.size()];
|
||||||
|
for (IncludePrototype prototype : includePrototypes.keySet()) {
|
||||||
|
if (prototype.existingInclude == null
|
||||||
|
|| (allowReordering && isContainedInRegion(prototype.existingInclude, includeReplacementRegion))) {
|
||||||
|
IncludeGroupStyle groupingStyle = getGroupingStyle(prototype.style);
|
||||||
|
// If reordering is not allowed, group everything together.
|
||||||
|
int position = allowReordering ? groupingStyle.getOrder() : 0;
|
||||||
|
List<IncludePrototype> prototypes = groupedPrototypes[position];
|
||||||
|
if (prototypes == null) {
|
||||||
|
prototypes = new ArrayList<IncludePrototype>();
|
||||||
|
groupedPrototypes[position] = prototypes;
|
||||||
|
}
|
||||||
|
prototypes.add(prototype);
|
||||||
|
}
|
||||||
|
if (!allowReordering && prototype.existingInclude != null
|
||||||
|
&& !prototype.required && prototype.header != null // Unused and resolved.
|
||||||
|
&& isContainedInRegion(prototype.existingInclude, includeReplacementRegion)) {
|
||||||
|
switch (preferences.unusedStatementsDisposition) {
|
||||||
|
case REMOVE:
|
||||||
|
createDelete(prototype.existingInclude, edits);
|
||||||
|
break;
|
||||||
|
case COMMENT_OUT:
|
||||||
|
createCommentOut(prototype.existingInclude, edits);
|
||||||
|
break;
|
||||||
|
case KEEP:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> includeDirectives = new ArrayList<String>();
|
||||||
|
IncludeGroupStyle previousParentStyle = null;
|
||||||
|
for (List<IncludePrototype> prototypes : groupedPrototypes) {
|
||||||
|
if (prototypes != null && !prototypes.isEmpty()) {
|
||||||
|
Collections.sort(prototypes, INCLUDE_COMPARATOR);
|
||||||
|
IncludeGroupStyle style = prototypes.get(0).style;
|
||||||
|
IncludeGroupStyle groupingStyle = getGroupingStyle(style);
|
||||||
|
IncludeGroupStyle parentStyle = getParentStyle(groupingStyle);
|
||||||
|
boolean blankLineBefore = groupingStyle.isBlankLineBefore() ||
|
||||||
|
(parentStyle != null && parentStyle != previousParentStyle &&
|
||||||
|
parentStyle.isKeepTogether() && parentStyle.isBlankLineBefore());
|
||||||
|
previousParentStyle = parentStyle;
|
||||||
|
if (!includeDirectives.isEmpty() && blankLineBefore)
|
||||||
|
includeDirectives.add(""); // Blank line separator //$NON-NLS-1$
|
||||||
|
for (IncludePrototype prototype : prototypes) {
|
||||||
|
String trailingComment = ""; //$NON-NLS-1$
|
||||||
|
IASTPreprocessorIncludeStatement include = prototype.existingInclude;
|
||||||
|
if (include == null
|
||||||
|
|| (allowReordering && isContainedInRegion(include, includeReplacementRegion))) {
|
||||||
|
if (include != null) {
|
||||||
|
List<IASTComment> comments = commentedNodeMap.getTrailingCommentsForNode(include);
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
for (IASTComment comment : comments) {
|
||||||
|
buf.append(getPrecedingWhitespace(comment));
|
||||||
|
buf.append(comment.getRawSignature());
|
||||||
|
}
|
||||||
|
trailingComment = buf.toString();
|
||||||
|
}
|
||||||
|
String directive = createIncludeDirective(prototype, trailingComment);
|
||||||
|
if (directive != null)
|
||||||
|
includeDirectives.add(directive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the source code to insert into the editor.
|
||||||
|
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
for (String include : includeDirectives) {
|
||||||
|
buf.append(include);
|
||||||
|
buf.append(fLineDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf.length() != 0 && !typeForwardDeclarations.isEmpty())
|
||||||
|
buf.append(fLineDelimiter);
|
||||||
|
for (String declaration : typeForwardDeclarations) {
|
||||||
|
buf.append(declaration);
|
||||||
|
buf.append(fLineDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf.length() != 0 && !functionForwardDeclarations.isEmpty())
|
||||||
|
buf.append(fLineDelimiter);
|
||||||
|
for (String declaration : functionForwardDeclarations) {
|
||||||
|
buf.append(declaration);
|
||||||
|
buf.append(fLineDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset = includeReplacementRegion.getOffset();
|
||||||
|
int length = includeReplacementRegion.getLength();
|
||||||
|
if (allowReordering) {
|
||||||
|
if (buf.length() != 0) {
|
||||||
|
if (offset != 0 && !isPreviousLineBlank(offset))
|
||||||
|
buf.insert(0, fLineDelimiter); // Blank line before.
|
||||||
|
if (!isBlankLineOrEndOfFile(offset + length))
|
||||||
|
buf.append(fLineDelimiter); // Blank line after.
|
||||||
|
}
|
||||||
|
|
||||||
|
String text = buf.toString();
|
||||||
|
// TODO(sprigogin): Add a diff algorithm and produce more narrow replacements.
|
||||||
|
if (!CharArrayUtils.equals(fContext.getTranslationUnit().getContents(), offset, length, text)) {
|
||||||
|
edits.add(new ReplaceEdit(offset, length, text));
|
||||||
|
}
|
||||||
|
} else if (buf.length() != 0) {
|
||||||
|
offset += length;
|
||||||
|
if (!isBlankLineOrEndOfFile(offset))
|
||||||
|
buf.append(fLineDelimiter); // Blank line after.
|
||||||
|
edits.add(new InsertEdit(offset, buf.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return edits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates forward declarations by examining the list of bindings which have to be declared.
|
||||||
|
* Bindings that cannot be safely declared for whatever reason are added to
|
||||||
|
* {@code bindingsToDefine} set.
|
||||||
|
*/
|
||||||
|
private void createForwardDeclarations(IASTTranslationUnit ast, BindingClassifier classifier,
|
||||||
|
List<String> forwardDeclarations, List<String> functionForwardDeclarations,
|
||||||
|
Set<IBinding> bindingsToDefine) throws CoreException {
|
||||||
|
IIndexFileSet reachableHeaders = ast.getIndexFileSet();
|
||||||
Set<IBinding> bindings =
|
Set<IBinding> bindings =
|
||||||
removeBindingsDefinedInIncludedHeaders(resolver.getBindingsToDeclare(), reachableHeaders);
|
removeBindingsDefinedInIncludedHeaders(classifier.getBindingsToDeclare(), reachableHeaders);
|
||||||
for (IBinding binding : bindings) {
|
for (IBinding binding : bindings) {
|
||||||
// Create the text of the forward declaration of this binding.
|
// Create the text of the forward declaration of this binding.
|
||||||
StringBuilder declarationText = new StringBuilder();
|
StringBuilder declarationText = new StringBuilder();
|
||||||
|
@ -150,6 +398,7 @@ public class IncludeOrganizer {
|
||||||
}
|
}
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.reverse(scopeNames);
|
Collections.reverse(scopeNames);
|
||||||
for (IName scopeName : scopeNames) {
|
for (IName scopeName : scopeNames) {
|
||||||
declarationText.append("namespace "); //$NON-NLS-1$
|
declarationText.append("namespace "); //$NON-NLS-1$
|
||||||
|
@ -222,8 +471,7 @@ public class IncludeOrganizer {
|
||||||
|
|
||||||
// Append return type and function name.
|
// Append return type and function name.
|
||||||
IFunctionType functionType = function.getType();
|
IFunctionType functionType = function.getType();
|
||||||
// TODO(sprigogin) Improper use of IType.toString();
|
declarationText.append(ASTTypeUtil.getType(functionType.getReturnType(), false));
|
||||||
declarationText.append(functionType.getReturnType().toString());
|
|
||||||
declarationText.append(' ');
|
declarationText.append(' ');
|
||||||
declarationText.append(function.getName());
|
declarationText.append(function.getName());
|
||||||
declarationText.append('(');
|
declarationText.append('(');
|
||||||
|
@ -232,17 +480,16 @@ public class IncludeOrganizer {
|
||||||
IType[] parameterTypes = functionType.getParameterTypes();
|
IType[] parameterTypes = functionType.getParameterTypes();
|
||||||
IParameter[] parameters = function.getParameters();
|
IParameter[] parameters = function.getParameters();
|
||||||
for (int i = 0; i < parameterTypes.length && i < parameters.length; i++) {
|
for (int i = 0; i < parameterTypes.length && i < parameters.length; i++) {
|
||||||
// TODO(sprigogin) Improper use of IType.toString();
|
if (i != 0) {
|
||||||
declarationText.append(parameterTypes[i].toString());
|
declarationText.append(", "); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
declarationText.append(ASTTypeUtil.getType(parameterTypes[i], false));
|
||||||
char lastChar = declarationText.charAt(declarationText.length() - 1);
|
char lastChar = declarationText.charAt(declarationText.length() - 1);
|
||||||
if (lastChar != '*' && lastChar != '&') {
|
if (lastChar != '*' && lastChar != '&') {
|
||||||
// Append a space to separate the type name from the parameter name.
|
// Append a space to separate the type name from the parameter name.
|
||||||
declarationText.append(' ');
|
declarationText.append(' ');
|
||||||
}
|
}
|
||||||
declarationText.append(parameters[i].getName());
|
declarationText.append(parameters[i].getName());
|
||||||
if (i != parameterTypes.length - 1 && i != parameters.length - 1) {
|
|
||||||
declarationText.append(", "); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declarationText.append(");"); //$NON-NLS-1$
|
declarationText.append(");"); //$NON-NLS-1$
|
||||||
|
@ -250,7 +497,9 @@ public class IncludeOrganizer {
|
||||||
// Add this forward declaration to the separate function forward declaration list.
|
// Add this forward declaration to the separate function forward declaration list.
|
||||||
forwardDeclarationListToUse = functionForwardDeclarations;
|
forwardDeclarationListToUse = functionForwardDeclarations;
|
||||||
} else {
|
} else {
|
||||||
// We don't handle forward declarations for those types of bindings. Ignore it.
|
// We can't create a forward declaration for this binding. The binding will have
|
||||||
|
// to be defined.
|
||||||
|
bindingsToDefine.add(binding);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,80 +512,266 @@ public class IncludeOrganizer {
|
||||||
forwardDeclarationListToUse.add(declarationText.toString());
|
forwardDeclarationListToUse.add(declarationText.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.sort(forwardDeclarations);
|
Collections.sort(forwardDeclarations, COLLATOR);
|
||||||
Collections.sort(functionForwardDeclarations);
|
Collections.sort(functionForwardDeclarations, COLLATOR);
|
||||||
|
|
||||||
IncludePreferences preferences = fContext.getPreferences();
|
|
||||||
Map<IPath, IncludeGroupStyle> classifiedHeaders =
|
|
||||||
new HashMap<IPath, IncludeGroupStyle>(fContext.getHeadersToInclude().size());
|
|
||||||
for (IPath file : fContext.getHeadersToInclude()) {
|
|
||||||
classifiedHeaders.put(file, getIncludeStyle(file));
|
|
||||||
}
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<IPath>[] orderedHeaders = (List<IPath>[]) new List<?>[classifiedHeaders.size()];
|
|
||||||
for (Map.Entry<IPath, IncludeGroupStyle> entry : classifiedHeaders.entrySet()) {
|
|
||||||
IPath path = entry.getKey();
|
|
||||||
IncludeGroupStyle style = entry.getValue();
|
|
||||||
IncludeGroupStyle groupingStyle = getGroupingStyle(style);
|
|
||||||
int position = groupingStyle.getOrder();
|
|
||||||
List<IPath> headers = orderedHeaders[position];
|
|
||||||
if (headers == null) {
|
|
||||||
headers = new ArrayList<IPath>();
|
|
||||||
orderedHeaders[position] = headers;
|
|
||||||
}
|
|
||||||
headers.add(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> includeDirectives = new ArrayList<String>();
|
private void createCommentOut(IASTPreprocessorIncludeStatement include, List<TextEdit> edits) {
|
||||||
IncludeGroupStyle previousParentStyle = null;
|
IASTFileLocation location = include.getFileLocation();
|
||||||
for (List<IPath> headers : orderedHeaders) {
|
int offset = location.getNodeOffset();
|
||||||
if (headers != null && !headers.isEmpty()) {
|
if (fContext.getTranslationUnit().isCXXLanguage()) {
|
||||||
Collections.sort(headers, PATH_COMPARATOR);
|
offset = getLineStart(offset);
|
||||||
IncludeGroupStyle style = classifiedHeaders.get(headers.get(0));
|
edits.add(new InsertEdit(offset, "//")); //$NON-NLS-1$
|
||||||
IncludeGroupStyle groupingStyle = getGroupingStyle(style);
|
} else {
|
||||||
IncludeGroupStyle parentStyle = getParentStyle(groupingStyle);
|
edits.add(new InsertEdit(offset, "/*")); //$NON-NLS-1$
|
||||||
boolean blankLineBefore = groupingStyle.isBlankLineBefore() ||
|
int endOffset = offset + location.getNodeLength();
|
||||||
(parentStyle != null && parentStyle != previousParentStyle &&
|
edits.add(new InsertEdit(endOffset, "*/")); //$NON-NLS-1$
|
||||||
parentStyle.isKeepTogether() && parentStyle.isBlankLineBefore());
|
}
|
||||||
previousParentStyle = parentStyle;
|
}
|
||||||
if (!includeDirectives.isEmpty() && blankLineBefore)
|
|
||||||
includeDirectives.add(""); // Blank line separator //$NON-NLS-1$
|
private void createDelete(IASTPreprocessorIncludeStatement include, List<TextEdit> edits) {
|
||||||
for (IPath header : headers) {
|
IASTFileLocation location = include.getFileLocation();
|
||||||
style = classifiedHeaders.get(header);
|
int offset = location.getNodeOffset();
|
||||||
includeDirectives.add(createIncludeDirective(header, style, "")); //$NON-NLS-1$
|
int endOffset = offset + location.getNodeLength();
|
||||||
|
offset = getLineStart(offset);
|
||||||
|
endOffset = skipToNextLine(endOffset);
|
||||||
|
edits.add(new DeleteEdit(offset, endOffset - offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateIncludePrototypes(Map<IncludePrototype, IncludePrototype> includePrototypes,
|
||||||
|
IncludePrototype prototype) {
|
||||||
|
IncludePrototype existing = includePrototypes.get(prototype);
|
||||||
|
if (existing == null) {
|
||||||
|
includePrototypes.put(prototype, prototype);
|
||||||
|
} else {
|
||||||
|
existing.updateFrom(prototype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isContainedInRegion(IASTNode node, IRegion region) {
|
||||||
|
return getNodeOffset(node) >= region.getOffset()
|
||||||
|
&& getNodeEndOffset(node) <= region.getOffset() + region.getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IRegion getSafeIncludeReplacementRegion(IASTTranslationUnit ast, NodeCommentMap commentMap) {
|
||||||
|
int maxSafeOffset = ast.getFileLocation().getNodeLength();
|
||||||
|
IASTDeclaration[] declarations = ast.getDeclarations(true);
|
||||||
|
if (declarations.length != 0)
|
||||||
|
maxSafeOffset = declarations[0].getFileLocation().getNodeOffset();
|
||||||
|
|
||||||
|
boolean topCommentSkipped = false;
|
||||||
|
int includeOffset = -1;
|
||||||
|
int includeEndOffset = -1;
|
||||||
|
int includeGuardStatementsToSkip = getNumberOfIncludeGuardStatementsToSkip(ast);
|
||||||
|
int includeGuardEndOffset = -1;
|
||||||
|
for (IASTPreprocessorStatement statement : ast.getAllPreprocessorStatements()) {
|
||||||
|
if (statement.isPartOfTranslationUnitFile()) {
|
||||||
|
IASTFileLocation fileLocation = statement.getFileLocation();
|
||||||
|
int offset = fileLocation.getNodeOffset();
|
||||||
|
if (offset >= maxSafeOffset)
|
||||||
|
break;
|
||||||
|
int endOffset = offset + fileLocation.getNodeLength();
|
||||||
|
|
||||||
|
if (includeGuardStatementsToSkip > 0) {
|
||||||
|
--includeGuardStatementsToSkip;
|
||||||
|
includeGuardEndOffset = endOffset;
|
||||||
|
if (!commentMap.getLeadingCommentsForNode(statement).isEmpty()) {
|
||||||
|
topCommentSkipped = true;
|
||||||
|
}
|
||||||
|
} else if (statement instanceof IASTPreprocessorIncludeStatement) {
|
||||||
|
if (includeOffset < 0)
|
||||||
|
includeOffset = offset;
|
||||||
|
includeEndOffset = endOffset;
|
||||||
|
includeGuardStatementsToSkip = 0; // Just in case
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (includeOffset <= 0) {
|
||||||
|
if (includeGuardEndOffset >= 0) {
|
||||||
|
includeOffset = skipToNextLine(includeGuardEndOffset);
|
||||||
|
} else {
|
||||||
|
includeOffset = 0;
|
||||||
|
}
|
||||||
|
if (!topCommentSkipped) {
|
||||||
|
// Skip the first comment block near the top of the file.
|
||||||
|
includeOffset = skipStandaloneCommentBlock(includeOffset, maxSafeOffset, ast.getComments(), commentMap);
|
||||||
|
}
|
||||||
|
includeEndOffset = includeOffset;
|
||||||
|
} else {
|
||||||
|
includeEndOffset = skipToNextLine(includeEndOffset);
|
||||||
|
}
|
||||||
|
return new Region(includeOffset, includeEndOffset - includeOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getNumberOfIncludeGuardStatementsToSkip(IASTTranslationUnit ast) {
|
||||||
|
IASTPreprocessorStatement statement = findFirstPreprocessorStatement(ast);
|
||||||
|
if (statement == null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int num = 0;
|
||||||
|
int offset = 0;
|
||||||
|
if (isPragmaOnce(statement)) {
|
||||||
|
num++;
|
||||||
|
offset = getNodeEndOffset(statement);
|
||||||
|
}
|
||||||
|
char[] contents = ast.getRawSignature().toCharArray();
|
||||||
|
if (offset != 0)
|
||||||
|
Arrays.copyOfRange(contents, offset, contents.length);
|
||||||
|
CharArrayIntMap ppKeywords= new CharArrayIntMap(40, -1);
|
||||||
|
Keywords.addKeywordsPreprocessor(ppKeywords);
|
||||||
|
if (IncludeGuardDetection.detectIncludeGuard(new CharArray(contents), new LexerOptions(), ppKeywords) != null) {
|
||||||
|
num += 2;
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IASTPreprocessorStatement findFirstPreprocessorStatement(IASTTranslationUnit ast) {
|
||||||
|
for (IASTPreprocessorStatement statement : ast.getAllPreprocessorStatements()) {
|
||||||
|
if (statement.isPartOfTranslationUnitFile())
|
||||||
|
return statement;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private boolean isPragmaOnce(IASTPreprocessorStatement statement) {
|
||||||
|
if (!(statement instanceof IASTPreprocessorPragmaStatement))
|
||||||
|
return false;
|
||||||
|
return CharArrayUtils.equals(((IASTPreprocessorPragmaStatement) statement).getMessage(), "once"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
private int skipToNextLine(int offset) {
|
||||||
|
char[] contents = fContext.getTranslationUnit().getContents();
|
||||||
|
while (offset < contents.length) {
|
||||||
|
if (contents[offset++] == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getLineStart(int offset) {
|
||||||
|
char[] contents = fContext.getTranslationUnit().getContents();
|
||||||
|
while (--offset >= 0) {
|
||||||
|
if (contents[offset] == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return offset + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int skipToNextLineAfterNode(IASTNode node) {
|
||||||
|
return skipToNextLine(getNodeEndOffset(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if there are no non-whitespace characters between the given
|
||||||
|
* {@code offset} and the end of the line.
|
||||||
|
*/
|
||||||
|
private boolean isBlankLineOrEndOfFile(int offset) {
|
||||||
|
char[] contents = fContext.getTranslationUnit().getContents();
|
||||||
|
while (offset < contents.length) {
|
||||||
|
char c = contents[offset++];
|
||||||
|
if (c == '\n')
|
||||||
|
return true;
|
||||||
|
if (!Character.isWhitespace(c))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} the line prior to the line corresponding to the given {@code offset}
|
||||||
|
* does not contain non-whitespace characters.
|
||||||
|
*/
|
||||||
|
private boolean isPreviousLineBlank(int offset) {
|
||||||
|
char[] contents = fContext.getTranslationUnit().getContents();
|
||||||
|
while (--offset >= 0) {
|
||||||
|
if (contents[offset] == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (--offset >= 0) {
|
||||||
|
char c = contents[offset];
|
||||||
|
if (c == '\n')
|
||||||
|
return true;
|
||||||
|
if (!Character.isWhitespace(c))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the whitespace preceding the given node. The newline character in not considered
|
||||||
|
* whitespace for the purpose of this method.
|
||||||
|
*/
|
||||||
|
private String getPrecedingWhitespace(IASTNode node) {
|
||||||
|
int offset = getNodeOffset(node);
|
||||||
|
if (offset >= 0) {
|
||||||
|
char[] contents = fContext.getTranslationUnit().getContents();
|
||||||
|
int i = offset;
|
||||||
|
while (--i >= 0) {
|
||||||
|
char c = contents[i];
|
||||||
|
if (c == '\n' || !Character.isWhitespace(c))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
return new String(contents, i, offset - i);
|
||||||
|
}
|
||||||
|
return ""; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
private int skipStandaloneCommentBlock(int offset, int endOffset, IASTComment[] comments, NodeCommentMap commentMap) {
|
||||||
|
Map<IASTComment, IASTNode> inverseLeadingMap = new HashMap<IASTComment, IASTNode>();
|
||||||
|
for (Map.Entry<IASTNode, List<IASTComment>> entry : commentMap.getLeadingMap().entrySet()) {
|
||||||
|
IASTNode node = entry.getKey();
|
||||||
|
if (getNodeOffset(node) <= endOffset) {
|
||||||
|
for (IASTComment comment : entry.getValue()) {
|
||||||
|
inverseLeadingMap.put(comment, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map<IASTComment, IASTNode> inverseFreestandingMap = new HashMap<IASTComment, IASTNode>();
|
||||||
|
for (Map.Entry<IASTNode, List<IASTComment>> entry : commentMap.getFreestandingMap().entrySet()) {
|
||||||
|
IASTNode node = entry.getKey();
|
||||||
|
if (getNodeEndOffset(node) < endOffset) {
|
||||||
|
for (IASTComment comment : entry.getValue()) {
|
||||||
|
inverseFreestandingMap.put(comment, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the source code to insert into the editor.
|
for (int i = 0; i < comments.length; i++) {
|
||||||
IBuffer fBuffer = fContext.getTranslationUnit().getBuffer();
|
IASTComment comment = comments[i];
|
||||||
String lineSep = getLineSeparator(fBuffer);
|
int commentOffset = getNodeOffset(comment);
|
||||||
|
if (commentOffset >= offset) {
|
||||||
StringBuilder buf = new StringBuilder();
|
if (commentOffset >= endOffset)
|
||||||
for (String include : includeDirectives) {
|
break;
|
||||||
buf.append(include);
|
IASTNode node = inverseLeadingMap.get(comment);
|
||||||
buf.append(lineSep);
|
if (node != null) {
|
||||||
|
List<IASTComment> leadingComments = commentMap.getLeadingMap().get(node);
|
||||||
|
IASTComment previous = leadingComments.get(0);
|
||||||
|
for (int j = 1; j < leadingComments.size(); j++) {
|
||||||
|
comment = leadingComments.get(j);
|
||||||
|
if (getStartingLineNumber(comment) > getEndingLineNumber(previous) + 1)
|
||||||
|
return skipToNextLineAfterNode(previous);
|
||||||
|
previous = comment;
|
||||||
}
|
}
|
||||||
|
if (getStartingLineNumber(node) > getEndingLineNumber(previous) + 1)
|
||||||
if (buf.length() != 0 && !forwardDeclarations.isEmpty())
|
return skipToNextLineAfterNode(previous);
|
||||||
buf.append(lineSep);
|
|
||||||
for (String declaration : forwardDeclarations) {
|
|
||||||
buf.append(declaration);
|
|
||||||
buf.append(lineSep);
|
|
||||||
}
|
}
|
||||||
|
node = inverseFreestandingMap.get(comment);
|
||||||
if (buf.length() != 0 && !functionForwardDeclarations.isEmpty())
|
if (node != null) {
|
||||||
buf.append(lineSep);
|
List<IASTComment> freestandingComments = commentMap.getFreestandingMap().get(node);
|
||||||
for (String declaration : functionForwardDeclarations) {
|
IASTComment previous = freestandingComments.get(0);
|
||||||
buf.append(declaration);
|
for (int j = 1; j < freestandingComments.size(); j++) {
|
||||||
buf.append(lineSep);
|
comment = freestandingComments.get(j);
|
||||||
|
if (getStartingLineNumber(comment) > getEndingLineNumber(previous) + 1)
|
||||||
|
return skipToNextLineAfterNode(previous);
|
||||||
|
previous = comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf.length() != 0) {
|
|
||||||
buf.append(lineSep);
|
|
||||||
fBuffer.replace(0, 0, buf.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
private IncludeGroupStyle getGroupingStyle(IncludeGroupStyle style) {
|
private IncludeGroupStyle getGroupingStyle(IncludeGroupStyle style) {
|
||||||
if (style.isKeepTogether())
|
if (style.isKeepTogether())
|
||||||
|
@ -357,7 +792,7 @@ public class IncludeOrganizer {
|
||||||
private IncludeGroupStyle getIncludeStyle(IPath headerPath) {
|
private IncludeGroupStyle getIncludeStyle(IPath headerPath) {
|
||||||
IncludeKind includeKind;
|
IncludeKind includeKind;
|
||||||
IncludeInfo includeInfo = fContext.getIncludeForHeaderFile(headerPath);
|
IncludeInfo includeInfo = fContext.getIncludeForHeaderFile(headerPath);
|
||||||
if (includeInfo.isSystem()) {
|
if (includeInfo != null && includeInfo.isSystem()) {
|
||||||
if (headerPath.getFileExtension() == null) {
|
if (headerPath.getFileExtension() == null) {
|
||||||
includeKind = IncludeKind.SYSTEM_WITHOUT_EXTENSION;
|
includeKind = IncludeKind.SYSTEM_WITHOUT_EXTENSION;
|
||||||
} else {
|
} else {
|
||||||
|
@ -389,8 +824,24 @@ public class IncludeOrganizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Map<IncludeKind, IncludeGroupStyle> styles = fContext.getPreferences().includeStyles;
|
return fContext.getPreferences().includeStyles.get(includeKind);
|
||||||
return styles.get(includeKind);
|
}
|
||||||
|
|
||||||
|
private IncludeGroupStyle getIncludeStyle(IncludeInfo includeInfo) {
|
||||||
|
IncludeKind includeKind;
|
||||||
|
IPath path = Path.fromPortableString(includeInfo.getName());
|
||||||
|
if (includeInfo.isSystem()) {
|
||||||
|
if (path.getFileExtension() == null) {
|
||||||
|
includeKind = IncludeKind.SYSTEM_WITHOUT_EXTENSION;
|
||||||
|
} else {
|
||||||
|
includeKind = IncludeKind.SYSTEM_WITH_EXTENSION;
|
||||||
|
}
|
||||||
|
} else if (isPartnerFile(path)) {
|
||||||
|
includeKind = IncludeKind.PARTNER;
|
||||||
|
} else {
|
||||||
|
includeKind = IncludeKind.EXTERNAL;
|
||||||
|
}
|
||||||
|
return fContext.getPreferences().includeStyles.get(includeKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<IBinding> removeBindingsDefinedInIncludedHeaders(Set<IBinding> bindings,
|
private Set<IBinding> removeBindingsDefinedInIncludedHeaders(Set<IBinding> bindings,
|
||||||
|
@ -426,7 +877,8 @@ public class IncludeOrganizer {
|
||||||
private void processInclusionRequests(List<InclusionRequest> requests,
|
private void processInclusionRequests(List<InclusionRequest> requests,
|
||||||
HeaderSubstitutor headerSubstitutor) {
|
HeaderSubstitutor headerSubstitutor) {
|
||||||
// Add partner header if necessary.
|
// Add partner header if necessary.
|
||||||
HashSet<IIndexFile> partnerIndexFiles = new HashSet<IIndexFile>();
|
HashSet<IIndexFile> includedByPartner = fContext.getPreferences().allowPartnerIndirectInclusion ?
|
||||||
|
new HashSet<IIndexFile>() : null;
|
||||||
for (InclusionRequest request : requests) {
|
for (InclusionRequest request : requests) {
|
||||||
List<IPath> candidatePaths = request.getCandidatePaths();
|
List<IPath> candidatePaths = request.getCandidatePaths();
|
||||||
if (candidatePaths.size() == 1) {
|
if (candidatePaths.size() == 1) {
|
||||||
|
@ -434,13 +886,14 @@ public class IncludeOrganizer {
|
||||||
if (isPartnerFile(path)) {
|
if (isPartnerFile(path)) {
|
||||||
request.resolve(path);
|
request.resolve(path);
|
||||||
fContext.addHeaderToInclude(path);
|
fContext.addHeaderToInclude(path);
|
||||||
|
if (includedByPartner != null) {
|
||||||
try {
|
try {
|
||||||
IIndexFile indexFile = request.getDeclaringFiles().keySet().iterator().next();
|
IIndexFile indexFile = request.getDeclaringFiles().keySet().iterator().next();
|
||||||
if (!partnerIndexFiles.contains(indexFile)) {
|
if (!includedByPartner.contains(indexFile)) {
|
||||||
for (IIndexInclude include : indexFile.getIncludes()) {
|
for (IIndexInclude include : indexFile.getIncludes()) {
|
||||||
fContext.addHeaderAlreadyIncluded(getPath(include.getIncludesLocation()));
|
fContext.addHeaderAlreadyIncluded(getPath(include.getIncludesLocation()));
|
||||||
}
|
}
|
||||||
partnerIndexFiles.add(indexFile);
|
includedByPartner.add(indexFile);
|
||||||
}
|
}
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
CUIPlugin.log(e);
|
CUIPlugin.log(e);
|
||||||
|
@ -448,6 +901,7 @@ public class IncludeOrganizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Process headers that are either indirectly included or have unique representatives.
|
// Process headers that are either indirectly included or have unique representatives.
|
||||||
for (InclusionRequest request : requests) {
|
for (InclusionRequest request : requests) {
|
||||||
|
@ -502,8 +956,6 @@ public class IncludeOrganizer {
|
||||||
// Resolve ambiguous inclusion requests.
|
// Resolve ambiguous inclusion requests.
|
||||||
|
|
||||||
// Maps a set of header files presented to the user to the file selected by the user.
|
// Maps a set of header files presented to the user to the file selected by the user.
|
||||||
HashMap<Collection<IPath>, IPath> userChoiceCache = new HashMap<Collection<IPath>, IPath>();
|
|
||||||
|
|
||||||
for (InclusionRequest request : requests) {
|
for (InclusionRequest request : requests) {
|
||||||
if (!request.isResolved()) {
|
if (!request.isResolved()) {
|
||||||
List<IPath> candidatePaths = request.getCandidatePaths();
|
List<IPath> candidatePaths = request.getCandidatePaths();
|
||||||
|
@ -513,7 +965,10 @@ public class IncludeOrganizer {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IPath header = askUserToSelectHeader(request.getBinding(), candidatePaths, userChoiceCache);
|
IPath header = fHeaderChooser.chooseHeader(request.getBinding().getName(), candidatePaths);
|
||||||
|
if (header == null)
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
|
||||||
request.resolve(header);
|
request.resolve(header);
|
||||||
if (!fContext.isAlreadyIncluded(header))
|
if (!fContext.isAlreadyIncluded(header))
|
||||||
fContext.addHeaderToInclude(header);
|
fContext.addHeaderToInclude(header);
|
||||||
|
@ -606,98 +1061,48 @@ public class IncludeOrganizer {
|
||||||
return requests;
|
return requests;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private IncludeInfo createIncludeInfo(IPath header, IncludeGroupStyle style) {
|
||||||
* Returns the line separator for the given buffer.
|
|
||||||
* @param fBuffer
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private String getLineSeparator(IBuffer fBuffer) {
|
|
||||||
try {
|
|
||||||
if (fBuffer instanceof IAdaptable) {
|
|
||||||
IDocument doc= (IDocument) ((IAdaptable) fBuffer).getAdapter(IDocument.class);
|
|
||||||
if (doc != null) {
|
|
||||||
String delim= doc.getLineDelimiter(0);
|
|
||||||
if (delim != null) {
|
|
||||||
return delim;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (BadLocationException e) {
|
|
||||||
}
|
|
||||||
return System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Picks a suitable header file that should be used to include the given binding.
|
|
||||||
*
|
|
||||||
* @param binding The binding which should be resolved.
|
|
||||||
* @param headers The available header files to pick from.
|
|
||||||
* @param userChoiceCache the cache of previous user choices
|
|
||||||
* @return The chosen header file.
|
|
||||||
*/
|
|
||||||
private IPath askUserToSelectHeader(IBinding binding, Collection<IPath> headers,
|
|
||||||
HashMap<Collection<IPath>, IPath> userChoiceCache) {
|
|
||||||
if (headers.isEmpty())
|
|
||||||
return null;
|
|
||||||
if (headers.size() == 1)
|
|
||||||
return headers.iterator().next();
|
|
||||||
|
|
||||||
// Check the decision cache. If the cache doesn't help, ask the user.
|
|
||||||
// Query the cache.
|
|
||||||
if (userChoiceCache.containsKey(headers)) {
|
|
||||||
return userChoiceCache.get(headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask the user.
|
|
||||||
final IPath[] elemArray = headers.toArray(new IPath[headers.size()]);
|
|
||||||
final IPath[] selectedElement = new IPath[1];
|
|
||||||
final String bindingName = binding.getName();
|
|
||||||
runInUIThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
ElementListSelectionDialog dialog =
|
|
||||||
new ElementListSelectionDialog(fEditor.getSite().getShell(), new LabelProvider());
|
|
||||||
dialog.setElements(elemArray);
|
|
||||||
dialog.setTitle(CEditorMessages.OrganizeIncludes_label);
|
|
||||||
dialog.setMessage(NLS.bind(Messages.IncludeOrganizer_ChooseHeader, bindingName));
|
|
||||||
if (dialog.open() == Window.OK) {
|
|
||||||
selectedElement[0] = (IPath) dialog.getFirstResult();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
IPath selectedHeader = selectedElement[0];
|
|
||||||
|
|
||||||
if (selectedHeader == null)
|
|
||||||
throw new OperationCanceledException();
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String createIncludeDirective(IPath header, IncludeGroupStyle style, String lineComment) {
|
|
||||||
StringBuilder buf = new StringBuilder("#include "); //$NON-NLS-1$
|
|
||||||
buf.append(style.isAngleBrackets() ? '<' : '"');
|
|
||||||
String name = null;
|
String name = null;
|
||||||
if (style.isRelativePath()) {
|
if (style.isRelativePath()) {
|
||||||
IPath relativePath = PathUtil.makeRelativePath(header, fContext.getCurrentDirectory());
|
name = getRelativePath(header);
|
||||||
if (relativePath != null)
|
|
||||||
name = relativePath.toPortableString();
|
|
||||||
}
|
}
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
IncludeInfo includeInfo = fContext.getIncludeForHeaderFile(header);
|
IncludeInfo includeInfo = fContext.getIncludeForHeaderFile(header);
|
||||||
|
if (includeInfo != null) {
|
||||||
name = includeInfo.getName();
|
name = includeInfo.getName();
|
||||||
|
} else {
|
||||||
|
name = getRelativePath(header);
|
||||||
}
|
}
|
||||||
buf.append(name);
|
if (name == null) {
|
||||||
buf.append(style.isAngleBrackets() ? '>' : '"');
|
name = header.toPortableString(); // Last resort.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new IncludeInfo(name, style.isAngleBrackets());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRelativePath(IPath header) {
|
||||||
|
IPath relativePath = PathUtil.makeRelativePath(header, fContext.getCurrentDirectory());
|
||||||
|
if (relativePath == null)
|
||||||
|
return null;
|
||||||
|
return relativePath.toPortableString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createIncludeDirective(IncludePrototype include, String lineComment) {
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
// Unresolved includes are preserved out of caution.
|
||||||
|
if (!include.required && include.header != null) {
|
||||||
|
switch (fContext.getPreferences().unusedStatementsDisposition) {
|
||||||
|
case REMOVE:
|
||||||
|
return null;
|
||||||
|
case COMMENT_OUT:
|
||||||
|
buf.append("//"); //$NON-NLS-1$
|
||||||
|
break;
|
||||||
|
case KEEP:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.append("#include "); //$NON-NLS-1$
|
||||||
|
buf.append(include.includeInfo.toString());
|
||||||
buf.append(lineComment);
|
buf.append(lineComment);
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,26 +34,30 @@ public class IncludePreferences {
|
||||||
public final Map<IncludeKind, IncludeGroupStyle> includeStyles;
|
public final Map<IncludeKind, IncludeGroupStyle> includeStyles;
|
||||||
public final boolean allowReordering;
|
public final boolean allowReordering;
|
||||||
public final boolean heuristicHeaderSubstitution;
|
public final boolean heuristicHeaderSubstitution;
|
||||||
|
public final boolean allowPartnerIndirectInclusion;
|
||||||
public final boolean forwardDeclareCompositeTypes;
|
public final boolean forwardDeclareCompositeTypes;
|
||||||
public final boolean forwardDeclareEnums;
|
public final boolean forwardDeclareEnums;
|
||||||
public final boolean forwardDeclareFunctions;
|
public final boolean forwardDeclareFunctions;
|
||||||
|
// TODO(sprigogin): Create a preference.
|
||||||
|
public final boolean forwardDeclareExternalVariables = false;
|
||||||
|
public final boolean forwardDeclareTemplates;
|
||||||
public final boolean forwardDeclareNamespaceElements;
|
public final boolean forwardDeclareNamespaceElements;
|
||||||
public final UnusedStatementDisposition unusedStatementsDisposition;
|
public final UnusedStatementDisposition unusedStatementsDisposition;
|
||||||
public final String[] partnerFileSuffixes;
|
public final String[] partnerFileSuffixes;
|
||||||
|
|
||||||
public IncludePreferences(ICProject project) {
|
public IncludePreferences(ICProject project) {
|
||||||
includeStyles = new HashMap<IncludeKind, IncludeGroupStyle>();
|
includeStyles = new HashMap<IncludeKind, IncludeGroupStyle>();
|
||||||
loadStyle(IncludeKind.RELATED, PREF_INCLUDE_STYLE_RELATED, project);
|
loadStyle(IncludeKind.RELATED, PreferenceConstants.INCLUDE_STYLE_RELATED, project);
|
||||||
loadStyle(IncludeKind.PARTNER, PREF_INCLUDE_STYLE_PARTNER, project);
|
loadStyle(IncludeKind.PARTNER, PreferenceConstants.INCLUDE_STYLE_PARTNER, project);
|
||||||
loadStyle(IncludeKind.IN_SAME_FOLDER, PREF_INCLUDE_STYLE_SAME_FOLDER, project);
|
loadStyle(IncludeKind.IN_SAME_FOLDER, PreferenceConstants.INCLUDE_STYLE_SAME_FOLDER, project);
|
||||||
loadStyle(IncludeKind.IN_SUBFOLDER, PREF_INCLUDE_STYLE_SUBFOLDER, project);
|
loadStyle(IncludeKind.IN_SUBFOLDER, PreferenceConstants.INCLUDE_STYLE_SUBFOLDER, project);
|
||||||
loadStyle(IncludeKind.SYSTEM, PREF_INCLUDE_STYLE_SYSTEM, project);
|
loadStyle(IncludeKind.SYSTEM, PreferenceConstants.INCLUDE_STYLE_SYSTEM, project);
|
||||||
loadStyle(IncludeKind.SYSTEM_WITH_EXTENSION, PREF_INCLUDE_STYLE_SYSTEM_WITH_EXTENSION, project);
|
loadStyle(IncludeKind.SYSTEM_WITH_EXTENSION, PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITH_EXTENSION, project);
|
||||||
loadStyle(IncludeKind.SYSTEM_WITHOUT_EXTENSION, PREF_INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION, project);
|
loadStyle(IncludeKind.SYSTEM_WITHOUT_EXTENSION, PreferenceConstants.INCLUDE_STYLE_SYSTEM_WITHOUT_EXTENSION, project);
|
||||||
loadStyle(IncludeKind.OTHER, PREF_INCLUDE_STYLE_OTHER, project);
|
loadStyle(IncludeKind.OTHER, PreferenceConstants.INCLUDE_STYLE_OTHER, project);
|
||||||
loadStyle(IncludeKind.IN_SAME_PROJECT, PREF_INCLUDE_STYLE_SAME_PROJECT, project);
|
loadStyle(IncludeKind.IN_SAME_PROJECT, PreferenceConstants.INCLUDE_STYLE_SAME_PROJECT, project);
|
||||||
loadStyle(IncludeKind.IN_OTHER_PROJECT, PREF_INCLUDE_STYLE_OTHER_PROJECT, project);
|
loadStyle(IncludeKind.IN_OTHER_PROJECT, PreferenceConstants.INCLUDE_STYLE_OTHER_PROJECT, project);
|
||||||
loadStyle(IncludeKind.EXTERNAL, PREF_INCLUDE_STYLE_EXTERNAL, project);
|
loadStyle(IncludeKind.EXTERNAL, PreferenceConstants.INCLUDE_STYLE_EXTERNAL, project);
|
||||||
// Unclassified includes are always kept together.
|
// Unclassified includes are always kept together.
|
||||||
includeStyles.get(IncludeKind.OTHER).setKeepTogether(true);
|
includeStyles.get(IncludeKind.OTHER).setKeepTogether(true);
|
||||||
// Normalize order property of the styles to make sure that the numbers are sequential.
|
// 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.
|
// TODO(sprigogin): Load styles for headers matching patterns.
|
||||||
|
|
||||||
forwardDeclareCompositeTypes = PreferenceConstants.getPreference(
|
forwardDeclareCompositeTypes = PreferenceConstants.getPreference(
|
||||||
PREF_FORWARD_DECLARE_COMPOSITE_TYPES, project, true);
|
PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES, project, true);
|
||||||
forwardDeclareEnums = PreferenceConstants.getPreference(
|
forwardDeclareEnums = PreferenceConstants.getPreference(
|
||||||
PREF_FORWARD_DECLARE_ENUMS, project, false);
|
PreferenceConstants.FORWARD_DECLARE_ENUMS, project, false);
|
||||||
forwardDeclareFunctions = PreferenceConstants.getPreference(
|
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(
|
forwardDeclareNamespaceElements = PreferenceConstants.getPreference(
|
||||||
PREF_FORWARD_DECLARE_NAMESPACE_ELEMENTS, project, true);
|
PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS, project, true);
|
||||||
|
|
||||||
String value = PreferenceConstants.getPreference(
|
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$
|
partnerFileSuffixes = value.split(","); //$NON-NLS-1$
|
||||||
|
|
||||||
heuristicHeaderSubstitution = PreferenceConstants.getPreference(
|
heuristicHeaderSubstitution = PreferenceConstants.getPreference(
|
||||||
PREF_HEURISTIC_HEADER_SUBSTITUTION, project, true);
|
PreferenceConstants.INCLUDES_HEURISTIC_HEADER_SUBSTITUTION, project, true);
|
||||||
|
|
||||||
allowReordering = PreferenceConstants.getPreference(
|
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
|
// 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;
|
UnusedStatementDisposition disposition = null;
|
||||||
if (value != null)
|
if (value != null)
|
||||||
disposition = UnusedStatementDisposition.valueOf(value);
|
disposition = UnusedStatementDisposition.valueOf(value);
|
||||||
|
@ -103,148 +112,6 @@ public class IncludePreferences {
|
||||||
includeStyles.put(includeKind, style);
|
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.
|
* Initializes the given preference store with the default values.
|
||||||
*
|
*
|
||||||
|
@ -252,50 +119,51 @@ public class IncludePreferences {
|
||||||
*/
|
*/
|
||||||
public static void initializeDefaultValues(IPreferenceStore store) {
|
public static void initializeDefaultValues(IPreferenceStore store) {
|
||||||
IncludeGroupStyle style = new IncludeGroupStyle(IncludeKind.RELATED);
|
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 = new IncludeGroupStyle(IncludeKind.PARTNER);
|
||||||
style.setKeepTogether(true);
|
style.setKeepTogether(true);
|
||||||
style.setBlankLineBefore(true);
|
style.setBlankLineBefore(true);
|
||||||
style.setOrder(0);
|
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);
|
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);
|
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 = new IncludeGroupStyle(IncludeKind.SYSTEM);
|
||||||
style.setKeepTogether(true);
|
style.setKeepTogether(true);
|
||||||
style.setBlankLineBefore(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 = new IncludeGroupStyle(IncludeKind.SYSTEM_WITH_EXTENSION);
|
||||||
style.setKeepTogether(true);
|
style.setKeepTogether(true);
|
||||||
style.setAngleBrackets(true);
|
style.setAngleBrackets(true);
|
||||||
style.setOrder(1);
|
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 = new IncludeGroupStyle(IncludeKind.SYSTEM_WITHOUT_EXTENSION);
|
||||||
style.setKeepTogether(true);
|
style.setKeepTogether(true);
|
||||||
style.setAngleBrackets(true);
|
style.setAngleBrackets(true);
|
||||||
style.setOrder(2);
|
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 = new IncludeGroupStyle(IncludeKind.OTHER);
|
||||||
style.setKeepTogether(true);
|
style.setKeepTogether(true);
|
||||||
style.setBlankLineBefore(true);
|
style.setBlankLineBefore(true);
|
||||||
style.setOrder(3);
|
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);
|
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);
|
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);
|
style = new IncludeGroupStyle(IncludeKind.EXTERNAL);
|
||||||
store.setDefault(PREF_INCLUDE_STYLE_EXTERNAL, style.toString());
|
store.setDefault(PreferenceConstants.INCLUDE_STYLE_EXTERNAL, style.toString());
|
||||||
store.setDefault(PREF_INCLUDE_STYLE_MATCHING_PATTERN, ""); //$NON-NLS-1$
|
store.setDefault(PreferenceConstants.INCLUDE_STYLE_MATCHING_PATTERN, ""); //$NON-NLS-1$
|
||||||
|
|
||||||
store.setDefault(PREF_PARTNER_FILE_SUFFIXES, DEFAULT_PARTNER_FILE_SUFFIXES);
|
store.setDefault(PreferenceConstants.INCLUDES_PARTNER_FILE_SUFFIXES, DEFAULT_PARTNER_FILE_SUFFIXES);
|
||||||
store.setDefault(PREF_HEURISTIC_HEADER_SUBSTITUTION, true);
|
store.setDefault(PreferenceConstants.INCLUDES_HEURISTIC_HEADER_SUBSTITUTION, true);
|
||||||
store.setDefault(PREF_INCLUDES_REORDERING, true);
|
store.setDefault(PreferenceConstants.INCLUDES_ALLOW_REORDERING, true);
|
||||||
store.setDefault(PREF_FORWARD_DECLARE_COMPOSITE_TYPES, true);
|
store.setDefault(PreferenceConstants.FORWARD_DECLARE_COMPOSITE_TYPES, true);
|
||||||
store.setDefault(PREF_FORWARD_DECLARE_ENUMS, false);
|
store.setDefault(PreferenceConstants.FORWARD_DECLARE_ENUMS, false);
|
||||||
store.setDefault(PREF_FORWARD_DECLARE_FUNCTIONS, false);
|
store.setDefault(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, false);
|
||||||
store.setDefault(PREF_FORWARD_DECLARE_NAMESPACE_ELEMENTS, true);
|
store.setDefault(PreferenceConstants.FORWARD_DECLARE_TEMPLATES, false);
|
||||||
store.setDefault(PREF_UNUSED_STATEMENTS_DISPOSITION, UnusedStatementDisposition.COMMENT_OUT.toString());
|
store.setDefault(PreferenceConstants.FORWARD_DECLARE_NAMESPACE_ELEMENTS, true);
|
||||||
|
store.setDefault(PreferenceConstants.INCLUDES_UNUSED_STATEMENTS_DISPOSITION, UnusedStatementDisposition.COMMENT_OUT.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -34,7 +34,7 @@ import org.eclipse.cdt.internal.core.parser.scanner.ScannerUtility;
|
||||||
* Context for managing include statements.
|
* Context for managing include statements.
|
||||||
*/
|
*/
|
||||||
public class InclusionContext {
|
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 ITranslationUnit fTu;
|
||||||
private final IProject fProject;
|
private final IProject fProject;
|
||||||
|
@ -132,22 +132,19 @@ public class InclusionContext {
|
||||||
String headerLocation = fullPath.toOSString();
|
String headerLocation = fullPath.toOSString();
|
||||||
String shortestInclude = null;
|
String shortestInclude = null;
|
||||||
boolean isSystem = false;
|
boolean isSystem = false;
|
||||||
int count = 0; //XXX
|
|
||||||
for (IncludeSearchPathElement pathElement : fIncludeSearchPath.getElements()) {
|
for (IncludeSearchPathElement pathElement : fIncludeSearchPath.getElements()) {
|
||||||
String includeDirective = pathElement.getIncludeDirective(headerLocation);
|
String includeDirective = pathElement.getIncludeDirective(headerLocation);
|
||||||
if (includeDirective != null &&
|
if (includeDirective != null &&
|
||||||
(shortestInclude == null || shortestInclude.length() > includeDirective.length())) {
|
(shortestInclude == null || shortestInclude.length() > includeDirective.length())) {
|
||||||
shortestInclude = includeDirective;
|
shortestInclude = includeDirective;
|
||||||
isSystem = !pathElement.isForQuoteIncludesOnly();
|
isSystem = !pathElement.isForQuoteIncludesOnly();
|
||||||
if (count < 1) //XXX
|
|
||||||
isSystem = false; //XXX Hack to introduce non-system includes
|
|
||||||
}
|
}
|
||||||
count++; //XXX
|
|
||||||
}
|
}
|
||||||
if (shortestInclude == null)
|
if (shortestInclude == null)
|
||||||
return null;
|
return null;
|
||||||
include = new IncludeInfo(shortestInclude, isSystem);
|
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);
|
fInverseIncludeResolutionCache.put(fullPath, include);
|
||||||
return include;
|
return include;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
|
|
@ -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}''
|
|
|
@ -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$
|
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.
|
* Returns the CDT-UI preference store.
|
||||||
|
|
|
@ -139,6 +139,13 @@ public class CdtActionConstants {
|
||||||
*/
|
*/
|
||||||
public static final String ADD_INCLUDE= "org.eclipse.cdt.ui.actions.AddInclude"; //$NON-NLS-1$
|
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
|
* Source menu: name of standard Sort Lines global action
|
||||||
* (value <code>"org.eclipse.cdt.ui.actions.SortLines"</code>).
|
* (value <code>"org.eclipse.cdt.ui.actions.SortLines"</code>).
|
||||||
|
|
|
@ -160,7 +160,7 @@ public class GenerateActionGroup extends ActionGroup implements ISelectionChange
|
||||||
editor.setAction("AddIncludeOnSelection", fAddInclude); //$NON-NLS-1$
|
editor.setAction("AddIncludeOnSelection", fAddInclude); //$NON-NLS-1$
|
||||||
|
|
||||||
fOrganizeIncludes= new OrganizeIncludesAction(editor);
|
fOrganizeIncludes= new OrganizeIncludesAction(editor);
|
||||||
// TODO: fOrganizeIncludes.setActionDefinitionId(ICEditorActionDefinitionIds.ORGANIZE_INCLUDES);
|
fOrganizeIncludes.setActionDefinitionId(ICEditorActionDefinitionIds.ORGANIZE_INCLUDES);
|
||||||
editor.setAction("OrganizeIncludes", fOrganizeIncludes); //$NON-NLS-1$
|
editor.setAction("OrganizeIncludes", fOrganizeIncludes); //$NON-NLS-1$
|
||||||
|
|
||||||
// fSortMembers= new SortMembersAction(editor);
|
// fSortMembers= new SortMembersAction(editor);
|
||||||
|
|
Loading…
Add table
Reference in a new issue