From da70ef502f6b7c37783f35a9842323f0cd3a04ea Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Tue, 22 Apr 2008 09:08:07 +0000 Subject: [PATCH] Support search for local variables and parameters, bug 151334. --- .../org.eclipse.cdt.core/META-INF/MANIFEST.MF | 1 + .../internal/core/browser/ASTTypeInfo.java | 324 ++++++++++++++++++ .../core/browser/ASTTypeReference.java | 40 +++ .../core/browser/util/IndexModelUtil.java | 23 +- .../typeinfo/TypeInfoLabelProvider.java | 6 +- .../internal/ui/search/PDOMSearchQuery.java | 37 +- .../search/PDOMSearchTextSelectionQuery.java | 30 +- .../ui/search/TypeInfoSearchElement.java | 7 + 8 files changed, 457 insertions(+), 11 deletions(-) create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/ASTTypeInfo.java create mode 100644 core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/ASTTypeReference.java diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF index 72b19e108b5..f402dce2612 100644 --- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF @@ -40,6 +40,7 @@ Export-Package: org.eclipse.cdt.core, org.eclipse.cdt.core.templateengine.process, org.eclipse.cdt.core.templateengine.process.processes, org.eclipse.cdt.internal.core;x-friends:="org.eclipse.cdt.ui", + org.eclipse.cdt.internal.core.browser;x-friends:="org.eclipse.cdt.ui", org.eclipse.cdt.internal.core.browser.util;x-friends:="org.eclipse.cdt.ui", org.eclipse.cdt.internal.core.cdtvariables;x-internal:=true, org.eclipse.cdt.internal.core.dom;x-friends:="org.eclipse.cdt.ui", diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/ASTTypeInfo.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/ASTTypeInfo.java new file mode 100644 index 00000000000..ae3133e1829 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/ASTTypeInfo.java @@ -0,0 +1,324 @@ +/******************************************************************************* + * Copyright (c) 2008 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.core.browser; + +import java.util.Arrays; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.browser.IFunctionInfo; +import org.eclipse.cdt.core.browser.IQualifiedTypeName; +import org.eclipse.cdt.core.browser.ITypeInfo; +import org.eclipse.cdt.core.browser.ITypeReference; +import org.eclipse.cdt.core.browser.ITypeSearchScope; +import org.eclipse.cdt.core.browser.QualifiedTypeName; +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.ICompositeType; +import org.eclipse.cdt.core.dom.ast.IField; +import org.eclipse.cdt.core.dom.ast.IFunction; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding; +import org.eclipse.cdt.core.index.IIndexFileLocation; +import org.eclipse.cdt.core.index.IndexLocationFactory; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; +import org.eclipse.cdt.internal.core.browser.util.IndexModelUtil; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMNotImplementedError; +import org.eclipse.core.filesystem.URIUtil; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +/** + * Type info object needed to support search for local variables. + * @since 5.0 + */ +public class ASTTypeInfo implements ITypeInfo, IFunctionInfo { + private static int hashCode(String[] array) { + int prime = 31; + if (array == null) + return 0; + int result = 1; + for (String element : array) { + result = prime * result + (element == null ? 0 : element.hashCode()); + } + return result; + } + + private final String[] fqn; + private final int elementType; + private final String[] params; + private final String returnType; + private ASTTypeReference reference; + + /** + * Creates a type info suitable for the binding. + * @param name the name to create the type info object for. + */ + public static ASTTypeInfo create(IASTName name) { + try { + String[] fqn; + int elementType; + final IBinding binding = name.resolveBinding(); + final ASTTypeReference ref= createReference(name); + elementType = IndexModelUtil.getElementType(binding); + if (binding instanceof ICPPBinding) { + fqn= ((ICPPBinding)binding).getQualifiedName(); + } + else if (binding instanceof IField) { + IField field= (IField) binding; + ICompositeType owner= field.getCompositeTypeOwner(); + fqn= new String[] {owner.getName(), field.getName()}; + } + else { + fqn= new String[] {binding.getName()}; + } + if (binding instanceof IFunction) { + final IFunction function= (IFunction)binding; + final String[] paramTypes= IndexModelUtil.extractParameterTypes(function); + final String returnType= IndexModelUtil.extractReturnType(function); + return new ASTTypeInfo(fqn, elementType, paramTypes, returnType, ref); + } + return new ASTTypeInfo(fqn, elementType, null, null, ref); + } catch (DOMException e) { + Assert.isTrue(false); + } + + return null; + } + + + private ASTTypeInfo(String[] fqn, int elementType, String[] params, String returnType, ASTTypeReference reference) { + Assert.isNotNull(reference); + this.fqn= fqn; + this.elementType= elementType; + this.params= params; + this.returnType= returnType; + this.reference= reference; + } + + public void addDerivedReference(ITypeReference location) { + throw new PDOMNotImplementedError(); + } + + public void addReference(ITypeReference location) { + throw new PDOMNotImplementedError(); + } + + public boolean canSubstituteFor(ITypeInfo info) { + throw new PDOMNotImplementedError(); + } + + public boolean encloses(ITypeInfo info) { + throw new PDOMNotImplementedError(); + } + + public boolean exists() { + throw new PDOMNotImplementedError(); + } + + public int getCElementType() { + return elementType; + } + + public ITypeReference[] getDerivedReferences() { + throw new PDOMNotImplementedError(); + } + + public ITypeInfo[] getEnclosedTypes() { + throw new PDOMNotImplementedError(); + } + + public ITypeInfo[] getEnclosedTypes(int[] kinds) { + throw new PDOMNotImplementedError(); + } + + public ITypeInfo getEnclosingNamespace(boolean includeGlobalNamespace) { + throw new PDOMNotImplementedError(); + } + + public ICProject getEnclosingProject() { + if(getResolvedReference()!=null) { + IProject project = reference.getProject(); + if(project!=null) { + return CCorePlugin.getDefault().getCoreModel().getCModel().getCProject(project.getName()); + } + } + return null; + } + + public ITypeInfo getEnclosingType() { + // TODO not sure + return null; + } + + public ITypeInfo getEnclosingType(int[] kinds) { + throw new PDOMNotImplementedError(); + } + + public String getName() { + return fqn[fqn.length-1]; + } + + public IQualifiedTypeName getQualifiedTypeName() { + return new QualifiedTypeName(fqn); + } + + public ITypeReference getResolvedReference() { + return reference; + } + + private static ASTTypeReference createReference(IASTName name) { + IASTFileLocation floc= name.getFileLocation(); + if (floc != null) { + String filename= floc.getFileName(); + IIndexFileLocation ifl= IndexLocationFactory.getIFLExpensive(filename); + String fullPath= ifl.getFullPath(); + if (fullPath != null) { + IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(fullPath)); + if(file!=null) { + return new ASTTypeReference(ifl, name.resolveBinding(), file, + floc.getNodeOffset(), floc.getNodeLength()); + } + } else { + IPath path = URIUtil.toPath(ifl.getURI()); + if (path!=null) { + return new ASTTypeReference(ifl, name.resolveBinding(), path, + floc.getNodeOffset(), floc.getNodeLength()); + } + } + } + return null; + } + + + public ITypeReference[] getReferences() { + throw new UnsupportedOperationException(); + } + + public ITypeInfo getRootNamespace(boolean includeGlobalNamespace) { + throw new PDOMNotImplementedError(); + } + + public ITypeInfo[] getSubTypes() { + throw new PDOMNotImplementedError(); + } + + public ASTAccessVisibility getSuperTypeAccess(ITypeInfo subType) { + throw new PDOMNotImplementedError(); + } + + public ITypeInfo[] getSuperTypes() { + throw new PDOMNotImplementedError(); + } + + public boolean hasEnclosedTypes() { + throw new PDOMNotImplementedError(); + } + + public boolean hasSubTypes() { + throw new PDOMNotImplementedError(); + } + + public boolean hasSuperTypes() { + throw new PDOMNotImplementedError(); + } + + public boolean isClass() { + throw new PDOMNotImplementedError(); + } + + public boolean isEnclosed(ITypeInfo info) { + throw new PDOMNotImplementedError(); + } + + public boolean isEnclosed(ITypeSearchScope scope) { + throw new PDOMNotImplementedError(); + } + + public boolean isEnclosedType() { + throw new PDOMNotImplementedError(); + } + + public boolean isEnclosingType() { + throw new PDOMNotImplementedError(); + } + + public boolean isReferenced(ITypeSearchScope scope) { + throw new PDOMNotImplementedError(); + } + + public boolean isUndefinedType() { + throw new PDOMNotImplementedError(); + } + + public void setCElementType(int type) { + throw new PDOMNotImplementedError(); + } + + public int compareTo(Object arg0) { + throw new PDOMNotImplementedError(); + } + + /* + * @see org.eclipse.cdt.internal.core.browser.IFunctionInfo#getParameters() + */ + public String[] getParameters() { + return params; + } + + /* + * @see org.eclipse.cdt.internal.core.browser.IFunctionInfo#getReturnType() + */ + public String getReturnType() { + return returnType; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + elementType; + result = prime * result + ASTTypeInfo.hashCode(fqn); + result = prime * result + ASTTypeInfo.hashCode(params); + return result; + } + + /** + * Type info objects are equal if they compute the same references. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ASTTypeInfo other = (ASTTypeInfo) obj; + if (elementType != other.elementType) + return false; + if (!Arrays.equals(fqn, other.fqn)) + return false; + if (!Arrays.equals(params, other.params)) + return false; + return true; + } + + + public IIndexFileLocation getIFL() { + return reference.getIFL(); + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/ASTTypeReference.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/ASTTypeReference.java new file mode 100644 index 00000000000..ce37b87ceb5 --- /dev/null +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/ASTTypeReference.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2008 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.core.browser; + +import org.eclipse.cdt.core.browser.ITypeReference; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.index.IIndexFileLocation; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IPath; + +/** + * A {@link ITypeReference} tailored for ast bindings. + * @since 5.0 + */ +public class ASTTypeReference extends IndexTypeReference { + + private final IIndexFileLocation fIfl; + + public ASTTypeReference(IIndexFileLocation ifl, IBinding binding, IFile file, int offset, int length) { + super(binding, file, file.getProject(), offset, length); + fIfl= ifl; + } + + public ASTTypeReference(IIndexFileLocation ifl, IBinding binding, IPath location, int offset, int length) { + super(binding, location, null, offset, length); + fIfl= ifl; + } + + public IIndexFileLocation getIFL() { + return fIfl; + } +} diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/IndexModelUtil.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/IndexModelUtil.java index b2e92e280b9..74e8b8f9583 100644 --- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/IndexModelUtil.java +++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/IndexModelUtil.java @@ -24,8 +24,11 @@ import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IParameter; +import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IVariable; +import org.eclipse.cdt.core.dom.ast.c.ICFunctionScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias; @@ -48,8 +51,8 @@ public class IndexModelUtil { */ public static boolean bindingHasCElementType(IBinding binding, int[] kinds) { try { - for(int i=0; i names= new HashSet(); + names.addAll(Arrays.asList(ast.getDeclarationsInAST(binding))); + names.addAll(Arrays.asList(ast.getDefinitionsInAST(binding))); + names.addAll(Arrays.asList(ast.getReferences(binding))); + + for (IASTName name : names) { + if ( ((flags & FIND_DECLARATIONS) != 0 && name.isDeclaration()) + || ((flags & FIND_DEFINITIONS) != 0 && name.isDefinition()) + || ((flags & FIND_REFERENCES) != 0 && name.isReference())) { + + ASTTypeInfo typeInfo= ASTTypeInfo.create(name); + if (typeInfo != null) { + ITypeReference ref= typeInfo.getResolvedReference(); + if (ref != null) { + result.addMatch(new PDOMSearchMatch( + new TypeInfoSearchElement(typeInfo), ref.getOffset(), ref.getLength())); + } + } + } + } + } + } + public final IStatus run(IProgressMonitor monitor) throws OperationCanceledException { PDOMSearchResult result= (PDOMSearchResult) getSearchResult(); result.removeAll(); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTextSelectionQuery.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTextSelectionQuery.java index b85cec9da48..f549842692a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTextSelectionQuery.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchTextSelectionQuery.java @@ -17,9 +17,14 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.text.ITextSelection; +import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IProblemBinding; +import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.core.dom.ast.c.ICFunctionScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ILanguage; @@ -36,11 +41,13 @@ public class PDOMSearchTextSelectionQuery extends PDOMSearchQuery { private ITranslationUnit tu; private ITextSelection selection; + private String searchText; public PDOMSearchTextSelectionQuery(ICElement[] scope, ITranslationUnit tu, ITextSelection selection, int flags) { super(scope, flags | IIndex.SEARCH_ACCROSS_LANGUAGE_BOUNDARIES); this.tu = tu; this.selection = selection; + this.searchText= selection.getText(); } @Override @@ -50,9 +57,24 @@ public class PDOMSearchTextSelectionQuery extends PDOMSearchQuery { if (ast != null) { IASTName searchName= ast.getNodeSelector(null).findEnclosingName(selection.getOffset(), selection.getLength()); if (searchName != null) { - IBinding binding = index.findBinding(searchName); - if (binding != null) - createMatches(index, binding); + searchText= searchName.toString(); + IBinding binding= searchName.resolveBinding(); + if (binding instanceof IProblemBinding == false) { + IScope scope= null; + try { + scope = binding.getScope(); + } catch (DOMException e) { + } + if (scope instanceof ICPPBlockScope || scope instanceof ICFunctionScope) { + createLocalMatches(ast, binding); + } + else { + binding = index.findBinding(searchName); + if (binding != null) { + createMatches(index, binding); + } + } + } } } return Status.OK_STATUS; @@ -62,6 +84,6 @@ public class PDOMSearchTextSelectionQuery extends PDOMSearchQuery { @Override public String getLabel() { - return super.getLabel() + " " + selection.getText(); //$NON-NLS-1$ + return super.getLabel() + " " + searchText; //$NON-NLS-1$ } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/TypeInfoSearchElement.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/TypeInfoSearchElement.java index 05963baab16..7df91828d52 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/TypeInfoSearchElement.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/TypeInfoSearchElement.java @@ -18,6 +18,8 @@ import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexName; +import org.eclipse.cdt.internal.core.browser.ASTTypeInfo; + /** * Represents a a c/c++-entity in a search. */ @@ -29,6 +31,11 @@ public class TypeInfoSearchElement extends PDOMSearchElement { this.typeInfo= IndexTypeInfo.create(index, binding); } + public TypeInfoSearchElement(ASTTypeInfo typeInfo) { + super(typeInfo.getIFL()); + this.typeInfo= typeInfo; + } + @Override public int hashCode() { return super.hashCode() + (typeInfo.getCElementType() *31 + typeInfo.getName().hashCode())*31;