@Nullable private PyType getImplicitlyResolvedType( @NotNull List<Token<PyElementType>> tokens, @NotNull TypeEvalContext context, @NotNull Map<TextRange, PyType> types, @NotNull Map<PyType, TextRange> fullRanges, TextRange firstRange) { PyType type = null; QualifiedName qName = null; while (!tokens.isEmpty()) { final Token<PyElementType> token = tokens.get(0); final String name = token.getText().toString(); qName = qName != null ? qName.append(name) : QualifiedName.fromComponents(name); PsiElement module = new QualifiedNameResolverImpl(qName).fromElement(myAnchor).firstResult(); if (module == null) { break; } if (module instanceof PsiDirectory) { module = PyUtil.getPackageElement((PsiDirectory) module, myAnchor); } if (module instanceof PyTypedElement) { final PyType moduleType = context.getType((PyTypedElement) module); if (moduleType != null) { type = moduleType; types.put(token.getRange(), type); fullRanges.put( type, TextRange.create(firstRange.getStartOffset(), token.getRange().getEndOffset())); } } tokens.remove(0); } return type; }
@Nullable private PyType resolveQualifierType( @NotNull List<Token<PyElementType>> tokens, @NotNull PyFile file, @NotNull TypeEvalContext context, @NotNull Map<TextRange, PyType> types, @NotNull Map<PyType, TextRange> fullRanges, @NotNull Map<PyType, PyImportElement> imports) { if (tokens.isEmpty()) { return null; } final Token<PyElementType> firstToken = tokens.get(0); final String firstText = firstToken.getText().toString(); final TextRange firstRange = firstToken.getRange(); final List<RatedResolveResult> resolveResults = file.multiResolveName(firstText); if (resolveResults.isEmpty()) { return getImplicitlyResolvedType(tokens, context, types, fullRanges, firstRange); } final List<PyType> members = Lists.newArrayList(); for (RatedResolveResult result : resolveResults) { final PsiElement resolved = result.getElement(); PyType type = null; if (resolved instanceof PyTargetExpression) { type = PyTypingTypeProvider.getTypeFromTargetExpression( (PyTargetExpression) resolved, context); } if (type == null && resolved instanceof PyTypedElement) { type = context.getType((PyTypedElement) resolved); } if (type != null) { if (!allowResolveToType(type)) { continue; } if (type instanceof PyClassLikeType) { type = ((PyClassLikeType) type).toInstance(); } types.put(firstRange, type); fullRanges.put(type, firstRange); for (PyFromImportStatement fromImportStatement : file.getFromImports()) { for (PyImportElement importElement : fromImportStatement.getImportElements()) { if (firstText.equals(importElement.getVisibleName())) { imports.put(type, importElement); } } } for (PyImportElement importElement : file.getImportTargets()) { if (firstText.equals(importElement.getVisibleName())) { imports.put(type, importElement); } } } members.add(type); } if (!members.isEmpty()) { tokens.remove(0); } return PyUnionType.union(members); }
private ParseResult merge(@NotNull ParseResult result) { final Map<TextRange, PyType> types = new HashMap<>(); final Map<PyType, TextRange> fullRanges = new HashMap<>(); final Map<PyType, PyImportElement> imports = new HashMap<>(); types.putAll(myTypes); types.putAll(result.getTypes()); fullRanges.putAll(myFullRanges); fullRanges.putAll(result.getFullRanges()); imports.putAll(myImports); imports.putAll(result.getImports()); return new ParseResult(myElement, myType, types, fullRanges, imports); }
@Nullable @Override public ParseResult fun(@NotNull Pair<Token<PyElementType>, List<Token<PyElementType>>> value) { final Token<PyElementType> first = value.getFirst(); final List<Token<PyElementType>> rest = value.getSecond(); final TextRange firstRange = first.getRange(); final boolean unqualified = rest.isEmpty(); if (unqualified) { final ParseResult result = parseBuiltinType(first); if (result != null) { return result; } } final PsiFile file = myAnchor.getContainingFile(); final List<Token<PyElementType>> tokens = new ArrayList<>(); tokens.add(first); tokens.addAll(rest); if (file instanceof PyFile) { final PyFile pyFile = (PyFile) file; final TypeEvalContext context = TypeEvalContext.codeInsightFallback(file.getProject()); final Map<TextRange, PyType> types = new HashMap<>(); final Map<PyType, TextRange> fullRanges = new HashMap<>(); final Map<PyType, PyImportElement> imports = new HashMap<>(); PyType type = resolveQualifierType(tokens, pyFile, context, types, fullRanges, imports); PsiElement resolved = type != null ? getElement(type) : null; if (type != null) { final PyResolveContext resolveContext = PyResolveContext.defaultContext().withTypeEvalContext(context); final PyExpression expression = myAnchor instanceof PyExpression ? (PyExpression) myAnchor : null; for (Token<PyElementType> token : tokens) { final PyType qualifierType = type; type = null; final List<? extends RatedResolveResult> results = qualifierType.resolveMember( token.getText().toString(), expression, AccessDirection.READ, resolveContext); if (results != null && !results.isEmpty()) { resolved = results.get(0).getElement(); if (resolved instanceof PyTypedElement) { type = context.getType((PyTypedElement) resolved); if (type != null && !allowResolveToType(type)) { type = null; break; } if (type instanceof PyClassLikeType) { type = ((PyClassLikeType) type).toInstance(); } } } if (type == null) { break; } types.put(token.getRange(), type); fullRanges.put( type, TextRange.create(firstRange.getStartOffset(), token.getRange().getEndOffset())); } if (type != null) { return new ParseResult(resolved, type, types, fullRanges, imports); } } } return EMPTY_RESULT; }