mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
Bug 509898 - CPPSemantics.isReachableFromAst is slow and is causing UI
freezes Added caching to the isReachableFromAst method. Change-Id: Ifb321f0ffde5a3068001711be222d8dadc0990cc
This commit is contained in:
parent
484895faea
commit
473c5c8ff1
3 changed files with 61 additions and 47 deletions
|
@ -32,6 +32,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||
import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.internal.core.dom.Linkage;
|
||||
|
@ -48,13 +51,15 @@ import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent;
|
|||
public class CPPASTTranslationUnit extends ASTTranslationUnit implements ICPPASTTranslationUnit, IASTAmbiguityParent {
|
||||
private CPPNamespaceScope fScope;
|
||||
private ICPPNamespace fBinding;
|
||||
private final CPPScopeMapper fScopeMapper= new CPPScopeMapper(this);
|
||||
private final CPPScopeMapper fScopeMapper;
|
||||
private CPPASTAmbiguityResolver fAmbiguityResolver;
|
||||
|
||||
// Caches
|
||||
private Map<ICPPClassType, FinalOverriderMap> fFinalOverriderMapCache = new HashMap<>();
|
||||
private final Map<ICPPClassType, FinalOverriderMap> fFinalOverriderMapCache = new HashMap<>();
|
||||
private final Map<IBinding, Boolean> fBindingReachabilityCache = new HashMap<>();
|
||||
|
||||
public CPPASTTranslationUnit() {
|
||||
fScopeMapper= new CPPScopeMapper(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -234,4 +239,43 @@ public class CPPASTTranslationUnit extends ASTTranslationUnit implements ICPPAST
|
|||
public ICPPClassTemplatePartialSpecialization mapToAST(ICPPClassTemplatePartialSpecialization indexSpec) {
|
||||
return fScopeMapper.mapToAST(indexSpec);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 binding
|
||||
* @return {@code true} if the {@code binding} is reachable from the AST.
|
||||
*/
|
||||
public boolean isReachableFromAst(IBinding binding) {
|
||||
Boolean cachedValue = fBindingReachabilityCache.get(binding);
|
||||
if (cachedValue != null)
|
||||
return cachedValue;
|
||||
|
||||
IIndexBinding indexBinding = null;
|
||||
if (binding instanceof IIndexBinding) {
|
||||
indexBinding = (IIndexBinding) binding;
|
||||
}
|
||||
if (binding instanceof ICPPSpecialization) {
|
||||
binding = ((ICPPSpecialization) binding).getSpecializedBinding();
|
||||
if (binding instanceof IIndexBinding) {
|
||||
indexBinding = (IIndexBinding) binding;
|
||||
}
|
||||
}
|
||||
boolean reachable;
|
||||
if (indexBinding == null) {
|
||||
// We don't check if the binding really belongs to this AST assuming that
|
||||
// the caller doesn't deal with two ASTs at a time.
|
||||
reachable = true;
|
||||
} else {
|
||||
IIndexFileSet indexFileSet = getIndexFileSet();
|
||||
IIndexFileSet astFileSet = getASTFileSet();
|
||||
reachable = indexFileSet != null &&
|
||||
(indexFileSet.containsDeclaration(indexBinding) ||
|
||||
astFileSet.containsDeclaration(indexBinding));
|
||||
}
|
||||
fBindingReachabilityCache.put(binding, reachable);
|
||||
return reachable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1104,7 +1104,7 @@ public class CPPSemantics {
|
|||
if (item instanceof IBinding) {
|
||||
IBinding binding = (IBinding) item;
|
||||
CPPASTTranslationUnit tu = data.getTranslationUnit();
|
||||
if (!isFromIndex(binding) || tu == null || isReachableFromAst(tu, binding)) {
|
||||
if (!isFromIndex(binding) || tu == null || tu.isReachableFromAst(binding)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2257,7 +2257,7 @@ public class CPPSemantics {
|
|||
* the two bindings have the same relevance; -1 if <code>b1</code> is less relevant than
|
||||
* <code>b2</code>.
|
||||
*/
|
||||
static int compareByRelevance(IASTTranslationUnit tu, IBinding b1, IBinding b2) {
|
||||
static int compareByRelevance(CPPASTTranslationUnit tu, IBinding b1, IBinding b2) {
|
||||
boolean b1FromIndex= isFromIndex(b1);
|
||||
boolean b2FromIndex= isFromIndex(b2);
|
||||
if (b1FromIndex != b2FromIndex) {
|
||||
|
@ -2265,8 +2265,8 @@ public class CPPSemantics {
|
|||
} else if (b1FromIndex) {
|
||||
// Both are from index.
|
||||
if (tu != null) {
|
||||
boolean b1Reachable= isReachableFromAst(tu, b1);
|
||||
boolean b2Reachable= isReachableFromAst(tu, b2);
|
||||
boolean b1Reachable= tu.isReachableFromAst(b1);
|
||||
boolean b2Reachable= tu.isReachableFromAst(b2);
|
||||
if (b1Reachable != b2Reachable) {
|
||||
return b1Reachable ? 1 : -1;
|
||||
}
|
||||
|
@ -2285,7 +2285,7 @@ public class CPPSemantics {
|
|||
return false;
|
||||
final CPPASTTranslationUnit tu = data.getTranslationUnit();
|
||||
if (tu != null) {
|
||||
return !isReachableFromAst(tu, b2) && isReachableFromAst(tu, type);
|
||||
return !tu.isReachableFromAst(b2) && tu.isReachableFromAst(type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -2306,12 +2306,12 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
|
||||
if (!isReachableFromAst(tu, type)) {
|
||||
if (!tu.isReachableFromAst(type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (IFunction fn : fns) {
|
||||
if (isReachableFromAst(tu, fn)) {
|
||||
if (tu.isReachableFromAst(fn)) {
|
||||
return false; // function from ast
|
||||
}
|
||||
}
|
||||
|
@ -2368,12 +2368,12 @@ public class CPPSemantics {
|
|||
}
|
||||
// Everything is from the index
|
||||
final CPPASTTranslationUnit tu = data.getTranslationUnit();
|
||||
if (!isReachableFromAst(tu, obj)) {
|
||||
if (!tu.isReachableFromAst(obj)) {
|
||||
return -1; // obj not reachable
|
||||
}
|
||||
|
||||
for (IFunction fn : fns) {
|
||||
if (isReachableFromAst(tu, fn)) {
|
||||
if (tu.isReachableFromAst(fn)) {
|
||||
return 0; // obj reachable, 1 function reachable
|
||||
}
|
||||
}
|
||||
|
@ -2403,40 +2403,10 @@ public class CPPSemantics {
|
|||
* 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 <code>true</code> if the <code>binding</code> is reachable from <code>ast</code>.
|
||||
*/
|
||||
private static boolean isReachableFromAst(IASTTranslationUnit ast, IBinding binding) {
|
||||
IIndexBinding indexBinding = null;
|
||||
if (binding instanceof IIndexBinding) {
|
||||
indexBinding = (IIndexBinding) binding;
|
||||
}
|
||||
if (binding instanceof ICPPSpecialization) {
|
||||
binding = ((ICPPSpecialization) binding).getSpecializedBinding();
|
||||
if (binding instanceof IIndexBinding) {
|
||||
indexBinding = (IIndexBinding) binding;
|
||||
}
|
||||
}
|
||||
if (indexBinding == null) {
|
||||
// We don't check if the binding really belongs to the AST specified by the ast
|
||||
// parameter assuming that the caller doesn't deal with two ASTs at a time.
|
||||
return true;
|
||||
}
|
||||
IIndexFileSet indexFileSet = ast.getIndexFileSet();
|
||||
IIndexFileSet astFileSet = ast.getASTFileSet();
|
||||
return indexFileSet != null &&
|
||||
(indexFileSet.containsDeclaration(indexBinding) ||
|
||||
astFileSet.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 <code>true</code> if the <code>binding</code> is reachable from <code>ast</code>.
|
||||
* @return {@code true} if the {@code binding}> is reachable from {@code ast}.
|
||||
*/
|
||||
private static boolean isReachableFromAst(IASTTranslationUnit ast, IName name) {
|
||||
if (!(name instanceof IIndexName)) {
|
||||
|
@ -2750,7 +2720,7 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
// Try to instantiate a template
|
||||
IASTTranslationUnit tu= data.getTranslationUnit();
|
||||
CPPASTTranslationUnit tu= data.getTranslationUnit();
|
||||
ICPPTemplateArgument[] tmplArgs= ICPPTemplateArgument.EMPTY_ARGUMENTS;
|
||||
if (templateID instanceof ICPPASTTemplateId) {
|
||||
tmplArgs = CPPTemplates.createTemplateArgumentArray((ICPPASTTemplateId) templateID);
|
||||
|
@ -3322,7 +3292,7 @@ public class CPPSemantics {
|
|||
ICPPFunction result= null;
|
||||
ICPPFunctionTemplate resultTemplate= null;
|
||||
boolean isAmbiguous= false;
|
||||
final IASTTranslationUnit tu= point.getTranslationUnit();
|
||||
final CPPASTTranslationUnit tu= (CPPASTTranslationUnit) point.getTranslationUnit();
|
||||
for (IFunction fn : fns) {
|
||||
try {
|
||||
if (fn instanceof ICPPFunctionTemplate) {
|
||||
|
|
|
@ -20,7 +20,6 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
|
|||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
|
@ -30,6 +29,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates.TypeSelection;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC;
|
||||
|
||||
|
@ -131,7 +131,7 @@ class FunctionCost {
|
|||
/**
|
||||
* Compares this function call cost to another one.
|
||||
*/
|
||||
public int compareTo(IASTTranslationUnit tu, FunctionCost other) throws DOMException {
|
||||
public int compareTo(CPPASTTranslationUnit tu, FunctionCost other) throws DOMException {
|
||||
if (other == null)
|
||||
return -1;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue