From 147e2efc706ef7459d605bca8fe9f7499b07ea91 Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Sun, 10 Mar 2013 21:03:15 -0400 Subject: [PATCH 01/14] Some JavaDoc for Build Variables change listeners --- .../core/cdtvariables/ICdtVariableChangeListener.java | 3 +++ .../core/cdtvariables/UserDefinedVariableSupplier.java | 10 ++++++++++ .../core/cdtvariables/VariableChangeEvent.java | 3 +++ 3 files changed, 16 insertions(+) diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/ICdtVariableChangeListener.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/ICdtVariableChangeListener.java index 79740cd4bef..eda0e2096d4 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/ICdtVariableChangeListener.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/ICdtVariableChangeListener.java @@ -10,6 +10,9 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.cdtvariables; +/** + * Listener to listen to Build Variables changes events. + */ public interface ICdtVariableChangeListener { void variablesChanged(VariableChangeEvent event); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/UserDefinedVariableSupplier.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/UserDefinedVariableSupplier.java index b823a917e0a..c098d01fba3 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/UserDefinedVariableSupplier.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/UserDefinedVariableSupplier.java @@ -651,10 +651,20 @@ public class UserDefinedVariableSupplier extends CoreMacroSupplierBase { // protected void updateProjectInfo(int type, Object context){ // } + /** + * Adds a listener that will be notified of changes in Build Variables. + * + * @param listener - the listener to add + */ public void addListener(ICdtVariableChangeListener listener){ fListeners.add(listener); } + /** + * Removes a Build Variables change listener. + * + * @param listener - the listener to remove. + */ public void removeListener(ICdtVariableChangeListener listener){ fListeners.remove(listener); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/VariableChangeEvent.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/VariableChangeEvent.java index e42425b2ada..fbf7db1dd2c 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/VariableChangeEvent.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/cdtvariables/VariableChangeEvent.java @@ -12,6 +12,9 @@ package org.eclipse.cdt.internal.core.cdtvariables; import org.eclipse.cdt.core.cdtvariables.ICdtVariable; +/** + * Event describing Build Variables changes. + */ public class VariableChangeEvent { private static final ICdtVariable[] EMPTY_VAR_ARRAY = new ICdtVariable[0]; From aed09ee4b8bdf2110254ae1e6e84ebd4a5d8e804 Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Mon, 11 Mar 2013 12:24:29 -0400 Subject: [PATCH 02/14] bug 357442: A bit more of tidy EnvironmentVariableManagerToolChain --- .../EnvironmentVariableManagerToolChain.java | 20 ++++++++++++++++++- .../cygwin/IsGnuCygwinToolChainSupported.java | 16 +-------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/envvar/EnvironmentVariableManagerToolChain.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/envvar/EnvironmentVariableManagerToolChain.java index 451b6918fbb..e5d52a004fb 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/envvar/EnvironmentVariableManagerToolChain.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/envvar/EnvironmentVariableManagerToolChain.java @@ -12,11 +12,13 @@ package org.eclipse.cdt.managedbuilder.internal.envvar; import org.eclipse.cdt.core.cdtvariables.ICdtVariable; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.internal.core.cdtvariables.CdtVariableManager; import org.eclipse.cdt.internal.core.cdtvariables.ICoreVariableContextInfo; import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager; import org.eclipse.cdt.internal.core.envvar.ICoreEnvironmentVariableSupplier; import org.eclipse.cdt.internal.core.envvar.IEnvironmentContextInfo; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IToolChain; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSupplier; @@ -27,14 +29,17 @@ import org.eclipse.cdt.utils.cdtvariables.IVariableContextInfo; /** * Helper class to resolve environment variables directly from toolchain. The intention is * to use that in New Project Wizard and other scenarios when no configuration is available yet. - * + * * @noextend This class is not intended to be subclassed by clients. */ public class EnvironmentVariableManagerToolChain extends EnvironmentVariableManager { private final IToolChain toolChain; + private final ICConfigurationDescription cfgDescription; public EnvironmentVariableManagerToolChain(IToolChain toolchain) { this.toolChain = toolchain; + IConfiguration cfg = toolChain.getParent(); + cfgDescription = cfg != null ? ManagedBuildManager.getDescriptionForConfiguration(cfg) : null; } /** @@ -154,6 +159,11 @@ public class EnvironmentVariableManagerToolChain extends EnvironmentVariableMana */ @Override public IEnvironmentContextInfo getContextInfo(Object level) { + if (cfgDescription != null) { + // Use regular EnvironmentVariableManager when configuration is available + return super.getContextInfo(level); + } + return new ToolChainEnvironmentContextInfo(toolChain); } @@ -162,7 +172,15 @@ public class EnvironmentVariableManagerToolChain extends EnvironmentVariableMana */ @Override public ICoreVariableContextInfo getMacroContextInfoForContext(Object context) { + if (cfgDescription != null) { + // Use regular EnvironmentVariableManager when configuration is available + return super.getMacroContextInfoForContext(context); + } + return new ToolChainCoreVariableContextInfo(toolChain); } + public IEnvironmentVariable getVariable(String variableName, boolean resolveMacros) { + return getVariable(variableName, cfgDescription, resolveMacros); + } } diff --git a/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/IsGnuCygwinToolChainSupported.java b/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/IsGnuCygwinToolChainSupported.java index 21998a342dc..5ef738e1572 100644 --- a/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/IsGnuCygwinToolChainSupported.java +++ b/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/IsGnuCygwinToolChainSupported.java @@ -12,14 +12,9 @@ package org.eclipse.cdt.managedbuilder.gnu.cygwin; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; -import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager; -import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.internal.core.Cygwin; -import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager; -import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IManagedIsToolChainSupported; import org.eclipse.cdt.managedbuilder.core.IToolChain; -import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.internal.envvar.EnvironmentVariableManagerToolChain; import org.osgi.framework.Version; @@ -33,16 +28,7 @@ public class IsGnuCygwinToolChainSupported implements IManagedIsToolChainSupport @Override public boolean isSupported(IToolChain toolChain, Version version, String instance) { - IConfiguration cfg = toolChain.getParent(); - ICConfigurationDescription cfgDescription = cfg != null ? ManagedBuildManager.getDescriptionForConfiguration(cfg) : null; - - IEnvironmentVariableManager envMngr; - if (cfgDescription != null) { - envMngr = EnvironmentVariableManager.getDefault(); - } else { - envMngr = new EnvironmentVariableManagerToolChain(toolChain); - } - IEnvironmentVariable var = envMngr.getVariable(ENV_PATH, cfgDescription, true); + IEnvironmentVariable var = new EnvironmentVariableManagerToolChain(toolChain).getVariable(ENV_PATH, true); String envPath = var != null ? var.getValue() : null; return Cygwin.isAvailable(envPath); } From 072b8512ea7ffded0f5feedab57b369f47faa8b4 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Sat, 9 Mar 2013 22:44:23 -0500 Subject: [PATCH 03/14] Bug 402807 - Partial specialization for vararg function type Change-Id: I2fa7bdede392a5b51da065d1d6196b10f2a52d6a Reviewed-on: https://git.eclipse.org/r/11025 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- .../core/parser/tests/ast2/AST2TemplateTests.java | 13 +++++++++++++ .../cpp/semantics/TemplateArgumentDeduction.java | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 7ec52522513..995369058a8 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -7195,6 +7195,19 @@ public class AST2TemplateTests extends AST2TestBase { parseAndCheckBindings(); } + // template + // struct waldo { + // typedef int type; + // }; + // + // template + // struct waldo; + // + // typedef waldo::type Type; + public void testPartialSpecializationForVarargFunctionType_402807() throws Exception { + parseAndCheckBindings(); + } + // template // struct meta { // static const bool value = 1; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java index f03403601e6..6dd0f7bb428 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java @@ -922,7 +922,7 @@ public class TemplateArgumentDeduction { private boolean fromFunctionType(ICPPFunctionType ftp, ICPPFunctionType fta, IASTNode point) throws DOMException { - if (ftp.isConst() != fta.isConst() || ftp.isVolatile() != fta.isVolatile()) + if (ftp.isConst() != fta.isConst() || ftp.isVolatile() != fta.isVolatile() || ftp.takesVarArgs() != fta.takesVarArgs()) return false; if (!fromType(ftp.getReturnType(), fta.getReturnType(), false, point)) From c8e936ae119c12ed88dbdfb6a9913aa71225d899 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Sun, 10 Mar 2013 19:52:09 -0400 Subject: [PATCH 04/14] Bug 402854 - Qualified name lookup finds name in enclosing scope Change-Id: Iebf9f427b3291a1af695936055daecb5d28e56f6 Reviewed-on: https://git.eclipse.org/r/11032 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- .../parser/tests/ast2/AST2TemplateTests.java | 30 ++++++++++++++----- .../core/parser/tests/ast2/AST2TestBase.java | 14 +++++++++ .../parser/cpp/semantics/CPPSemantics.java | 1 + 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 995369058a8..98f06da5e73 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -42,7 +42,6 @@ import org.eclipse.cdt.core.dom.ast.IASTProblemStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IBasicType; -import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.ICompositeType; import org.eclipse.cdt.core.dom.ast.IEnumerator; @@ -96,7 +95,6 @@ import org.eclipse.cdt.core.parser.util.ObjectMap; import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; @@ -5891,11 +5889,8 @@ public class AST2TemplateTests extends AST2TestBase { // auto x2 = begin2(v); public void testResolvingAutoTypeWithDependentExpression_402409a() throws Exception { BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true); - ICPPVariable x1 = helper.assertNonProblem("x1", ICPPVariable.class); - ICPPVariable x2 = helper.assertNonProblem("x2", ICPPVariable.class); - IType pointerToInt = new CPPPointerType(new CPPBasicType(Kind.eInt, 0)); - assertSameType(pointerToInt, x1.getType()); - assertSameType(pointerToInt, x2.getType()); + helper.assertVariableType("x1", CommonTypes.pointerToInt); + helper.assertVariableType("x2", CommonTypes.pointerToInt); } // struct vector { @@ -7532,4 +7527,25 @@ public class AST2TemplateTests extends AST2TestBase { public void testUnqualifiedFunctionCallInTemplate_402498() throws Exception { parseAndCheckBindings(); } + + // template + // struct no_type {}; + // + // struct type {}; + // + // template + // struct A {}; + // + // template + // int foo(T); + // + // template + // typename no_type::type const foo(A); + // + // A a; + // auto b = foo(a); + public void testQualifiedNameLookupInTemplate_402854() throws Exception { + BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true); + helper.assertVariableType("b", CommonTypes.int_); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java index 6dd95c5dce1..fa6c2a07227 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java @@ -57,6 +57,8 @@ import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; +import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; @@ -86,6 +88,8 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser; import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor; import org.eclipse.cdt.internal.core.dom.parser.c.GNUCSourceParser; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.GNUCPPSourceParser; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.model.ASTStringUtil; @@ -99,6 +103,11 @@ public class AST2TestBase extends BaseTestCase { public final static String TEST_CODE = ""; protected static final IParserLogService NULL_LOG = new NullLogService(); protected static boolean sValidateCopy; + + protected static class CommonTypes { + public static IType int_ = new CPPBasicType(Kind.eInt, 0); + public static IType pointerToInt = new CPPPointerType(int_); + } private static final ScannerInfo GNU_SCANNER_INFO = new ScannerInfo(getGnuMap()); private static final ScannerInfo SCANNER_INFO = new ScannerInfo(getStdMap()); @@ -739,6 +748,11 @@ public class AST2TestBase extends BaseTestCase { assertTrue("ProblemBinding for name: " + name, !(binding instanceof IProblemBinding)); return assertType(binding, cs); } + + public void assertVariableType(String variableName, IType expectedType) { + IVariable var = assertNonProblem(variableName, IVariable.class); + assertSameType(expectedType, var.getType()); + } public U assertType(T obj, Class... cs) { for (Class c : cs) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index d9154a68c6a..6dd5c3bab52 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -3737,6 +3737,7 @@ public class CPPSemantics { LookupData data = new LookupData(unknownName, null, point); data.setIgnorePointOfDeclaration(true); data.typesOnly= unknown instanceof IType; + data.qualified= true; try { // 2: Lookup From 0d2decffcfbbe453c6c58fb2f9cb5c0be0082589 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Sun, 10 Mar 2013 23:35:12 -0400 Subject: [PATCH 05/14] Bug 402861 - Error involving pointer-to-member of template class Change-Id: I418b5698757650f86000c31b8b7ea12e0192fcee Reviewed-on: https://git.eclipse.org/r/11034 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- .../core/parser/tests/ast2/AST2TemplateTests.java | 15 +++++++++++++++ .../dom/parser/cpp/CPPFieldSpecialization.java | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 98f06da5e73..9d6a65a6de9 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -6212,6 +6212,21 @@ public class AST2TemplateTests extends AST2TestBase { public void testPointerToMemberAsDependentExpression_391001() throws Exception { parseAndCheckBindings(getAboveComment(), CPP, true); } + + // template + // struct A { + // char x; + // }; + // + // typedef A B; + // + // template + // struct C {}; + // + // typedef C<&B::x> T; + public void testPointerToMemberOfTemplateClass_402861() throws Exception { + parseAndCheckBindings(); + } // class Memory { }; // Memory memory; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java index 39b4c496cd9..ebc64913b07 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFieldSpecialization.java @@ -44,7 +44,7 @@ public class CPPFieldSpecialization extends CPPSpecialization implements ICPPFie @Override public ICPPClassType getClassOwner() { - return getField().getClassOwner(); + return (ICPPClassType) getOwner(); } @Override From 88411d63e5e806a5dad0723877e537e9ef2cad47 Mon Sep 17 00:00:00 2001 From: Jesse Weinstein Date: Fri, 8 Mar 2013 17:59:05 -0500 Subject: [PATCH 06/14] Bug 393883 - Implement Method loses throw() Change-Id: Ic14046dd3a97f209a56704a22f7d3f2e417a69c9 Reviewed-on: https://git.eclipse.org/r/11013 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- .../ImplementMethodRefactoringTest.java | 33 +++++++++++++++++++ .../ImplementMethodRefactoring.java | 9 ++++- 2 files changed, 41 insertions(+), 1 deletion(-) mode change 100644 => 100755 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/implementmethod/ImplementMethodRefactoringTest.java mode change 100644 => 100755 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ImplementMethodRefactoring.java diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/implementmethod/ImplementMethodRefactoringTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/implementmethod/ImplementMethodRefactoringTest.java old mode 100644 new mode 100755 index 9071317e29f..9233b1798d8 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/implementmethod/ImplementMethodRefactoringTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/implementmethod/ImplementMethodRefactoringTest.java @@ -788,4 +788,37 @@ public class ImplementMethodRefactoringTest extends RefactoringTestBase { public void testExplicitConstructor_Bug363111() throws Exception { assertRefactoringSuccess(); } + + //A.h + // + //class TestClass { + //public: + // /*$*/void foo() throw ();/*$$*/ + //}; + // + + //A.cpp + //==================== + //void TestClass::foo() throw () { + //} + public void testEmptyThowsClause_Bug393833() throws Exception { + assertRefactoringSuccess(); + } + + //A.h + // + //class TestClass { + //public: + // /*$*/void foo() throw (TestClass);/*$$*/ + //}; + // + + //A.cpp + //==================== + //void TestClass::foo() throw (TestClass) { + //} + public void testNonEmptyThowsClause_Bug393833() throws Exception { + assertRefactoringSuccess(); + } + } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ImplementMethodRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ImplementMethodRefactoring.java old mode 100644 new mode 100755 index 0fef24d8eee..5385fd8fabc --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ImplementMethodRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ImplementMethodRefactoring.java @@ -38,6 +38,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; @@ -266,7 +267,13 @@ public class ImplementMethodRefactoring extends CRefactoring { for (IASTPointerOperator pop : functionDeclarator.getPointerOperators()) { createdMethodDeclarator.addPointerOperator(pop.copy(CopyStyle.withLocations)); } - + IASTTypeId[] exceptionSpecification = functionDeclarator.getExceptionSpecification(); + if (exceptionSpecification != ICPPASTFunctionDeclarator.NO_EXCEPTION_SPECIFICATION) { + createdMethodDeclarator.setEmptyExceptionSpecification(); + for (IASTTypeId typeId : exceptionSpecification) { + createdMethodDeclarator.addExceptionSpecificationTypeId(typeId == null ? null : typeId.copy(CopyStyle.withLocations)); + } + } IASTFunctionDefinition functionDefinition = nodeFactory.newFunctionDefinition(declSpecifier, createdMethodDeclarator, nodeFactory.newCompoundStatement()); functionDefinition.setParent(unit); From 8883fb1af518482b2a8ca741c62a141b89e42404 Mon Sep 17 00:00:00 2001 From: Andrew Eidsness Date: Tue, 12 Mar 2013 09:08:39 -0400 Subject: [PATCH 07/14] Bug 402177: Btree.insert returns wrong value The javadoc for BTree.insert says "don't insert if the key was already there, in which case we return the record that matched". However, the implementation was returning the new record even when it was not actually inserted. This is a fix for the problem and a test case to demonstrate the issue. Further Changes: ---------------- I have modified the code style as described in the comments in https://git.eclipse.org/r/#/c/10804. However, I'm still not sure what style is expected. I've looked through the CDT wiki a few times, especially the 'new developer' parts, but haven't found anything relevant. When I asked the question a few weeks ago, the only reply was to use the "eclipse built-in style", which I can't find in my preferences. The default seems to be "K&R Style" (that is what it is set to now, and I don't think that I would have changed it), so that is what I've used here. If I've missed the section in the wiki then a pointer would be greatly appreciated. Otherwise this topic would be a great topic for someone that knows the answers to add to the wiki. Change-Id: If079f235871fcdfbd35f1cba3f64cc3e33edaaec Reviewed-on: https://git.eclipse.org/r/10804 Reviewed-by: Doug Schaefer IP-Clean: Doug Schaefer Tested-by: Doug Schaefer --- .../cdt/internal/pdom/tests/BTreeTests.java | 40 ++++++++++++++----- .../cdt/internal/core/pdom/db/BTree.java | 4 +- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/BTreeTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/BTreeTests.java index 967720e93cb..389694a61f9 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/BTreeTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/BTreeTests.java @@ -31,7 +31,7 @@ import org.eclipse.core.runtime.CoreException; /** * Test insertion/deletion of records of a mock record type in a B-tree - * + * * @author aferguso * */ @@ -65,11 +65,11 @@ public class BTreeTests extends BaseTestCase { dbFile.deleteOnExit(); } - + public void testBySortedSetMirrorLite() throws Exception { sortedMirrorTest(8); } - + /** * Test random (but reproducible via known seed) sequences of insertions/deletions * and use TreeSet as a reference implementation to check behaviour against. @@ -103,13 +103,31 @@ public class BTreeTests extends BaseTestCase { } /** - * Insert/Delete a random number of records into/from the B-tree + * Bug 402177: BTree.insert should return the matching record if the new record was not inserted. + */ + public void testEquivalentRecordInsert_Bug402177() throws Exception { + + init(8); + try { + BTMockRecord value1 = new BTMockRecord(db, 42); + BTMockRecord value2 = new BTMockRecord(db, 42); + + long insert1 = btree.insert(value1.getRecord()); + long insert2 = btree.insert(value2.getRecord()); + assertEquals(insert1, insert2); + } finally { + finish(); + } + } + + /** + * Insert/Delete a random number of records into/from the B-tree * @param seed the seed for obtaining the deterministic random testing * @param checkCorrectnessEachIteration if true, then on every single insertion/deletion check that the B-tree invariants * still hold * @throws Exception */ - protected void trial(int seed, final boolean checkCorrectnessEachIteration) throws Exception { + protected void trial(int seed, final boolean checkCorrectnessEachIteration) throws Exception { Random random = new Random(seed); // the probabilty that a particular iterations action will be an insertion @@ -123,9 +141,9 @@ public class BTreeTests extends BaseTestCase { final int nIterations = random.nextInt(100000); final SortedSet expected = new TreeSet(); final List history = new ArrayList(); - + init(degree); - + if (DEBUG > 0) System.out.print("\t "+seed+" "+(nIterations/1000)+"K: "); for(int i=0; i Date: Tue, 12 Mar 2013 14:54:56 -0700 Subject: [PATCH 08/14] Added ArrayUtil.removeDuplicates method. --- .../cdt/core/parser/tests/ArrayUtilTest.java | 21 +++++ .../cdt/core/parser/util/ArrayUtil.java | 90 +++++++++++++------ 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ArrayUtilTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ArrayUtilTest.java index 234723a336d..cdab81aa5d8 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ArrayUtilTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ArrayUtilTest.java @@ -229,4 +229,25 @@ public class ArrayUtilTest extends TestCase { assertSame(result[0], o1); assertSame(result[1], o2); } + + public void testRemoveDuplicates() { + String[] array = { "1", "2", null, "3", "2", "1", "4", "3" }; + String[] result = ArrayUtil.removeDuplicates(array); + assertEquals(4, result.length); + assertEquals("1", result[0]); + assertEquals("2", result[1]); + assertEquals("3", result[2]); + assertEquals("4", result[3]); + + // Test a long array. + array = new String[100]; + for (int i = 0; i < array.length; i++) { + array[i] = (i + 1) % 11 == 0 ? null : String.valueOf(i % 17); + } + result = ArrayUtil.removeDuplicates(array); + assertEquals(17, result.length); + for (int i = 0; i < result.length - 1; i++) { + assertEquals(String.valueOf(i < 10 ? i : i < 16 ? i + 1 : 10), result[i]); + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java index 8c560e483a1..fb994763f44 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java @@ -18,6 +18,7 @@ import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.LinkedHashSet; import org.eclipse.core.runtime.Assert; @@ -257,13 +258,13 @@ public abstract class ArrayUtil { } /** - * Takes contents of the two arrays up to the first null element and concatenates + * Takes contents of the two arrays up to the first {@code null} element and concatenates * them. * @param c The type of the element of the returned array if there was not enough free space * in the destination array. * @param dest The destination array. The elements of the source array are added to this array - * if there is enough free space in it. May be null. - * @param source The source array. May not be null. + * if there is enough free space in it. May be {@code null}. + * @param source The source array. May not be {@code null}. * @return The concatenated array, which may be the same as the first parameter. */ @SuppressWarnings("unchecked") @@ -300,11 +301,11 @@ public abstract class ArrayUtil { } /** - * Takes contents of the two arrays up to the first null element and concatenates + * Takes contents of the two arrays up to the first {@code null} element and concatenates * them. * @param dest The destination array. The elements of the source array are added to this array - * if there is enough free space in it. May be null. - * @param source The source array. May not be null. + * if there is enough free space in it. May be {@code null}. + * @param source The source array. May not be {@code null}. * @return The concatenated array, which may be the same as the first parameter. * @since 5.2 */ @@ -362,7 +363,7 @@ public abstract class ArrayUtil { * @param array the array to search * @param obj the object to search for * @return true if the specified array contains the specified object, or - * the specified array is null + * the specified array is {@code null} */ public static boolean contains(T[] array, T obj) { return indexOf(array, obj) >= 0; @@ -374,7 +375,7 @@ public abstract class ArrayUtil { * @param array the array to search * @param obj the object to search for * @return the index into the specified array of the specified object, or -1 if the array does - * not contain the object, or if the array is null + * not contain the object, or if the array is {@code null} */ public static int indexOf(T[] array, T obj) { int result = -1; @@ -391,10 +392,11 @@ public abstract class ArrayUtil { * Assumes that array contains nulls at the end, only. * Returns whether the specified array contains the specified object. Comparison is by * object identity. + * * @param array the array to search * @param obj the object to search for * @return true if the specified array contains the specified object, or the specified array is - * null + * {@code null} */ public static boolean containsEqual(T[] array, T obj) { return indexOfEqual(array, obj) != -1; @@ -404,16 +406,17 @@ public abstract class ArrayUtil { * Assumes that array contains nulls at the end, only. * Returns the index into the specified array of the specified object, or -1 if the array does * not contain the object, or if the array is null. Comparison is by equals(). - * @param comments the array to search - * @param comment the object to search for + * + * @param array the array to search + * @param obj the object to search for * @return the index into the specified array of the specified object, or -1 if the array does - * not contain an equal object, or if the array is null + * not contain an equal object, or if the array is {@code null} */ - public static int indexOfEqual(T[] comments, T comment) { + public static int indexOfEqual(T[] array, T obj) { int result = -1; - if (comments != null) { - for (int i= 0; (i < comments.length) && (comments[i] != null); i++) { - if (comments[i].equals(comment)) + if (array != null) { + for (int i= 0; (i < array.length) && (array[i] != null); i++) { + if (array[i].equals(obj)) return i; } } @@ -566,7 +569,7 @@ public abstract class ArrayUtil { /** * Inserts the obj at the beginning of the array, shifting the whole thing one index * Assumes that array contains nulls at the end, only. - * array must not be null. + * array must not be {@code null}. * @since 5.2 */ public static T[] prepend(T[] array, T obj) { @@ -660,26 +663,63 @@ public abstract class ArrayUtil { } /** - * Returns a new array that contains all of the elements of the - * given array except the first one. + * Returns a new array that contains all of the elements of the given array except + * the first one. * + * @throws NullPointerException if {@code array} is {@code null} + * @throws IllegalArgumentException if {@code array} is empty * @since 5.1 - * @throws NullPointerException if args is null - * @throws IllegalArgumentException if args.length <= 0 */ @SuppressWarnings("unchecked") - public static T[] removeFirst(T[] args) { - int n = args.length; + public static T[] removeFirst(T[] array) { + int n = array.length; if (n <= 0) throw new IllegalArgumentException(); - T[] newArgs = (T[]) Array.newInstance(args.getClass().getComponentType(), n - 1); + T[] newArgs = (T[]) Array.newInstance(array.getClass().getComponentType(), n - 1); for (int i = 1; i < n; i++) { - newArgs[i - 1] = args[i]; + newArgs[i - 1] = array[i]; } return newArgs; } + /** + * Returns a new array that contains elements of the given array except duplicates and + * {@code null}s. Duplicates are determined by {@link Object#equals(Object)} method. + * + * @throws NullPointerException if {@code array} is {@code null} + * @since 5.5 + */ + @SuppressWarnings("unchecked") + public static T[] removeDuplicates(T[] array) { + if (array.length >= 16) { + LinkedHashSet set = new LinkedHashSet(array.length); + for (int i = 0; i < array.length; i++) { + T obj = array[i]; + if (obj != null) + set.add(obj); + } + if (set.size() == array.length) + return array; + return set.toArray((T[]) Array.newInstance(array.getClass().getComponentType(), set.size())); + } else { + int k = 0; + for (int i = 0; i < array.length; i++) { + T obj = array[i]; + if (obj != null) { + array[k++] = obj; + for (int j = i + 1; j < array.length; j++) { + if (obj.equals(array[j])) + array[j] = null; + } + } + } + if (k == array.length) + return array; + return Arrays.copyOf(array, k); + } + } + public static int[] setInt(int[] array, int idx, int val) { if (array == null) { array = new int[DEFAULT_LENGTH > idx + 1 ? DEFAULT_LENGTH : idx + 1]; From 4d120934328af8d3e736c824ceb929f6549fd245 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Tue, 12 Mar 2013 14:57:34 -0700 Subject: [PATCH 09/14] Fixed a typo. --- .../core/settings/model/util/SettingsSet.java | 197 +++++++++--------- 1 file changed, 95 insertions(+), 102 deletions(-) diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/SettingsSet.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/SettingsSet.java index 3fc7634eb0c..a8b2593bf1c 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/SettingsSet.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/SettingsSet.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Intel Corporation - Initial API and implementation + * Intel Corporation - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.core.settings.model.util; @@ -27,6 +27,7 @@ public class SettingsSet { public static final int WRITABLE = 1 << 1; private SettingLevel[] fLevels; + public class SettingLevel { private int fFlagsToSet; private int fFlagsToClear; @@ -36,149 +37,149 @@ public class SettingsSet { HashSet fOverrideSet; private Object fContext; - private SettingLevel(){ + private SettingLevel() { fEntries = new LinkedHashMap(); } - public boolean isReadOnly(){ + public boolean isReadOnly() { return fIsReadOnly; } - public void setReadOnly(boolean readOnly){ + public void setReadOnly(boolean readOnly) { fIsReadOnly = readOnly; } - public boolean isOverrideSupported(){ + public boolean isOverrideSupported() { return fIsOverrideSupported; } - public void setOverrideSupported(boolean supported){ + public void setOverrideSupported(boolean supported) { fIsOverrideSupported = supported; } - public void setFlagsToSet(int flags){ + public void setFlagsToSet(int flags) { fFlagsToSet = flags; } - public boolean containsOverrideInfo(){ + public boolean containsOverrideInfo() { return fOverrideSet != null; } - public void setFlagsToClear(int flags){ + public void setFlagsToClear(int flags) { fFlagsToClear = flags; } - public int getFlagsToSet(){ + public int getFlagsToSet() { return fFlagsToSet; } - public int getFlagsToClear(){ + public int getFlagsToClear() { return fFlagsToClear; } - public int getFlags(int baseFlags){ + public int getFlags(int baseFlags) { return (baseFlags | fFlagsToSet) & (~fFlagsToClear); } @SuppressWarnings("unchecked") - public Set getOverrideSet(){ - if(fOverrideSet != null) + public Set getOverrideSet() { + if (fOverrideSet != null) return (HashSet)fOverrideSet.clone(); return new HashSet(); } - public void addEntries(ICLanguageSettingEntry entries[]){ - if(entries != null){ - for(int i = 0; i < entries.length; i++){ + public void addEntries(ICLanguageSettingEntry entries[]) { + if (entries != null) { + for (int i = 0; i < entries.length; i++) { addEntry(entries[i]); } } } - public void addEntries(List list){ - for(ICLanguageSettingEntry se : list) + public void addEntries(List list) { + for (ICLanguageSettingEntry se : list) addEntry(se); } - public void addEntry(ICLanguageSettingEntry entry){ + public void addEntry(ICLanguageSettingEntry entry) { addEntry(entry, null); } - public void addEntry(ICLanguageSettingEntry entry, Object customInfo){ + public void addEntry(ICLanguageSettingEntry entry, Object customInfo) { entry = CDataUtil.createEntry(entry, fFlagsToSet, fFlagsToClear); EntryInfo info = new EntryInfo(entry, customInfo); fEntries.put(info.getContentsKey(), info); } - public void addOverrideName(String name){ - if(fOverrideSet == null) + public void addOverrideName(String name) { + if (fOverrideSet == null) fOverrideSet = new HashSet(); fOverrideSet.add(name); } - public void addOverrideNameSet(Set set){ - if(set == null) + public void addOverrideNameSet(Set set) { + if (set == null) return; - if(fOverrideSet != null){ + if (fOverrideSet != null) { fOverrideSet.addAll(set); - } else if(set.size() != 0){ + } else if (set.size() != 0) { fOverrideSet = new HashSet(set); } } - public void removeOverrideName(String name){ - if(fOverrideSet == null) + public void removeOverrideName(String name) { + if (fOverrideSet == null) return; fOverrideSet.remove(name); - if(fOverrideSet.size() == 0) + if (fOverrideSet.size() == 0) fOverrideSet = null; } - public void clear(){ + public void clear() { fEntries.clear(); fOverrideSet = null; } - public Map clearAndGetMap(){ + public Map clearAndGetMap() { Map map = fEntries; fEntries = new LinkedHashMap(); fOverrideSet = null; return map; } - public EntryInfo[] getInfos(){ + public EntryInfo[] getInfos() { return fEntries.values().toArray(new EntryInfo[fEntries.size()]); } - public ICLanguageSettingEntry[] getEntries(){ + public ICLanguageSettingEntry[] getEntries() { List list = getEntriesList(false); return list.toArray(new ICLanguageSettingEntry[list.size()]); } - public ICLanguageSettingEntry[] getEntries(boolean includeOverridden){ + public ICLanguageSettingEntry[] getEntries(boolean includeOverridden) { List list = getEntriesList(includeOverridden); return list.toArray(new ICLanguageSettingEntry[list.size()]); } - public List getEntriesList(boolean includeOverridden){ + public List getEntriesList(boolean includeOverridden) { List list = new ArrayList(); EntryInfo infos[] = getInfos(); - for(EntryInfo info : infos){ - if(includeOverridden || !info.isOverridden()) + for (EntryInfo info : infos) { + if (includeOverridden || !info.isOverridden()) list.add(info.getEntry()); } return list; } - public Object getContext(){ + public Object getContext() { return fContext; } - public void setContext(Object context){ + public void setContext(Object context) { fContext = context; } } @@ -189,60 +190,60 @@ public class SettingsSet { private boolean fIsOverRidden; private Object fCustomInfo; - private EntryInfo(ICLanguageSettingEntry entry, Object customInfo){ + private EntryInfo(ICLanguageSettingEntry entry, Object customInfo) { fEntry = entry; fCustomInfo = customInfo; } - public EntryNameKey getContentsKey(){ - if(fNameKey == null){ + public EntryNameKey getContentsKey() { + if (fNameKey == null) { fNameKey = new EntryNameKey(fEntry); } return fNameKey; } - private void makeOverridden(boolean overrridden){ - fIsOverRidden = overrridden; + private void makeOverridden(boolean overridden) { + fIsOverRidden = overridden; } - public ICLanguageSettingEntry getEntry(){ + public ICLanguageSettingEntry getEntry() { return fEntry; } - public boolean isOverridden(){ + public boolean isOverridden() { return fIsOverRidden; } - public Object getCustomInfo(){ + public Object getCustomInfo() { return fCustomInfo; } } - public SettingsSet(int num){ + public SettingsSet(int num) { fLevels = new SettingLevel[num]; - for(int i = 0; i < num; i++){ + for (int i = 0; i < num; i++) { fLevels[i] = new SettingLevel(); } } - public SettingLevel[] getLevels(){ + public SettingLevel[] getLevels() { return fLevels.clone(); } - public void adjustOverrideState(){ + public void adjustOverrideState() { Set set = new HashSet(); SettingLevel level; - for(int i = 0; i < fLevels.length; i++){ + for (int i = 0; i < fLevels.length; i++) { level = fLevels[i]; - if(level.isOverrideSupported() && level.fOverrideSet != null) + if (level.isOverrideSupported() && level.fOverrideSet != null) set.addAll(level.fOverrideSet); adjustOverrideState(fLevels[i], set); } } - private void adjustOverrideState(SettingLevel level, Set overridenSet){ - for(EntryInfo info : level.getInfos()){ - if(overridenSet.add(info.getEntry().getName())){ + private void adjustOverrideState(SettingLevel level, Set overridenSet) { + for (EntryInfo info : level.getInfos()) { + if (overridenSet.add(info.getEntry().getName())) { info.makeOverridden(false); } else { info.makeOverridden(true); @@ -250,47 +251,47 @@ public class SettingsSet { } } - public ICLanguageSettingEntry[] getEntries(){ + public ICLanguageSettingEntry[] getEntries() { return getEntries(READ_ONLY | WRITABLE); } - public ICLanguageSettingEntry[] getEntries(int types){ + public ICLanguageSettingEntry[] getEntries(int types) { adjustOverrideState(); List entries = new ArrayList(); - for(SettingLevel sl : fLevels){ - if(isCompatible(sl, types)) + for (SettingLevel sl : fLevels) { + if (isCompatible(sl, types)) getEntries(sl, entries); } return entries.toArray(new ICLanguageSettingEntry[entries.size()]); } - private void getEntries(SettingLevel level, List list){ - for(EntryInfo info : level.getInfos()) - if(!info.isOverridden()) + private void getEntries(SettingLevel level, List list) { + for (EntryInfo info : level.getInfos()) + if (!info.isOverridden()) list.add(info.getEntry()); } - private boolean isCompatible(SettingLevel level, int types){ - if((types & READ_ONLY) == 0 && level.isReadOnly()) + private boolean isCompatible(SettingLevel level, int types) { + if ((types & READ_ONLY) == 0 && level.isReadOnly()) return false; - if((types & WRITABLE) == 0 && !level.isReadOnly()) + if ((types & WRITABLE) == 0 && !level.isReadOnly()) return false; return true; } - private int getWritableLevelNum(){ - for(int i = 0; i map = getEntryLevelMap(WRITABLE | READ_ONLY); Map mapCopy = (HashMap)map.clone(); Map[] clearedInfos = new Map [fLevels.length]; - for(int i = 0; i < fLevels.length; i++){ - if(!fLevels[i].isReadOnly()) + for (int i = 0; i < fLevels.length; i++) { + if (!fLevels[i].isReadOnly()) clearedInfos[i] = fLevels[i].clearAndGetMap(); } @@ -314,13 +315,13 @@ public class SettingsSet { int writableLevel = getWritableLevelNum(); SettingLevel level; - for(int i = 0; i < entries.length; i++){ + for (int i = 0; i < entries.length; i++) { entry = entries[i]; EntryNameKey key = new EntryNameKey(entry); Object[] o = map.get(key); - if(o != null && valueMatches(entry, o[1])){ + if (o != null && valueMatches(entry, o[1])) { mapCopy.remove(key); levelInteger = (Integer)o[0]; if (! entry.isBuiltIn()) // allow overwrite existing entry, @@ -330,14 +331,14 @@ public class SettingsSet { } levelNum = levelInteger != null ? levelInteger.intValue() : writableLevel; - if(levelNum >= 0){ + if (levelNum >= 0) { level = fLevels[levelNum]; - if(!level.isReadOnly()){ + if (!level.isReadOnly()) { Map clearedInfo = clearedInfos[levelNum]; Object customInfo = null; - if(clearedInfo != null){ + if (clearedInfo != null) { EntryInfo info = clearedInfo.get(key); - if(info != null && entry.equalsByContents(info.getEntry())) + if (info != null && entry.equalsByContents(info.getEntry())) customInfo = info.getCustomInfo(); } level.addEntry(entry, customInfo); @@ -346,15 +347,15 @@ public class SettingsSet { } int overrideLevel = getOverrideLevelNum(); - if(overrideLevel >= 0){ + if (overrideLevel >= 0) { level = fLevels[overrideLevel]; - if(level.isOverrideSupported() && !mapCopy.isEmpty()){ - for(EntryNameKey enk : mapCopy.keySet()){ + if (level.isOverrideSupported() && !mapCopy.isEmpty()) { + for (EntryNameKey enk : mapCopy.keySet()) { ICSettingEntry e = enk.getEntry(); if ((e.getFlags() & ICSettingEntry.BUILTIN) == 0) continue; String str = e.getName(); - if(str != null) + if (str != null) level.addOverrideName(str); } } @@ -362,19 +363,19 @@ public class SettingsSet { adjustOverrideState(); } - public HashMap getEntryLevelMap(int types){ + public HashMap getEntryLevelMap(int types) { HashMap map = new HashMap(); - for(int i = 0; i < fLevels.length; i++){ - if(isCompatible(fLevels[i], types)) + for (int i = 0; i < fLevels.length; i++) { + if (isCompatible(fLevels[i], types)) addLevelInfoToMap(fLevels[i], i, map); } return map; } - private void addLevelInfoToMap(SettingLevel level, int l, Map map){ - for(EntryInfo info : level.getInfos()){ + private void addLevelInfoToMap(SettingLevel level, int l, Map map) { + for (EntryInfo info : level.getInfos()) { EntryNameKey key = info.getContentsKey(); - if(!map.containsKey(key)) + if (!map.containsKey(key)) map.put(key, new Object[]{new Integer(l), info.getEntry()}); } } @@ -385,15 +386,7 @@ public class SettingsSet { if (!(o instanceof ICMacroEntry)) return false; // cannot compare different entries String s1 = e.getValue(); - String s2 = ((ICMacroEntry)o).getValue(); - if (s1 == null && s2 == null) - return true; - if (s1 != null) - return s1.equals(s2); - else - return s2.equals(s1); + String s2 = ((ICMacroEntry) o).getValue(); + return s1 == null ? s2 == null : s1.equals(s2); } - - - } From e063f00b674db979d5e634a9dda4f631b3c0614b Mon Sep 17 00:00:00 2001 From: Jesse Weinstein Date: Mon, 11 Mar 2013 16:36:31 -0400 Subject: [PATCH 10/14] Bug 240692 -- Fix rename for templates Just a failing test, so far. Change-Id: Idb923862614ff2f1b7736495d8a2d8967e278de7 Reviewed-on: https://git.eclipse.org/r/11064 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- .../rename/RenameTemplatesTests.java | 102 +++++++++++------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTemplatesTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTemplatesTests.java index 1adde370a20..fa30925b358 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTemplatesTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameTemplatesTests.java @@ -24,44 +24,70 @@ import org.eclipse.ltk.core.refactoring.RefactoringStatus; */ public class RenameTemplatesTests extends RenameTests { - public RenameTemplatesTests(String name) { - super(name); - } + public RenameTemplatesTests(String name) { + super(name); + } - public static Test suite(){ - return suite(true); - } + public static Test suite() { + return suite(true); + } - public static Test suite( boolean cleanup ) { - TestSuite suite = new TestSuite(RenameTemplatesTests.class); - if (cleanup) { - suite.addTest( new RefactoringTests("cleanupProject") ); //$NON-NLS-1$ - } - return suite; - } - - public void testClassTemplate() throws Exception { - StringWriter writer = new StringWriter(); - writer.write("template \n"); //$NON-NLS-1$ - writer.write("class Array { \n"); //$NON-NLS-1$ - writer.write("public: \n"); //$NON-NLS-1$ - writer.write(" Array(unsigned sz) {} \n"); //$NON-NLS-1$ - writer.write(" ~Array(){} \n"); //$NON-NLS-1$ - writer.write(" Type& operator[] (unsigned idx); \n"); //$NON-NLS-1$ - writer.write("}; \n"); //$NON-NLS-1$ - writer.write("template \n"); //$NON-NLS-1$ - writer.write("inline Type& Array::operator[] (unsigned index) {\n"); //$NON-NLS-1$ - writer.write(" return 1; \n"); //$NON-NLS-1$ - writer.write("}; \n"); //$NON-NLS-1$ - String contents = writer.toString(); - IFile cpp= importFile("test.cpp", contents ); //$NON-NLS-1$ - - int offset1= contents.indexOf("Array"); //$NON-NLS-1$ - - RefactoringStatus stat= checkConditions(cpp, offset1, "WELT"); //$NON-NLS-1$ - assertRefactoringOk(stat); - - Change ch= getRefactorChanges(cpp, offset1, "WELT"); //$NON-NLS-1$ - assertTotalChanges(4, ch); - } + public static Test suite(boolean cleanup) { + TestSuite suite = new TestSuite(RenameTemplatesTests.class); + if (cleanup) { + suite.addTest(new RefactoringTests("cleanupProject")); + } + return suite; + } + + public void testClassTemplate() throws Exception { + StringWriter writer = new StringWriter(); + writer.write("template \n"); + writer.write("class Array { \n"); + writer.write("public: \n"); + writer.write(" Array(unsigned sz) {} \n"); + writer.write(" ~Array(){} \n"); + writer.write(" Type& operator[] (unsigned idx); \n"); + writer.write("}; \n"); + writer.write("template \n"); + writer.write("inline Type& Array::operator[] (unsigned index) {\n"); + writer.write(" return 1; \n"); + writer.write("}; \n"); + String contents = writer.toString(); + IFile cpp = importFile("test.cpp", contents); + + int offset1 = contents.indexOf("Array"); + + RefactoringStatus stat = checkConditions(cpp, offset1, "WELT"); + assertRefactoringOk(stat); + + Change ch = getRefactorChanges(cpp, offset1, "WELT"); + assertTotalChanges(4, ch); + } + + public void _testRenameSpecializations_bug240692() throws Exception { + StringWriter writer = new StringWriter(); + + writer.write("template \n"); + writer.write("class CSome {\n"); + writer.write("public:\n"); + writer.write(" void Foo() {};\n"); + writer.write("};\n"); + + writer.write("int main ()\n"); + writer.write("{\n"); + writer.write(" CSome A;\n"); + writer.write(" A.Foo();\n"); + writer.write(" return 0;\n"); + writer.write("}\n"); + String contents = writer.toString(); + IFile cpp = importFile("test.cpp", contents); + + int offset1 = contents.indexOf("Foo"); + + RefactoringStatus stat = checkConditions(cpp, offset1, "Baz"); + assertRefactoringOk(stat); + + assertTotalChanges(2, getRefactorChanges(cpp, offset1, "Baz")); + } } From 6c4ec01412eece78ce0d324753de2d3c93140d47 Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Tue, 12 Mar 2013 15:47:34 -0700 Subject: [PATCH 11/14] Code streamlining. --- .../cdt/core/parser/util/ArrayUtil.java | 126 +++++++++--------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java index fb994763f44..96860d9c8aa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java @@ -18,7 +18,7 @@ import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.LinkedHashSet; +import java.util.HashSet; import org.eclipse.core.runtime.Assert; @@ -29,9 +29,9 @@ public abstract class ArrayUtil { private static final int DEFAULT_LENGTH = 2; /** - * Assumes that array contains nulls at the end, only. - * Appends element after the last non-null element. - * If the array is null or not large enough, a larger one is allocated, using + * Assumes that array contains {@code null}s at the end, only. + * Appends element after the last non-{@code null} element. + * If the array is {@code null} or not large enough, a larger one is allocated, using * the given class object. */ @SuppressWarnings("unchecked") @@ -57,8 +57,8 @@ public abstract class ArrayUtil { } /** - * Assumes that array contains nulls at the end, only. - * Appends element after the last non-null element. + * Assumes that array contains {@code null}s at the end, only. + * Appends element after the last non-{@code null} element. * If the array is not large enough, a larger one is allocated. * Null array is supported for backward compatibility only and only when T is * Object. @@ -88,8 +88,8 @@ public abstract class ArrayUtil { } /** - * Assumes that array contains nulls at the end, only. - * @returns index of first null, or -1 + * Assumes that array contains {@code null}s at the end, only. + * @returns index of first {@code null}, or -1 */ private static int findFirstNull(Object[] array) { boolean haveNull= false; @@ -118,7 +118,7 @@ public abstract class ArrayUtil { } /** - * Assumes that array contains nulls at the end, only. + * Assumes that array contains {@code null}s at the end, only. * Appends object using the current length of the array. * @since 5.1 */ @@ -146,7 +146,7 @@ public abstract class ArrayUtil { } /** - * Assumes that array contains nulls at the end, only. + * Assumes that array contains {@code null}s at the end, only. * Appends object using the current length of the array. * @param array The array to append to. Not {@code null} * @param currentLength The number of non-{@code null} elements in the array @@ -167,12 +167,12 @@ public abstract class ArrayUtil { } /** - * Trims the given array and returns a new array with no null entries. - * Assumes that nulls can be found at the end, only. - * if array == null, a new array of length 0 is returned - * if forceNew == true, a new array will always be created. - * if forceNew == false, a new array will only be created if the original array - * contained null entries. + * Trims the given array and returns a new array with no {@code null} entries. + * Assumes that {@code null}s can be found at the end, only. + * if {@code array} is {@code null}, a new array of length 0 is returned + * if {@code forceNew} is {@code true}, a new array will always be created. + * if {@code forceNew} is {@code false}, a new array will only be created if the original array + * contained {@code null} entries. * * @param c the type of the new array * @param array the array to be trimmed @@ -203,11 +203,11 @@ public abstract class ArrayUtil { } /** - * Trims the given array and returns a new array with no null entries. - * Assumes that nulls can be found at the end, only. - * if forceNew == true, a new array will always be created. - * if forceNew == false, a new array will only be created if the original array - * contained null entries. + * Trims the given array and returns a new array with no {@code null} entries. + * Assumes that {@code null}s can be found at the end, only. + * if {@code forceNew} is {@code true}, a new array will always be created. + * if {@code forceNew} is {@code false}, a new array will only be created if the original array + * contained {@code null} entries. * * @param array the array to be trimmed * @param forceNew @@ -228,8 +228,8 @@ public abstract class ArrayUtil { } /** - * Trims the given array and returns a new array with no null entries. - * Assumes that nulls can be found at the end, only. + * Trims the given array and returns a new array with no {@code null} entries. + * Assumes that {@code null}s can be found at the end, only. * * @param array the array to be trimmed * @since 5.2 @@ -301,8 +301,8 @@ public abstract class ArrayUtil { } /** - * Takes contents of the two arrays up to the first {@code null} element and concatenates - * them. + * Takes contents of the two arrays up to the first {@code null} element and concatenates them. + * * @param dest The destination array. The elements of the source array are added to this array * if there is enough free space in it. May be {@code null}. * @param source The source array. May not be {@code null}. @@ -360,6 +360,7 @@ public abstract class ArrayUtil { /** * Returns whether the specified array contains the specified object. Comparison is by * object identity. + * * @param array the array to search * @param obj the object to search for * @return true if the specified array contains the specified object, or @@ -371,7 +372,8 @@ public abstract class ArrayUtil { /** * Returns the index into the specified array of the specified object, or -1 if the array does - * not contain the object, or if the array is null. Comparison is by object identity. + * not contain the object, or if the array is {@code null}. Comparison is by object identity. + * * @param array the array to search * @param obj the object to search for * @return the index into the specified array of the specified object, or -1 if the array does @@ -389,7 +391,7 @@ public abstract class ArrayUtil { } /** - * Assumes that array contains nulls at the end, only. + * Assumes that array contains {@code null}s at the end, only. * Returns whether the specified array contains the specified object. Comparison is by * object identity. * @@ -403,9 +405,9 @@ public abstract class ArrayUtil { } /** - * Assumes that array contains nulls at the end, only. + * Assumes that array contains {@code null}s at the end, only. * Returns the index into the specified array of the specified object, or -1 if the array does - * not contain the object, or if the array is null. Comparison is by equals(). + * not contain the object, or if the array is {@code null}. Comparison is by equals(). * * @param array the array to search * @param obj the object to search for @@ -424,7 +426,9 @@ public abstract class ArrayUtil { } /** - * Moves all null elements to the end of the array. The order of non-null elements is preserved. + * Moves all {@code null} elements to the end of the array. The order of non-{@code null} + * elements is preserved. + * * @since 5.4 */ public static void compact(Object[] array) { @@ -441,13 +445,13 @@ public abstract class ArrayUtil { } /** - * Removes all of the nulls from the array and returns a new array that contains all - * of the non-null elements. + * Removes all of the {@code null}s from the array and returns a new array that contains all + * of the non-{@code null} elements. * - * If there are no nulls in the original array then the original array is returned. + * If there are no {@code null}s in the original array then the original array is returned. - * Note that this method should only be used when the placement of nulls within the array - * is unknown (due to performance efficiency). + * Note that this method should only be used when the placement of {@code null}s within + * the array is unknown (due to performance efficiency). */ @SuppressWarnings("unchecked") public static T[] removeNulls(Class c, T[] array) { @@ -475,13 +479,13 @@ public abstract class ArrayUtil { } /** - * Removes all of the nulls from the array and returns a new array that contains all - * of the non-null elements. - * - * If there are no nulls in the original array then the original array is returned. - * - * Note that this method should only be used when the placement of nulls within the array - * is unknown (due to performance efficiency). + * Removes all of the {@code null}s from the array and returns a new array that contains all + * of the non-{@code null} elements. + *

+ * If there are no {@code null}s in the original array then the original array is returned. + *

+ * Note that this method should only be used when the placement of {@code null}s within + * the array is unknown (due to performance efficiency). * @since 5.2 */ @SuppressWarnings("unchecked") @@ -517,11 +521,11 @@ public abstract class ArrayUtil { /** * To improve performance, this method should be used instead of * {@link #removeNulls(Class, Object[])} when all of the non-{@code null} elements in - * the array are grouped together at the beginning of the array and all of the nulls are at - * the end of the array. The position of the last non-{@code null} element in the array must also - * be known. + * the array are grouped together at the beginning of the array and all of the s are at + * the end of the array. The position of the last non-{@code null} element in the array must + * also be known. *

- * If you don't indend to pass {@code null} array, consider using {@link #trim(Object[], int)} + * If you don't intend to pass {@code null} array, consider using {@link #trim(Object[], int)} * instead. * * @since 5.1 @@ -539,8 +543,8 @@ public abstract class ArrayUtil { } /** - * Inserts the obj at the beginning of the array, shifting the whole thing one index - * Assumes that array contains nulls at the end, only. + * Inserts the {@code obj} at the beginning of the array, shifting the whole thing one index + * Assumes that array contains {@code null}s at the end, only. */ @SuppressWarnings("unchecked") public static T[] prepend(Class c, T[] array, T obj) { @@ -567,8 +571,8 @@ public abstract class ArrayUtil { } /** - * Inserts the obj at the beginning of the array, shifting the whole thing one index - * Assumes that array contains nulls at the end, only. + * Inserts the {@code obj} at the beginning of the array, shifting the whole thing one index + * Assumes that array contains {@code null}s at the end, only. * array must not be {@code null}. * @since 5.2 */ @@ -624,7 +628,7 @@ public abstract class ArrayUtil { * @param target the runtime type of the new array * @param source the source array * @return the current array stored in a new array with the specified runtime type, - * or null if source is null. + * or {@code null} if source is {@code null}. */ @SuppressWarnings("unchecked") public static T[] convert(Class target, S[] source) { @@ -649,6 +653,7 @@ public abstract class ArrayUtil { /** * Reverses order of elements in a subsection of an array. + * * @param array the array * @param fromIndex the index of the first affected element (inclusive) * @param toIndex the index of the last affected element (exclusive) @@ -690,20 +695,17 @@ public abstract class ArrayUtil { * @throws NullPointerException if {@code array} is {@code null} * @since 5.5 */ - @SuppressWarnings("unchecked") public static T[] removeDuplicates(T[] array) { + int k = 0; if (array.length >= 16) { - LinkedHashSet set = new LinkedHashSet(array.length); + HashSet set = new HashSet(array.length); for (int i = 0; i < array.length; i++) { T obj = array[i]; - if (obj != null) - set.add(obj); + if (obj != null && set.add(obj)) { + array[k++] = obj; + } } - if (set.size() == array.length) - return array; - return set.toArray((T[]) Array.newInstance(array.getClass().getComponentType(), set.size())); } else { - int k = 0; for (int i = 0; i < array.length; i++) { T obj = array[i]; if (obj != null) { @@ -714,10 +716,10 @@ public abstract class ArrayUtil { } } } - if (k == array.length) - return array; - return Arrays.copyOf(array, k); } + if (k == array.length) + return array; + return Arrays.copyOf(array, k); } public static int[] setInt(int[] array, int idx, int val) { From 032f17d5f5eba9784f91ade6b349d625998ae044 Mon Sep 17 00:00:00 2001 From: Jesse Weinstein Date: Tue, 12 Mar 2013 18:20:55 -0400 Subject: [PATCH 12/14] Bug 402071: Update Window menu Change-Id: I9bc4ed774a9f9c261c2c5d87e0ad14f5b4ece00c Reviewed-on: https://git.eclipse.org/r/11095 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- .../images/cdt_menu_window.png | Bin 60974 -> 26947 bytes .../reference/cdt_u_m_window.htm | 324 ++++++++++++------ 2 files changed, 218 insertions(+), 106 deletions(-) diff --git a/doc/org.eclipse.cdt.doc.user/images/cdt_menu_window.png b/doc/org.eclipse.cdt.doc.user/images/cdt_menu_window.png index aafdd4c29b72986262cd4adf9ec12d014218aa77..7be777288498b3ce67a047be285fa6d503f4c090 100644 GIT binary patch literal 26947 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 v02cs(4uJVO2o%&v4m$+`iuJz`ij6 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�^m=xG#bQsAc!F1;JLBbL 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 S6rDi8M_pM*sb0Z0@_zvh_%LJu diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_m_window.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_m_window.htm index eb02caa34f3..66ed08dbd34 100755 --- a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_m_window.htm +++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_m_window.htm @@ -1,122 +1,234 @@ - + - - + Window Menu actions -

Window Menu actions

+
+

Window Menu actions

+

+ Selecting Window Menu +

+ + + + + + + + + + + + + + -

Window Menu

-

-

- + + + + + - - - - - + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - -

- -

-IBM Copyright Statement -

- - - \ No newline at end of file + + +
+
Next Editor
+
Activates the most-recently-used editor (If held down, + displays the list of open editors, ordered by time.)
+
+ + Ctrl+F6 + + + +
+
Previous Editor
+
Activates least-recently-used editor (If held down, + displays the list of open editors, ordered by time.)
+
+ + Ctrl+Shift+F6 + + + +
+
Switch to Editor...
+
Displays a dialog that allows multiple editors to be + saved or closed
+
+ + Ctrl+Shift+E + + + +
+
Next View
+
Activates the most-recently-used view (If held down, + displays the list of open views, ordered by time.)
+
+ + Ctrl+F7 + + + +
+
Previous View
+
Activates least-recently-used view (If held down, + displays the list of open views, ordered by time.)
+
+ + Ctrl+Shift+F7 + + + +
+
Next Perspective
+
Activates the most-recently-used perspective (If held + down, displays the list of open perspectives, ordered by time.)
+
+ + Ctrl+F8 + + + +
+
Previous Perspective
+
Activates least-recently-used perspective (If held down, + displays the list of open perspective, ordered by time.)
+
+ + Ctrl+Shift+F8 + + + Preferences + Opens the Preferences dialog, where + workspace-wide preferences can be set (The
C/C++ Page Preference Window section + documents the C/C++-specific preferences.) + +   + + + +

+ IBM Copyright Statement +

+
+ + From bbea2db0b4c872b826bd04202b01f875636e0ac5 Mon Sep 17 00:00:00 2001 From: Jesse Weinstein Date: Tue, 12 Mar 2013 20:51:53 -0400 Subject: [PATCH 13/14] Bug 402071: Add link to Workbench Help menu docs Change-Id: I68d8e374d39321deed6ef426b211a3cc81063dae Reviewed-on: https://git.eclipse.org/r/11097 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- doc/org.eclipse.cdt.doc.user/reference/cdt_o_menu.htm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_o_menu.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_o_menu.htm index 06217f65a24..1afd5a0f200 100755 --- a/doc/org.eclipse.cdt.doc.user/reference/cdt_o_menu.htm +++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_o_menu.htm @@ -12,9 +12,9 @@

C/C++ Menubar

This section describes the menubar options available from the C/C++ perspective.

+alt="C/C++ perspective main menu">

- + File Menu actions
Edit Menu actions
@@ -32,6 +32,8 @@ alt="CDT main menu"> Run Menu actions
Window Menu actions
+ +Help Menu actions (from Workbench User Guide)

IBM Copyright Statement

From 62eeab5ef647d55f266aae91e108b5b7cc5a06b9 Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Thu, 21 Feb 2013 14:14:46 -0500 Subject: [PATCH 14/14] bug 382423: Add Builtin Compiler Settings LSP provider for Cygwin toolchain --- .../tests/BuiltinSpecsDetectorTest.java | 5 +- .../tests/GCCBuiltinSpecsDetectorTest.java | 100 ++++++++++++++++++ .../plugin.xml | 8 ++ .../GCCBuiltinSpecsDetectorCygwin.java | 82 ++++++++++++++ .../AbstractBuiltinSpecsDetector.java | 97 ++++++++++++++--- ...AbstractLanguageSettingsOutputScanner.java | 71 ++++++++++--- .../ToolchainBuiltinSpecsDetector.java | 26 ++--- .../plugin.xml | 1 + 8 files changed, 343 insertions(+), 47 deletions(-) create mode 100644 build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/language/settings/providers/GCCBuiltinSpecsDetectorCygwin.java diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/BuiltinSpecsDetectorTest.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/BuiltinSpecsDetectorTest.java index c10adce4907..27e40a598f2 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/BuiltinSpecsDetectorTest.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/BuiltinSpecsDetectorTest.java @@ -225,6 +225,7 @@ public class BuiltinSpecsDetectorTest extends BaseTestCase { provider.execute(); assertEquals(true, provider.isExecuted()); + assertEquals(null, provider.getSettingEntries(null, null, null)); } } @@ -307,7 +308,9 @@ public class BuiltinSpecsDetectorTest extends BaseTestCase { // check entries { MockDetectorCloneable clone = provider.clone(); - clone.setSettingEntries(null, null, null, null); + List entries2 = new ArrayList(); + entries2.add(new CMacroEntry("MACRO2", "VALUE2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY)); + clone.setSettingEntries(null, null, null, entries2); assertFalse(provider.equals(clone)); } diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/GCCBuiltinSpecsDetectorTest.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/GCCBuiltinSpecsDetectorTest.java index 870cc21e0c0..d8f3eab1379 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/GCCBuiltinSpecsDetectorTest.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/language/settings/providers/tests/GCCBuiltinSpecsDetectorTest.java @@ -14,16 +14,23 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.cdt.core.dom.ast.gnu.c.GCCLanguage; +import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.settings.model.CIncludePathEntry; import org.eclipse.cdt.core.settings.model.CMacroEntry; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager; import org.eclipse.cdt.core.settings.model.ICSettingEntry; import org.eclipse.cdt.core.testplugin.ResourceHelper; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; +import org.eclipse.cdt.internal.core.Cygwin; +import org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorCygwin; import org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; /** * Test cases to test GCC built-in specs detector. @@ -45,6 +52,20 @@ public class GCCBuiltinSpecsDetectorTest extends BaseTestCase { } } + /** + * Mock GCCBuiltinSpecsDetectorCygwin to gain access to protected methods. + */ + class MockGCCBuiltinSpecsDetectorCygwin extends GCCBuiltinSpecsDetectorCygwin { + @Override + public void startupForLanguage(String languageId) throws CoreException { + super.startupForLanguage(languageId); + } + @Override + public void shutdownForLanguage() { + super.shutdownForLanguage(); + } + } + @Override protected void setUp() throws Exception { super.setUp(); @@ -55,6 +76,21 @@ public class GCCBuiltinSpecsDetectorTest extends BaseTestCase { super.tearDown(); } + /** + * Helper method to fetch configuration descriptions. + */ + private ICConfigurationDescription[] getConfigurationDescriptions(IProject project) { + CoreModel coreModel = CoreModel.getDefault(); + ICProjectDescriptionManager mngr = coreModel.getProjectDescriptionManager(); + // project description + ICProjectDescription projectDescription = mngr.getProjectDescription(project); + assertNotNull(projectDescription); + assertEquals(1, projectDescription.getConfigurations().length); + // configuration description + ICConfigurationDescription[] cfgDescriptions = projectDescription.getConfigurations(); + return cfgDescriptions; + } + /** * Test expansion of variables in build command. */ @@ -365,4 +401,68 @@ public class GCCBuiltinSpecsDetectorTest extends BaseTestCase { assertEquals(1, entries.size()); } + /** + * Test parsing of include directives for Cygwin for global provider. + */ + public void testGCCBuiltinSpecsDetector_Cygwin_NoProject() throws Exception { + if (!Cygwin.isAvailable()) { + // Skip the test if Cygwin is not available. + return; + } + + String cygwinLocation = "/usr/include"; + String windowsLocation = ResourceHelper.cygwinToWindowsPath(cygwinLocation); + assertTrue("windowsLocation=["+windowsLocation+"]", new Path(windowsLocation).getDevice()!=null); + + MockGCCBuiltinSpecsDetectorCygwin detector = new MockGCCBuiltinSpecsDetectorCygwin(); + + detector.startup(null, null); + detector.startupForLanguage(null); + detector.processLine("#include <...> search starts here:"); + detector.processLine(" /usr/include"); + detector.processLine("End of search list."); + detector.shutdownForLanguage(); + detector.shutdown(); + + // check populated entries + List entries = detector.getSettingEntries(null, null, null); + assertEquals(new CIncludePathEntry(new Path(windowsLocation), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0)); + assertEquals(1, entries.size()); + } + + /** + * Test parsing of include directives for Cygwin for provider running for a configuration. + */ + public void testGCCBuiltinSpecsDetector_Cygwin_Configuration() throws Exception { + if (!Cygwin.isAvailable()) { + // Skip the test if Cygwin is not available. + return; + } + + String cygwinLocation = "/usr/include"; + String windowsLocation = ResourceHelper.cygwinToWindowsPath(cygwinLocation); + assertTrue("windowsLocation=["+windowsLocation+"]", new Path(windowsLocation).getDevice()!=null); + + // Create model project and folders to test + String projectName = getName(); + IProject project = ResourceHelper.createCDTProjectWithConfig(projectName); + ICConfigurationDescription[] cfgDescriptions = getConfigurationDescriptions(project); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + + MockGCCBuiltinSpecsDetectorCygwin detector = new MockGCCBuiltinSpecsDetectorCygwin(); + + detector.startup(cfgDescription, null); + detector.startupForLanguage(null); + detector.processLine("#include <...> search starts here:"); + detector.processLine(" /usr/include"); + detector.processLine("End of search list."); + detector.shutdownForLanguage(); + detector.shutdown(); + + // check populated entries + List entries = detector.getSettingEntries(null, null, null); + assertEquals(new CIncludePathEntry(new Path(windowsLocation), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0)); + assertEquals(1, entries.size()); + } + } diff --git a/build/org.eclipse.cdt.managedbuilder.core/plugin.xml b/build/org.eclipse.cdt.managedbuilder.core/plugin.xml index f808643a31b..5c198d3ad4f 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/plugin.xml +++ b/build/org.eclipse.cdt.managedbuilder.core/plugin.xml @@ -613,6 +613,14 @@ + + + + environmentMap = null; + protected List detectedSettingEntries = null; protected int collected = 0; - protected boolean isExecuted = false; + protected volatile boolean isExecuted = false; + private int envPathHash = 0; private BuildRunnerHelper buildRunnerHelper; private SDMarkerGenerator markerGenerator = new SDMarkerGenerator(); @@ -348,6 +358,7 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti mappedRootURI = null; buildDirURI = getBuildDirURI(mappedRootURI); + environmentMap = createEnvironmentMap(currentCfgDescription); } @Override @@ -358,18 +369,46 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti super.shutdown(); } + /** + * This method does 2 related things: + *
+ * 1. Validate environment, i.e. check that environment for running the command has not changed. + * If environment changed {@link #execute()} will rerun the command even if flag {@link #isExecuted} + * suggests that it was run already. + *
+ * 2. The relevant environment is cached here so the new one is validated against it at the next call. + * {@link #validateEnvironment()} will be called right before running the job to execute the command. + * + * @since 8.2 + */ + protected boolean validateEnvironment() { + String envPathValue = environmentMap.get(ENV_PATH); + int envPathValueHash = envPathValue != null ? envPathValue.hashCode() : 0; + if (envPathValueHash != envPathHash || envPathValueHash == 0) { + envPathHash = envPathValueHash; + return false; + } + return true; + } + /** * Execute provider's command which is expected to print built-in compiler options (specs) to build output. * The parser will parse output and generate language settings for corresponding resources. */ protected void execute() { - if (isExecuted) { + environmentMap = createEnvironmentMap(currentCfgDescription); + if (validateEnvironment() && isExecuted) { return; } WorkspaceJob job = new WorkspaceJob(ManagedMakeMessages.getResourceString("AbstractBuiltinSpecsDetector.DiscoverBuiltInSettingsJobName")) { //$NON-NLS-1$ @Override public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { + isExecuted = false; + if (!isEmpty()) { + clear(); + serializeLanguageSettings(currentCfgDescription); + } IStatus status; try { startup(currentCfgDescription, null); @@ -550,7 +589,7 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti } } - String[] envp = getEnvp(); + String[] envp = toEnvp(environmentMap); // Using GMAKE_ERROR_PARSER_ID as it can handle generated error messages ErrorParserManager epm = new ErrorParserManager(currentProject, buildDirURI, markerGenerator, new String[] {GMAKE_ERROR_PARSER_ID}); @@ -592,8 +631,10 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti * @since 8.2 */ protected List getEnvironmentVariables() { - IEnvironmentVariableManager mngr = CCorePlugin.getDefault().getBuildEnvironmentManager(); - List vars = new ArrayList(Arrays.asList(mngr.getVariables(currentCfgDescription, true))); + if (envMngr == null) { + envMngr = CCorePlugin.getDefault().getBuildEnvironmentManager(); + } + List vars = new ArrayList(Arrays.asList(envMngr.getVariables(currentCfgDescription, true))); // On POSIX (Linux, UNIX) systems reset language variables to default (English) // with UTF-8 encoding since GNU compilers can handle only UTF-8 characters. @@ -608,16 +649,23 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti } /** - * Get array of environment variables in format "var=value". + * Create a handy map of environment variables. */ - private String[] getEnvp() { - EnvironmentCollector collector = new EnvironmentCollector(); - List vars = getEnvironmentVariables(); - collector.addVariables(vars.toArray(new IEnvironmentVariable[vars.size()])); + private Map createEnvironmentMap(ICConfigurationDescription cfgDescription) { + Map envMap = new HashMap(); + for (IEnvironmentVariable var : getEnvironmentVariables()) { + envMap.put(var.getName(), var.getValue()); + } + return envMap; + } + /** + * Convert map of environment variables to array in format "var=value". + */ + private String[] toEnvp(Map environmentMap) { Set envp = new HashSet(); - for (IEnvironmentVariable var : collector.getVariables()) { - envp.add(var.getName() + '=' + var.getValue()); + for (Entry var: environmentMap.entrySet()) { + envp.add(var.getKey() + '=' + var.getValue()); } return envp.toArray(new String[envp.size()]); } @@ -736,6 +784,9 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti public Element serializeAttributes(Element parentElement) { Element elementProvider = super.serializeAttributes(parentElement); elementProvider.setAttribute(ATTR_CONSOLE, Boolean.toString(isConsoleEnabled)); + if (envPathHash != 0) { + elementProvider.setAttribute(ATTR_ENV_HASH, Integer.toString(envPathHash)); + } return elementProvider; } @@ -747,6 +798,16 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti if (consoleValue != null) { isConsoleEnabled = Boolean.parseBoolean(consoleValue); } + + envPathHash = 0; + String envPathHashStr = XmlUtil.determineAttributeValue(providerNode, ATTR_ENV_HASH); + if (envPathHashStr != null) { + try { + envPathHash = Integer.parseInt(envPathHashStr); + } catch (Exception e) { + ManagedBuilderCorePlugin.log(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, "Wrong integer format [" + envPathHashStr + "]", e)); //$NON-NLS-1$ //$NON-NLS-2$ + } + } } @Override @@ -774,6 +835,9 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti protected AbstractBuiltinSpecsDetector cloneShallow() throws CloneNotSupportedException { AbstractBuiltinSpecsDetector clone = (AbstractBuiltinSpecsDetector) super.cloneShallow(); clone.isExecuted = false; + clone.envMngr = null; + clone.environmentMap = null; + clone.envPathHash = 0; return clone; } @@ -783,6 +847,7 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti int result = super.hashCode(); result = prime * result + (isConsoleEnabled ? 1231 : 1237); result = prime * result + (isExecuted ? 1231 : 1237); + result = prime * result + envPathHash; return result; } @@ -792,13 +857,15 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti return true; if (!super.equals(obj)) return false; - if (!(obj instanceof AbstractBuiltinSpecsDetector)) + if (getClass() != obj.getClass()) return false; AbstractBuiltinSpecsDetector other = (AbstractBuiltinSpecsDetector) obj; if (isConsoleEnabled != other.isConsoleEnabled) return false; if (isExecuted != other.isExecuted) return false; + if (envPathHash != other.envPathHash) + return false; return true; } } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/AbstractLanguageSettingsOutputScanner.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/AbstractLanguageSettingsOutputScanner.java index 9d8d5347644..f11ec08a8ea 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/AbstractLanguageSettingsOutputScanner.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/AbstractLanguageSettingsOutputScanner.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2012 Andrew Gvozdev and others. + * Copyright (c) 2009, 2013 Andrew Gvozdev 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 @@ -25,6 +25,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.EFSExtensionProvider; import org.eclipse.cdt.core.ErrorParserManager; import org.eclipse.cdt.core.cdtvariables.CdtVariableException; import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager; @@ -80,6 +81,37 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett protected String parsedResourceName = null; protected boolean isResolvingPaths = true; + /** @since 8.2 */ + protected EFSExtensionProvider efsProvider = null; + + private static final EFSExtensionProvider efsProviderDefault = new EFSExtensionProvider() { + final EFSExtensionManager efsManager = EFSExtensionManager.getDefault(); + @Override + public String getPathFromURI(URI locationURI) { + return efsManager.getPathFromURI(locationURI); + } + @Override + public URI getLinkedURI(URI locationURI) { + return efsManager.getLinkedURI(locationURI); + } + @Override + public URI createNewURIFromPath(URI locationOnSameFilesystem, String path) { + return efsManager.createNewURIFromPath(locationOnSameFilesystem, path); + } + @Override + public String getMappedPath(URI locationURI) { + return efsManager.getMappedPath(locationURI); + } + @Override + public boolean isVirtual(URI locationURI) { + return efsManager.isVirtual(locationURI); + } + @Override + public URI append(URI baseURI, String extension) { + return efsManager.append(baseURI, extension); + } + }; + /** * Abstract class defining common functionality for option parsers. * The purpose of this parser is to parse a portion of string representing @@ -373,6 +405,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett this.currentCfgDescription = cfgDescription; this.currentProject = cfgDescription != null ? cfgDescription.getProjectDescription().getProject() : null; this.cwdTracker = cwdTracker; + this.efsProvider = getEFSProvider(); } @Override @@ -429,7 +462,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett if (isResolvingPaths && (optionParser.isForFile() || optionParser.isForFolder())) { URI baseURI = mappedRootURI; if (buildDirURI != null && !new Path(optionParser.parsedName).isAbsolute()) { - baseURI = EFSExtensionManager.getDefault().append(mappedRootURI, buildDirURI.getPath()); + baseURI = efsProvider.append(mappedRootURI, buildDirURI.getPath()); } entry = createResolvedPathEntry(optionParser, optionParser.parsedName, 0, baseURI); } else { @@ -494,7 +527,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett } } // this creates URI with schema and other components from resourceURI but path as mappedRoot - URI uri = EFSExtensionManager.getDefault().createNewURIFromPath(resourceURI, mappedRoot); + URI uri = efsProvider.createNewURIFromPath(resourceURI, mappedRoot); return uri; } @@ -513,9 +546,9 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett if (currentResource != null && parsedResourceName != null && !new Path(parsedResourceName).isAbsolute()) { cwdURI = findBaseLocationURI(currentResource.getLocationURI(), parsedResourceName); } - String cwdPath = cwdURI != null ? EFSExtensionManager.getDefault().getPathFromURI(cwdURI) : null; + String cwdPath = cwdURI != null ? efsProvider.getPathFromURI(cwdURI) : null; if (cwdPath != null && mappedRootURI != null) { - buildDirURI = EFSExtensionManager.getDefault().append(mappedRootURI, cwdPath); + buildDirURI = efsProvider.append(mappedRootURI, cwdPath); } else { buildDirURI = cwdURI; } @@ -674,7 +707,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett if (sourceFile == null && cwdTracker != null) { URI cwdURI = cwdTracker.getWorkingDirectoryURI(); if (cwdURI != null) { - URI uri = EFSExtensionManager.getDefault().append(cwdURI, parsedResourceName); + URI uri = efsProvider.append(cwdURI, parsedResourceName); sourceFile = findFileForLocationURI(uri, currentProject); } } @@ -804,7 +837,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett * @param baseURI - base {@link URI} where path to the resource is rooted * @return {@link URI} of the resource */ - private static URI determineMappedURI(String pathStr, URI baseURI) { + private URI determineMappedURI(String pathStr, URI baseURI) { URI uri = null; if (baseURI == null) { @@ -819,9 +852,9 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett } else { // location on a remote file-system IPath path = new Path(pathStr); // use canonicalized path here, in particular replace all '\' with '/' for Windows paths - URI remoteUri = EFSExtensionManager.getDefault().append(baseURI, path.toString()); + URI remoteUri = efsProvider.append(baseURI, path.toString()); if (remoteUri != null) { - String localPath = EFSExtensionManager.getDefault().getMappedPath(remoteUri); + String localPath = efsProvider.getMappedPath(remoteUri); if (localPath != null) { uri = org.eclipse.core.filesystem.URIUtil.toURI(localPath); } @@ -929,13 +962,13 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett } /** - * Get location on the local file-system considering possible mapping by {@link EFSExtensionManager}. + * Get location on the local file-system considering possible mapping by EFS provider. See {@link EFSExtensionManager}. */ - private static IPath getFilesystemLocation(URI uri) { + private IPath getFilesystemLocation(URI uri) { if (uri == null) return null; - String pathStr = EFSExtensionManager.getDefault().getMappedPath(uri); + String pathStr = efsProvider.getMappedPath(uri); uri = org.eclipse.core.filesystem.URIUtil.toURI(pathStr); if (uri != null && uri.isAbsolute()) { @@ -1065,6 +1098,20 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett return pattern; } + + /** + * This {@link EFSExtensionProvider} is capable to translate EFS paths to and from local + * file-system. Added mostly for Cygwin translations. + * + * This usage of {@link EFSExtensionProvider} is somewhat a misnomer. This provider is not + * an "extension" provider but rather a wrapper on {@link EFSExtensionManager} which in fact + * will use genuine {@link EFSExtensionProvider}s defined as extensions. + * + * @since 8.2 + */ + protected EFSExtensionProvider getEFSProvider() { + return efsProviderDefault; + } @Override public Element serializeAttributes(Element parentElement) { diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/ToolchainBuiltinSpecsDetector.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/ToolchainBuiltinSpecsDetector.java index 8d4d6b7cb1a..2a2322d3aa7 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/ToolchainBuiltinSpecsDetector.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/language/settings/providers/ToolchainBuiltinSpecsDetector.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2012 Andrew Gvozdev and others. + * Copyright (c) 2009, 2013 Andrew Gvozdev 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 @@ -11,22 +11,17 @@ package org.eclipse.cdt.managedbuilder.language.settings.providers; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; -import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IInputType; import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.IToolChain; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; -import org.eclipse.cdt.managedbuilder.envvar.IBuildEnvironmentVariable; -import org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSupplier; -import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider; +import org.eclipse.cdt.managedbuilder.internal.envvar.EnvironmentVariableManagerToolChain; /** * Abstract parser capable to execute compiler command printing built-in compiler @@ -120,19 +115,12 @@ public abstract class ToolchainBuiltinSpecsDetector extends AbstractBuiltinSpecs @Override protected List getEnvironmentVariables() { - List vars = new ArrayList(super.getEnvironmentVariables()); - - String toolchainId = getToolchainId(); - for (IToolChain toolchain = ManagedBuildManager.getExtensionToolChain(toolchainId); toolchain != null; toolchain = toolchain.getSuperClass()) { - IConfigurationEnvironmentVariableSupplier envSupplier = toolchain.getEnvironmentVariableSupplier(); - if (envSupplier != null) { - IConfiguration cfg = ManagedBuildManager.getConfigurationForDescription(currentCfgDescription); - IEnvironmentVariableProvider provider = ManagedBuildManager.getEnvironmentVariableProvider(); - IBuildEnvironmentVariable[] added = envSupplier.getVariables(cfg, provider); - vars.addAll(Arrays.asList(added)); - break; - } + if (envMngr == null && currentCfgDescription == null) { + // For global provider need to include toolchain in the equation + IToolChain toolchain = ManagedBuildManager.getExtensionToolChain(getToolchainId()); + envMngr = new EnvironmentVariableManagerToolChain(toolchain); } + List vars = super.getEnvironmentVariables(); return vars; } diff --git a/build/org.eclipse.cdt.managedbuilder.gnu.ui/plugin.xml b/build/org.eclipse.cdt.managedbuilder.gnu.ui/plugin.xml index da844d82768..eaa55a1ea6f 100644 --- a/build/org.eclipse.cdt.managedbuilder.gnu.ui/plugin.xml +++ b/build/org.eclipse.cdt.managedbuilder.gnu.ui/plugin.xml @@ -1772,6 +1772,7 @@ configurationEnvironmentSupplier="org.eclipse.cdt.managedbuilder.gnu.cygwin.GnuCygwinConfigurationEnvironmentSupplier" id="cdt.managedbuild.toolchain.gnu.cygwin.base" isToolChainSupported="org.eclipse.cdt.managedbuilder.gnu.cygwin.IsGnuCygwinToolChainSupported" + languageSettingsProviders="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser;org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorCygwin" name="%ToolChainName.Cygwin" osList="win32" targetTool="cdt.managedbuild.tool.gnu.cpp.linker.cygwin.base;cdt.managedbuild.tool.gnu.c.linker.cygwin.base;cdt.managedbuild.tool.gnu.archiver">