@NotNull private static List<RatedResolveResult> resolveInDirectory( @NotNull final String referencedName, @Nullable final PsiFile containingFile, final PsiDirectory dir, boolean isFileOnly, boolean checkForPackage) { final PsiDirectory subdir = dir.findSubdirectory(referencedName); if (subdir != null && (!checkForPackage || PyUtil.isPackage(subdir, containingFile))) { return ResolveResultList.to(subdir); } final PsiFile module = findPyFileInDir(dir, referencedName); if (module != null) { return ResolveResultList.to(module); } if (!isFileOnly) { // not a subdir, not a file; could be a name in parent/__init__.py final PsiFile initPy = dir.findFile(PyNames.INIT_DOT_PY); if (initPy == containingFile) { return Collections.emptyList(); // don't dive into the file we're in } if (initPy instanceof PyFile) { return ((PyFile) initPy).multiResolveName(referencedName); } } return Collections.emptyList(); }
@Override public Icon getIcon(@NotNull PsiElement element, int flags) { if (element instanceof PsiDirectory) { final PsiDirectory directory = (PsiDirectory) element; if (PyUtil.isPackage(directory, null) && !isSpecialDirectory(directory)) { return PlatformIcons.PACKAGE_ICON; } } return null; }
/** * Finds a directory that many levels above a given file, making sure that every level has an * __init__.py. * * @param base file that works as a reference. * @param depth must be positive, 1 means the dir that contains base, 2 is one dir above, etc. * @return found directory, or null. */ @Nullable public static PsiDirectory stepBackFrom(PsiFile base, int depth) { if (depth == 0) { return base.getContainingDirectory(); } PsiDirectory result; if (base != null) { base = base.getOriginalFile(); // just to make sure result = base.getContainingDirectory(); int count = 1; while (result != null && PyUtil.isPackage(result, base)) { if (count >= depth) return result; result = result.getParentDirectory(); count += 1; } } return null; }
@Nullable @Override public List<? extends RatedResolveResult> resolveMember( @NotNull String name, @Nullable PyExpression location, @NotNull AccessDirection direction, @NotNull PyResolveContext resolveContext) { final PsiElement resolved = myImportedModule.resolve(); if (resolved != null) { final PsiFile containingFile = location != null ? location.getContainingFile() : null; List<PsiElement> elements = Collections.singletonList( ResolveImportUtil.resolveChild(resolved, name, containingFile, false, true)); final PyImportElement importElement = myImportedModule.getImportElement(); final PyFile resolvedFile = PyUtil.as(resolved, PyFile.class); if (location != null && importElement != null && PyUtil.inSameFile(location, importElement) && ResolveImportUtil.getPointInImport(location) == PointInImport.NONE && resolved instanceof PsiFileSystemItem && (resolvedFile == null || !PyUtil.isPackage(resolvedFile) || resolvedFile.getElementNamed(name) == null)) { final List<PsiElement> importedSubmodules = PyModuleType.collectImportedSubmodules((PsiFileSystemItem) resolved, location); if (importedSubmodules != null) { final Set<PsiElement> imported = Sets.newHashSet(importedSubmodules); elements = ContainerUtil.filter( elements, new Condition<PsiElement>() { @Override public boolean value(PsiElement element) { return imported.contains(element); } }); } } return ResolveImportUtil.rateResults(elements); } return null; }
public Object[] getCompletionVariants( String completionPrefix, PsiElement location, ProcessingContext context) { final List<LookupElement> result = new ArrayList<LookupElement>(); final PsiElement resolved = myImportedModule.resolve(); if (resolved instanceof PyFile) { final PyModuleType moduleType = new PyModuleType((PyFile) resolved, myImportedModule); result.addAll( moduleType.getCompletionVariantsAsLookupElements(location, context, false, false)); } else if (resolved instanceof PsiDirectory) { final PsiDirectory dir = (PsiDirectory) resolved; if (PyUtil.isPackage(dir, location)) { if (ResolveImportUtil.getPointInImport(location) != PointInImport.NONE) { result.addAll(PyModuleType.getSubModuleVariants(dir, location, null)); } else { result.addAll( PyModuleType.collectImportedSubmodulesAsLookupElements( dir, location, context.get(CTX_NAMES))); } } } return ArrayUtil.toObjectArray(result); }
@Nullable public static PyType getTypeFromTarget( @NotNull final PsiElement target, final TypeEvalContext context, PyReferenceExpression anchor) { if (!(target instanceof PyTargetExpression)) { // PyTargetExpression will ask about its type itself final PyType pyType = getReferenceTypeFromProviders(target, context, anchor); if (pyType != null) { return pyType; } } if (target instanceof PyTargetExpression) { final String name = ((PyTargetExpression) target).getName(); if (PyNames.NONE.equals(name)) { return PyNoneType.INSTANCE; } if (PyNames.TRUE.equals(name) || PyNames.FALSE.equals(name)) { return PyBuiltinCache.getInstance(target).getBoolType(); } } if (target instanceof PyFile) { return new PyModuleType((PyFile) target); } if (target instanceof PyImportedModule) { return new PyImportedModuleType((PyImportedModule) target); } if ((target instanceof PyTargetExpression || target instanceof PyNamedParameter) && anchor != null && context.allowDataFlow(anchor)) { final ScopeOwner scopeOwner = PsiTreeUtil.getStubOrPsiParentOfType(anchor, ScopeOwner.class); if (scopeOwner != null && scopeOwner == PsiTreeUtil.getStubOrPsiParentOfType(target, ScopeOwner.class)) { final String name = ((PyElement) target).getName(); if (name != null) { final PyType type = getTypeByControlFlow(name, context, anchor, scopeOwner); if (type != null) { return type; } } } } if (target instanceof PyFunction) { final PyDecoratorList decoratorList = ((PyFunction) target).getDecoratorList(); if (decoratorList != null) { final PyDecorator propertyDecorator = decoratorList.findDecorator(PyNames.PROPERTY); if (propertyDecorator != null) { return PyBuiltinCache.getInstance(target).getObjectType(PyNames.PROPERTY); } for (PyDecorator decorator : decoratorList.getDecorators()) { final QualifiedName qName = decorator.getQualifiedName(); if (qName != null && (qName.endsWith(PyNames.SETTER) || qName.endsWith(PyNames.DELETER) || qName.endsWith(PyNames.GETTER))) { return PyBuiltinCache.getInstance(target).getObjectType(PyNames.PROPERTY); } } } } if (target instanceof PyTypedElement) { return context.getType((PyTypedElement) target); } if (target instanceof PsiDirectory) { final PsiDirectory dir = (PsiDirectory) target; PsiFile file = dir.findFile(PyNames.INIT_DOT_PY); if (file != null) { return getTypeFromTarget(file, context, anchor); } if (PyUtil.isPackage(dir, anchor)) { final PsiFile containingFile = anchor.getContainingFile(); if (containingFile instanceof PyFile) { final QualifiedName qualifiedName = QualifiedNameFinder.findShortestImportableQName(dir); if (qualifiedName != null) { final PyImportedModule module = new PyImportedModule(null, (PyFile) containingFile, qualifiedName); return new PyImportedModuleType(module); } } } } return null; }