diff --git a/php.editor/src/org/netbeans/modules/php/editor/model/impl/ModelVisitor.java b/php.editor/src/org/netbeans/modules/php/editor/model/impl/ModelVisitor.java --- a/php.editor/src/org/netbeans/modules/php/editor/model/impl/ModelVisitor.java +++ b/php.editor/src/org/netbeans/modules/php/editor/model/impl/ModelVisitor.java @@ -1346,10 +1346,12 @@ } public VariableScope getVariableScope(int offset) { + return getVariableScope(getFileScope().getElements(), offset); + } + + private VariableScope getVariableScope(List elements, int offset) { VariableScope retval = null; - List elements = new ArrayList(); - elements.add(getFileScope()); - elements.addAll(ModelUtils.getElements(getFileScope(), true)); + List subElements = new LinkedList(); for (ModelElement modelElement : elements) { if (modelElement instanceof VariableScope) { VariableScope varScope = (VariableScope) modelElement; @@ -1364,11 +1366,13 @@ if (possibleScope && blockRange.containsInclusive(offset) && (retval == null || retval.getBlockRange().overlaps(varScope.getBlockRange()))) { retval = varScope; + subElements.addAll(varScope.getElements()); } } } } - return retval; + VariableScope subResult = subElements.isEmpty() ? null : getVariableScope(subElements, offset); + return subResult == null ? retval : subResult; } private void buildCodeMarks(final int offset) { diff --git a/php.editor/src/org/netbeans/modules/php/editor/parser/SemanticAnalysis.java b/php.editor/src/org/netbeans/modules/php/editor/parser/SemanticAnalysis.java --- a/php.editor/src/org/netbeans/modules/php/editor/parser/SemanticAnalysis.java +++ b/php.editor/src/org/netbeans/modules/php/editor/parser/SemanticAnalysis.java @@ -48,6 +48,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.WeakHashMap; import org.netbeans.modules.csl.api.ColoringAttributes; import org.netbeans.modules.csl.api.OffsetRange; import org.netbeans.modules.csl.api.SemanticAnalyzer; @@ -433,10 +434,20 @@ super.visit(node); } + private final Map> typeToMethodCache = new WeakHashMap>(); + private Collection getMethods(TypeScope typeScope) { + Collection methods = typeToMethodCache.get(typeScope); + if (methods == null) { + methods = typeScope.getMethods(); + typeToMethodCache.put(typeScope, methods); + } + return methods; + } + private boolean isDeprecatedMethodInvocation(Collection typeScopes, Identifier identifier) { boolean isDeprecated = false; for (TypeScope typeScope : typeScopes) { - for (MethodScope methodScope : typeScope.getMethods()) { + for (MethodScope methodScope : getMethods(typeScope)) { if (methodScope.getName().equals(identifier.getName()) && methodScope.isDeprecated()) { isDeprecated = true; break; @@ -540,16 +551,36 @@ super.scan(node.getDispatcher()); } + private final Map> typeToFieldCache + = new WeakHashMap>(); + private Collection getFields(ClassScope classScope) { + Collection fields = typeToFieldCache.get(classScope); + if (fields == null) { + fields = classScope.getDeclaredFields(); + typeToFieldCache.put(classScope, fields); + } + return fields; + } + + private Collection getFields(TraitScope traitScope) { + Collection fields = typeToFieldCache.get(traitScope); + if (fields == null) { + fields = traitScope.getDeclaredFields(); + typeToFieldCache.put(traitScope, fields); + } + return fields; + } + private boolean isDeprecatedFieldAccess(Collection typeScopes, String variableName) { boolean isDeprecated = false; for (TypeScope typeScope : typeScopes) { Collection declaredFields = null; if (typeScope instanceof ClassScope) { ClassScope classScope = (ClassScope) typeScope; - declaredFields = classScope.getDeclaredFields(); + declaredFields = getFields(classScope); } else if (typeScope instanceof TraitScope) { TraitScope traitScope = (TraitScope) typeScope; - declaredFields = traitScope.getDeclaredFields(); + declaredFields = getFields(traitScope); } if (declaredFields != null) { for (org.netbeans.modules.php.editor.model.FieldElement fieldElement : declaredFields) { @@ -659,10 +690,20 @@ super.visit(node); } + private final Map> typeToConstantCache = new WeakHashMap>(); + private Collection getConstants(TypeScope typeScope) { + Collection constants = typeToConstantCache.get(typeScope); + if (constants == null) { + constants = typeScope.getDeclaredConstants(); + typeToConstantCache.put(typeScope, constants); + } + return constants; + } + private boolean isDeprecatedConstantAccess(Collection typeScopes, String constantName) { boolean isDeprecated = false; for (TypeScope typeScope : typeScopes) { - for (ClassConstantElement constantElement : typeScope.getDeclaredConstants()) { + for (ClassConstantElement constantElement : getConstants(typeScope)) { if (constantElement.getName().equals(constantName) && constantElement.isDeprecated()) { isDeprecated = true; break;