introduce PyPsiFacade; extract interface from QualifiedNameResolver

This commit is contained in:
Dmitry Jemerov
2012-08-08 11:34:23 +02:00
parent 2bc06ba5c4
commit 46fee0c166
10 changed files with 107 additions and 13 deletions
+1
View File
@@ -8,6 +8,7 @@
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="core-api" />
<orderEntry type="module" module-name="projectModel-api" />
</component>
</module>
@@ -0,0 +1,19 @@
package com.jetbrains.python.psi;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.resolve.QualifiedNameResolver;
/**
* @author yole
*/
public abstract class PyPsiFacade {
public static PyPsiFacade getInstance(Project project) {
return ServiceManager.getService(project, PyPsiFacade.class);
}
public abstract QualifiedNameResolver qualifiedNameResolver(String qNameString);
public abstract QualifiedNameResolver qualifiedNameResolver(PyQualifiedName qualifiedName);
}
@@ -0,0 +1,41 @@
package com.jetbrains.python.psi.resolve;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFileSystemItem;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author yole
*/
public interface QualifiedNameResolver {
QualifiedNameResolver fromElement(@NotNull PsiElement foothold);
QualifiedNameResolver fromModule(@NotNull Module module);
QualifiedNameResolver withAllModules();
QualifiedNameResolver withSdk(Sdk sdk);
QualifiedNameResolver withRelative(int relativeLevel);
QualifiedNameResolver withoutRoots();
QualifiedNameResolver withPlainDirectories();
@NotNull
List<PsiFileSystemItem> resultsAsList();
@Nullable
PsiFileSystemItem firstResult();
@NotNull
<T extends PsiElement> List<T> resultsOfType(Class<T> clazz);
@Nullable
<T extends PsiElement> T firstResultOfType(Class<T> clazz);
}
@@ -412,6 +412,9 @@
<projectService serviceInterface="com.jetbrains.python.debugger.PySignatureCacheManager"
serviceImplementation="com.jetbrains.python.debugger.PySignatureCacheManagerImpl"/>
<projectService serviceInterface="com.jetbrains.python.psi.PyPsiFacade"
serviceImplementation="com.jetbrains.python.psi.impl.PyPsiFacadeImpl"/>
<!-- Cython -->
<lang.parserDefinition language="Cython" implementationClass="com.jetbrains.cython.parser.CythonParserDefinition"/>
<lang.syntaxHighlighterFactory key="Cython" implementationClass="com.jetbrains.cython.CythonSyntaxHighlighterFactory"/>
@@ -11,6 +11,7 @@ import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.jetbrains.python.psi.resolve.QualifiedNameResolver;
import com.jetbrains.python.psi.resolve.QualifiedNameResolverImpl;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -109,7 +110,7 @@ public abstract class QtFileType implements FileType, INativeFileType {
@Nullable
private static String findToolInPackage(String toolName, Module module, Sdk sdk, String name) {
QualifiedNameResolver visitor = new QualifiedNameResolver(name).fromModule(module).withSdk(sdk);
QualifiedNameResolver visitor = new QualifiedNameResolverImpl(name).fromModule(module).withSdk(sdk);
List<PsiDirectory> elements = visitor.resultsOfType(PsiDirectory.class);
for (PsiDirectory directory : elements) {
VirtualFile tool = directory.getVirtualFile().findChild(toolName + ".exe");
@@ -4,6 +4,7 @@ import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.resolve.QualifiedNameResolver;
import com.jetbrains.python.psi.resolve.QualifiedNameResolverImpl;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
import org.jetbrains.annotations.Nullable;
@@ -24,7 +25,7 @@ public abstract class PyPsiPath {
@Nullable
@Override
public PsiElement resolve(PsiElement context) {
QualifiedNameResolver visitor = new QualifiedNameResolver(myQualifiedName).fromElement(context);
QualifiedNameResolver visitor = new QualifiedNameResolverImpl(myQualifiedName).fromElement(context);
return visitor.firstResult();
}
}
@@ -0,0 +1,20 @@
package com.jetbrains.python.psi.impl;
import com.jetbrains.python.psi.PyPsiFacade;
import com.jetbrains.python.psi.resolve.QualifiedNameResolver;
import com.jetbrains.python.psi.resolve.QualifiedNameResolverImpl;
/**
* @author yole
*/
public class PyPsiFacadeImpl extends PyPsiFacade {
@Override
public QualifiedNameResolver qualifiedNameResolver(String qNameString) {
return new QualifiedNameResolverImpl(qNameString);
}
@Override
public QualifiedNameResolver qualifiedNameResolver(PyQualifiedName qualifiedName) {
return new QualifiedNameResolverImpl(qualifiedName);
}
}
@@ -17,10 +17,7 @@ import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.impl.PyReferenceExpressionImpl;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.QualifiedNameResolver;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
import com.jetbrains.python.psi.resolve.ResolveImportUtil;
import com.jetbrains.python.psi.resolve.*;
import com.jetbrains.python.psi.types.PyModuleType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -249,7 +246,7 @@ public class PyImportReference extends PyReferenceImpl {
}
private void fillFromQName(PyQualifiedName thisQName, InsertHandler<LookupElement> insertHandler) {
QualifiedNameResolver visitor = new QualifiedNameResolver(thisQName).fromElement(myCurrentFile);
QualifiedNameResolver visitor = new QualifiedNameResolverImpl(thisQName).fromElement(myCurrentFile);
for (PsiDirectory dir : visitor.resultsOfType(PsiDirectory.class)) {
fillFromDir(dir, insertHandler);
}
@@ -28,7 +28,7 @@ import java.util.Set;
*
* @author yole
*/
public class QualifiedNameResolver implements RootVisitor {
public class QualifiedNameResolverImpl implements RootVisitor, QualifiedNameResolver {
boolean myCheckForPackage = true;
@Nullable private Module myModule;
private PsiFile myFootholdFile;
@@ -41,14 +41,15 @@ public class QualifiedNameResolver implements RootVisitor {
private boolean myWithoutRoots;
private Sdk myWithSdk;
public QualifiedNameResolver(@NotNull String qNameString) {
public QualifiedNameResolverImpl(@NotNull String qNameString) {
myQualifiedName = PyQualifiedName.fromDottedString(qNameString);
}
public QualifiedNameResolver(@NotNull PyQualifiedName qName) {
public QualifiedNameResolverImpl(@NotNull PyQualifiedName qName) {
myQualifiedName = qName;
}
@Override
public QualifiedNameResolver fromElement(@NotNull PsiElement foothold) {
if (foothold instanceof PsiDirectory) {
myFootholdFile = (PsiFile)PyUtil.turnDirIntoInit(foothold);
@@ -64,6 +65,7 @@ public class QualifiedNameResolver implements RootVisitor {
return this;
}
@Override
public QualifiedNameResolver fromModule(@NotNull Module module) {
setModule(module);
myPsiManager = PsiManager.getInstance(module.getProject());
@@ -77,6 +79,7 @@ public class QualifiedNameResolver implements RootVisitor {
}
}
@Override
public QualifiedNameResolver withAllModules() {
myVisitAllModules = true;
return this;
@@ -88,6 +91,7 @@ public class QualifiedNameResolver implements RootVisitor {
* @param sdk the SDK in which the name should be searched.
* @return this
*/
@Override
public QualifiedNameResolver withSdk(Sdk sdk) {
myWithSdk = sdk;
return this;
@@ -99,6 +103,7 @@ public class QualifiedNameResolver implements RootVisitor {
* @param relativeLevel if >= 0, we try to resolve at the specified number of levels above the current file.
* @return this
*/
@Override
public QualifiedNameResolver withRelative(int relativeLevel) {
myRelativeLevel = relativeLevel;
return this;
@@ -109,6 +114,7 @@ public class QualifiedNameResolver implements RootVisitor {
*
* @return this
*/
@Override
public QualifiedNameResolver withoutRoots() {
myWithoutRoots = true;
return this;
@@ -120,6 +126,7 @@ public class QualifiedNameResolver implements RootVisitor {
*
* @return
*/
@Override
public QualifiedNameResolver withPlainDirectories() {
myCheckForPackage = false;
return this;
@@ -144,6 +151,7 @@ public class QualifiedNameResolver implements RootVisitor {
return true;
}
@Override
@NotNull
public List<PsiFileSystemItem> resultsAsList() {
if (myFootholdFile != null && !myFootholdFile.isValid()) {
@@ -206,12 +214,14 @@ public class QualifiedNameResolver implements RootVisitor {
return resultList;
}
@Override
@Nullable
public PsiFileSystemItem firstResult() {
final List<PsiFileSystemItem> results = resultsAsList();
return results.size() > 0 ? results.get(0) : null;
}
@Override
@NotNull
public <T extends PsiElement> List<T> resultsOfType(Class<T> clazz) {
List<T> result = new ArrayList<T>();
@@ -224,6 +234,7 @@ public class QualifiedNameResolver implements RootVisitor {
return result;
}
@Override
@Nullable
public <T extends PsiElement> T firstResultOfType(Class<T> clazz) {
final List<T> list = resultsOfType(clazz);
@@ -204,7 +204,7 @@ public class ResolveImportUtil {
}
try {
beingImported.add(marker);
final QualifiedNameResolver visitor = new QualifiedNameResolver(qualifiedName).fromElement(sourceFile);
final QualifiedNameResolver visitor = new QualifiedNameResolverImpl(qualifiedName).fromElement(sourceFile);
if (relativeLevel > 0) {
// "from ...module import"
visitor.withRelative(relativeLevel).withoutRoots();
@@ -243,7 +243,7 @@ public class ResolveImportUtil {
final PyQualifiedName containingPath = findCanonicalImportPath(containingDirectory, null);
if (containingPath != null && containingPath.getComponentCount() > 0) {
final PyQualifiedName absolutePath = containingPath.append(qualifiedName.toString());
final QualifiedNameResolver absoluteVisitor = new QualifiedNameResolver(absolutePath).fromElement(foothold);
final QualifiedNameResolver absoluteVisitor = new QualifiedNameResolverImpl(absolutePath).fromElement(foothold);
return absoluteVisitor.resultsAsList();
}
}
@@ -253,7 +253,7 @@ public class ResolveImportUtil {
@Nullable
public static PsiElement resolveModuleInRoots(@NotNull PyQualifiedName moduleQualifiedName, @Nullable PsiElement foothold) {
if (foothold == null) return null;
QualifiedNameResolver visitor = new QualifiedNameResolver(moduleQualifiedName).fromElement(foothold);
QualifiedNameResolver visitor = new QualifiedNameResolverImpl(moduleQualifiedName).fromElement(foothold);
return visitor.firstResult();
}