Cleanup of API for qualified names of expressions

Added PyQualifiedExpression.asQualifiedName() and moved utility
functions to PyPsiUtils. Expression classes can now cache the results
of calculating their qualified names.
This commit is contained in:
Andrey Vlasovskikh
2014-01-23 22:00:58 +04:00
parent b8116194e1
commit 50d1e9b3cc
21 changed files with 126 additions and 151 deletions
@@ -17,6 +17,7 @@ package com.jetbrains.python.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,6 +38,12 @@ public interface PyQualifiedExpression extends PyExpression {
*/
boolean isQualified();
/**
* Returns the qualified name for the expression if all the qualifiers are qualified expressions.
*/
@Nullable
QualifiedName asQualifiedName();
/**
* Returns the name to the right of the qualifier.
*
@@ -16,11 +16,9 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.QualifiedResolveResult;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
@@ -40,9 +38,6 @@ public interface PyReferenceExpression extends PyQualifiedExpression, PyReferenc
@NotNull
QualifiedResolveResult followAssignmentsChain(PyResolveContext resolveContext);
@Nullable
QualifiedName asQualifiedName();
@NotNull
PsiPolyVariantReference getReference();
}
@@ -23,6 +23,7 @@ import com.intellij.psi.*;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.QualifiedName;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.PyTokenTypes;
@@ -32,6 +33,7 @@ import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
@@ -375,6 +377,65 @@ public class PyPsiUtils {
return element.getTextOffset() <= element2.getTextOffset();
}
@Nullable
public static QualifiedName asQualifiedName(@Nullable PyExpression expr) {
return expr instanceof PyQualifiedExpression ? ((PyQualifiedExpression)expr).asQualifiedName() : null;
}
@Nullable
public static PyExpression getFirstQualifier(@NotNull PyQualifiedExpression expr) {
final List<PyExpression> expressions = unwindQualifiers(expr);
if (!expressions.isEmpty()) {
return expressions.get(0);
}
return null;
}
@NotNull
public static String toPath(@Nullable PyQualifiedExpression expr) {
if (expr != null) {
final QualifiedName qName = expr.asQualifiedName();
if (qName != null) {
return qName.toString();
}
final String name = expr.getName();
if (name != null) {
return name;
}
}
return "";
}
@Nullable
protected static QualifiedName asQualifiedName(@NotNull PyQualifiedExpression expr) {
return fromReferenceChain(unwindQualifiers(expr));
}
@NotNull
private static List<PyExpression> unwindQualifiers(@NotNull final PyQualifiedExpression expr) {
final List<PyExpression> path = new LinkedList<PyExpression>();
PyQualifiedExpression e = expr;
while (e != null) {
path.add(0, e);
final PyExpression q = e.getQualifier();
e = q instanceof PyQualifiedExpression ? (PyQualifiedExpression)q : null;
}
return path;
}
@Nullable
private static QualifiedName fromReferenceChain(@NotNull List<PyExpression> components) {
final List<String> componentNames = new ArrayList<String>(components.size());
for (PyExpression component : components) {
final String refName = (component instanceof PyQualifiedExpression) ? ((PyQualifiedExpression)component).getReferencedName() : null;
if (refName == null) {
return null;
}
componentNames.add(refName);
}
return QualifiedName.fromComponents(componentNames);
}
private static abstract class TopLevelVisitor extends PyRecursiveElementVisitor {
public void visitPyElement(final PyElement node) {
super.visitPyElement(node);
@@ -1,48 +0,0 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.psi.impl;
import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyQualifiedExpression;
import com.jetbrains.python.psi.PyReferenceExpression;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* @author yole
*/
public class PyQualifiedNameFactory {
@Nullable
public static QualifiedName fromReferenceChain(List<PyExpression> components) {
List<String> componentNames = new ArrayList<String>(components.size());
for (PyExpression component : components) {
final String refName = (component instanceof PyQualifiedExpression) ? ((PyQualifiedExpression)component).getReferencedName() : null;
if (refName == null) {
return null;
}
componentNames.add(refName);
}
return QualifiedName.fromComponents(componentNames);
}
@Nullable
public static QualifiedName fromExpression(PyExpression expr) {
return expr instanceof PyReferenceExpression ? ((PyReferenceExpression) expr).asQualifiedName() : null;
}
}