diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java index c470347b2d9..182dac85f77 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java @@ -233,6 +233,72 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase { assertQNEquals(expContainedTypeQN, (IBinding) containedType); } } + + class SinglePDOMTestFirstASTStrategy implements ITestStrategy { + private IIndex index; + private ICProject cproject; + private StringBuffer[] testData; + private IASTTranslationUnit ast; + private boolean cpp; + + public SinglePDOMTestFirstASTStrategy(boolean cpp) { + this.cpp = cpp; + } + + public ICProject getCProject() { + return cproject; + } + + public StringBuffer[] getTestData() { + return testData; + } + + public IASTTranslationUnit getAst() { + return ast; + } + + public void setUp() throws Exception { + cproject = cpp ? CProjectHelper.createCCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER) + : CProjectHelper.createCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER); + Bundle b = CTestPlugin.getDefault().getBundle(); + testData = TestSourceReader.getContentsForTest(b, "parser", IndexBindingResolutionTestBase.this.getClass(), getName(), 2); + + if (testData.length < 2) + return; + IFile file = TestSourceReader.createFile(cproject.getProject(), new Path("header.h"), testData[0].toString()); + CCorePlugin.getIndexManager().setIndexerId(cproject, IPDOMManager.ID_FAST_INDEXER); + assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor())); + + if (DEBUG) { + System.out.println("Project PDOM: "+getName()); + ((PDOM)CCoreInternals.getPDOMManager().getPDOM(cproject)).accept(new PDOMPrettyPrinter()); + } + + index= CCorePlugin.getIndexManager().getIndex(cproject); + + index.acquireReadLock(); + IFile cppfile= TestSourceReader.createFile(cproject.getProject(), new Path("references.c" + (cpp ? "pp" : "")), testData[1].toString()); + ast = TestSourceReader.createIndexBasedAST(index, cproject, cppfile); + } + + public void tearDown() throws Exception { + if (index != null) { + index.releaseReadLock(); + } + if (cproject != null) { + cproject.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, new NullProgressMonitor()); + } + } + + public IIndex getIndex() { + return index; + } + + public boolean isCompositeIndex() { + return false; + } + } + class SinglePDOMTestStrategy implements ITestStrategy { private IIndex index; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java index 30e8212becc..e0c63b385cd 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java @@ -64,13 +64,14 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true));} public static TestSuite suite() {return suite(SingleProject.class);} } - + public static class ProjectWithDepProj extends IndexCPPBindingResolutionBugs { public ProjectWithDepProj() {setStrategy(new ReferencedProject(true));} public static TestSuite suite() {return suite(ProjectWithDepProj.class);} } public static void addTests(TestSuite suite) { + suite.addTest(IndexCPPBindingResolutionBugsSingleProjectFirstAST.suite()); suite.addTest(SingleProject.suite()); suite.addTest(ProjectWithDepProj.suite()); } @@ -87,6 +88,7 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas // #define FUNC() void bar() // #define FUNC2(A) void baz() + // #include "header.h" // // OBJ {} @@ -1136,4 +1138,20 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas buf.append('}'); return buf.toString(); } + + // class Derived; + // class X { + // Derived* d; + // }; + // class Base {}; + // void useBase(Base* b); + + // class Derived: Base {}; + // void test() { + // X x; + // useBase(x.d); + // } + public void testLateDefinitionOfInheritance_Bug292749() throws Exception { + getBindingFromASTName("useBase(x.d", 7, ICPPFunction.class); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugsSingleProjectFirstAST.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugsSingleProjectFirstAST.java new file mode 100644 index 00000000000..1cd104e79be --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugsSingleProjectFirstAST.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.index.tests; + +import junit.framework.TestSuite; + +public class IndexCPPBindingResolutionBugsSingleProjectFirstAST extends IndexCPPBindingResolutionBugs { + public IndexCPPBindingResolutionBugsSingleProjectFirstAST() { + setStrategy(new SinglePDOMTestFirstASTStrategy(true)); + } + public static TestSuite suite() {return suite(IndexCPPBindingResolutionBugsSingleProjectFirstAST.class);} + // invalid tests for this strategy, they assume that the second file is already indexed. + @Override public void testBug208558() {} + @Override public void testBug176708_CCE() {} + @Override public void testIsSameAnonymousType_Bug193962() {} + @Override public void testIsSameNestedAnonymousType_Bug193962() {} +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java index d287adc1102..745f878ac91 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java @@ -35,6 +35,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; /** * @author jcamelon @@ -188,11 +189,11 @@ public class CPPASTFieldReference extends ASTNode implements IBinding binding = name.resolvePreBinding(); try { if (binding instanceof IVariable) { - return ((IVariable) binding).getType(); + return SemanticUtil.mapToAST(((IVariable) binding).getType(), this); } else if (binding instanceof IEnumerator) { return ((IEnumerator) binding).getType(); } else if (binding instanceof IFunction) { - return ((IFunction) binding).getType(); + return SemanticUtil.mapToAST(((IFunction) binding).getType(), this); } else if (binding instanceof ICPPUnknownBinding) { return CPPUnknownClass.createUnnamedInstance(); } else if (binding instanceof IProblemBinding) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java index 8d5c42cf674..f2363a81124 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java @@ -213,9 +213,9 @@ public class CPPASTFunctionCallExpression extends ASTNode implements return new ProblemBinding(this, IProblemBinding.SEMANTIC_BAD_SCOPE, binding.getName().toCharArray()); } else if (binding instanceof IFunction) { - t = ((IFunction) binding).getType(); + t = SemanticUtil.mapToAST(((IFunction) binding).getType(), this); } else if (binding instanceof IVariable) { - t = ((IVariable) binding).getType(); + t = SemanticUtil.mapToAST(((IVariable) binding).getType(), this); } else if (binding instanceof IType) { return (IType) binding; // constructor or simple type initializer } else if (binding instanceof IProblemBinding) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java index 5aa7b29a4d7..e1fd753713b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java @@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; /** * @author jcamelon @@ -91,13 +92,13 @@ public class CPPASTIdExpression extends ASTNode implements IASTIdExpression, IAS IBinding binding = name.resolvePreBinding(); try { if (binding instanceof IVariable) { - return ((IVariable) binding).getType(); + return SemanticUtil.mapToAST(((IVariable) binding).getType(), this); } else if (binding instanceof IEnumerator) { return ((IEnumerator) binding).getType(); } else if (binding instanceof IProblemBinding) { return (IType) binding; } else if (binding instanceof IFunction) { - return ((IFunction) binding).getType(); + return SemanticUtil.mapToAST(((IFunction) binding).getType(), this); } else if (binding instanceof ICPPTemplateNonTypeParameter) { return ((ICPPTemplateNonTypeParameter) binding).getType(); } else if (binding instanceof ICPPClassType) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BaseClassLookup.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BaseClassLookup.java index 098f75be32c..bf07b6f43e0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BaseClassLookup.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BaseClassLookup.java @@ -17,6 +17,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding; @@ -194,10 +195,20 @@ class BaseClassLookup { // assume that there are no bases } if (grandBases != null && grandBases.length > 0) { - HashSet grandBaseBindings= grandBases.length > 1 ? new HashSet() : null; - for (ICPPBase grandBase : grandBases) { + HashSet grandBaseBindings= null; + BitSet selectedBases= null; + if (grandBases.length > 1) { + grandBaseBindings= new HashSet(); + + // if we have reachable bases, then ignore the others + selectedBases = selectPreferredBases(data, grandBases); + } + for (int i = 0; i < grandBases.length; i++) { + ICPPBase grandBase = grandBases[i]; if (grandBase instanceof IProblemBinding) continue; + if (selectedBases != null && !selectedBases.get(i)) + continue; try { IBinding grandBaseBinding = grandBase.getBaseClass(); @@ -238,6 +249,31 @@ class BaseClassLookup { return result; } + private static BitSet selectPreferredBases(LookupData data, ICPPBase[] grandBases) { + if (data.contentAssist) + return null; + + BitSet selectedBases; + selectedBases= new BitSet(grandBases.length); + IName baseName= null; + for (int i = 0; i < grandBases.length; i++) { + ICPPBase nbase = grandBases[i]; + if (nbase instanceof IProblemBinding) + continue; + + final IName nbaseName = nbase.getBaseClassSpecifierName(); + int cmp= baseName == null ? -1 : CPPSemantics.compareByRelevance(data, baseName, nbaseName); + if (cmp <= 0) { + if (cmp < 0) { + selectedBases.clear(); + baseName= nbaseName; + } + selectedBases.set(i); + } + } + return selectedBases; + } + static void hideVirtualBases(BaseClassLookup rootInfo, HashMap infoMap) { boolean containsVirtualBase= false; final BaseClassLookup[] allInfos = infoMap.values().toArray(new BaseClassLookup[infoMap.size()]); 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 e109bf5ea3f..3110e135bcb 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 @@ -24,6 +24,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; @@ -136,7 +137,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.index.IIndexBinding; +import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.index.IIndexFileSet; +import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.parser.IProblem; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; @@ -183,6 +186,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank; import org.eclipse.cdt.internal.core.index.IIndexScope; +import org.eclipse.core.runtime.CoreException; /** * Name resolution @@ -1788,6 +1792,36 @@ public class CPPSemantics { return 0; } + /** + * Compares two bindings for relevance in the context of an AST. AST bindings are + * considered more relevant than index ones since the index may be out of date, + * built for a different configuration, etc. Index bindings reachable through includes + * are more relevant than unreachable ones. + * @param ast + * @param b1 + * @param b2 + * @return 1 if binding b1 is more relevant than b2; 0 if + * the two bindings have the same relevance; -1 if b1 is less relevant than + * b2. + */ + static int compareByRelevance(LookupData data, IName b1, IName b2) { + boolean b1FromIndex= (b1 instanceof IIndexName); + boolean b2FromIndex= (b2 instanceof IIndexName); + if (b1FromIndex != b2FromIndex) { + return !b1FromIndex ? 1 : -1; + } else if (b1FromIndex) { + // Both are from index. + if (data.tu != null) { + boolean b1Reachable= isReachableFromAst(data.tu, b1); + boolean b2Reachable= isReachableFromAst(data.tu, b2); + if (b1Reachable != b2Reachable) { + return b1Reachable ? 1 : -1; + } + } + } + return 0; + } + /** * Compares a binding with a list of function candidates for relevance in the context of an AST. AST bindings are * considered more relevant than index ones since the index may be out of date, @@ -1864,6 +1898,28 @@ public class CPPSemantics { return indexFileSet != null && indexFileSet.containsDeclaration(indexBinding); } + /** + * Checks if a binding is an AST binding, or is reachable from the AST through includes. + * The binding is assumed to belong to the AST, if it is not an IIndexBinding and not + * a specialization of an IIndexBinding. + * @param ast + * @param binding + * @return true if the binding is reachable from ast. + */ + private static boolean isReachableFromAst(IASTTranslationUnit ast, IName name) { + if (!(name instanceof IIndexName)) { + return true; + } + IIndexName indexName = (IIndexName) name; + try { + IIndexFile file= indexName.getFile(); + IIndexFileSet indexFileSet = ast.getIndexFileSet(); + return indexFileSet != null && indexFileSet.contains(file); + } catch (CoreException e) { + return false; + } + } + static private void reduceToViable(LookupData data, IBinding[] functions) throws DOMException { if (functions == null || functions.length == 0) return; @@ -2452,7 +2508,7 @@ public class CPPSemantics { * Also collections the function bindings if requested. */ public static IType getChainedMemberAccessOperatorReturnType(ICPPASTFieldReference fieldReference, Collection functionBindings) throws DOMException { - IASTExpression owner = fieldReference.getFieldOwner(); + final IASTExpression owner = fieldReference.getFieldOwner(); if (owner == null) return null; @@ -2505,7 +2561,7 @@ public class CPPSemantics { if (functionBindings != null) functionBindings.add(op); - type= op.getType().getReturnType(); + type= SemanticUtil.mapToAST(op.getType().getReturnType(), owner); foundOperator= true; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index d119045d592..9f9f371ff0e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -594,9 +594,8 @@ public class Conversions { } } - // This should actually be done in 'checkImplicitConversionSequence', see 13.3.3.1-6 and 8.5.14 - // 8.5.14 cv-qualifiers can be ignored for non-class types - // mstodo + // This should actually be done before the conversion is attempted, see for instance 13.3.3.1-6 and 8.5.14. + // However, it does not hurt to do it here either. IType unqualifiedTarget= getNestedType(target, CVQ | PTR_CVQ | TDEF | REF); if (!(unqualifiedTarget instanceof ICPPClassType)) { IType unqualifiedSource= getNestedType(source, CVQ | PTR_CVQ | TDEF | REF); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java index ea58755f8f6..4ea1d023018 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java @@ -15,6 +15,8 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IFunctionType; @@ -37,6 +39,7 @@ import org.eclipse.cdt.core.parser.util.CharArraySet; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.ObjectSet; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; @@ -44,6 +47,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; +import org.eclipse.cdt.internal.core.index.IIndexType; /** * @@ -290,6 +294,42 @@ public class SemanticUtil { type.setType(newNestedType); return type; } + + public static IType mapToAST(IType type, IASTNode node) { + if (!(type instanceof IIndexType)) + return type; + + try { + if (type instanceof IFunctionType) { + final ICPPFunctionType ft = (ICPPFunctionType) type; + final IType r = ft.getReturnType(); + final IType ret = mapToAST(r, node); + if (ret == r) { + return type; + } + return new CPPFunctionType(ret, ft.getParameterTypes(), ft.isConst(), ft.isVolatile()); + } + if (type instanceof ITypeContainer) { + final ITypeContainer tc = (ITypeContainer) type; + final IType nestedType= tc.getType(); + if (nestedType == null) + return type; + + IType newType= mapToAST(nestedType, node); + if (newType != nestedType) { + return replaceNestedType(tc, newType); + } + return type; + } else if (type instanceof ICPPClassType && type instanceof IIndexType) { + IASTTranslationUnit tu = node.getTranslationUnit(); + if (tu instanceof CPPASTTranslationUnit) { + return ((CPPASTTranslationUnit) tu).mapToAST((ICPPClassType) type); + } + } + } catch (DOMException e) { + } + return type; + } public static IType[] getSimplifiedTypes(IType[] types) { // Don't create a new array until it's really needed.