@Override public PyType getReferenceType( @NotNull PsiElement referenceTarget, TypeEvalContext context, @Nullable PsiElement anchor) { if (referenceTarget instanceof PyTargetExpression) { final PyTargetExpression target = (PyTargetExpression) referenceTarget; if (context.maySwitchToAST(target)) { // XXX: Requires switching from stub to AST final PyAnnotation annotation = target.getAnnotation(); if (annotation != null) { final PyExpression value = annotation.getValue(); if (value != null) { return getType(value, new Context(context)); } return null; } } final String comment = target.getTypeCommentAnnotation(); if (comment != null) { final PyType type = getStringBasedType(comment, referenceTarget, new Context(context)); if (type instanceof PyTupleType) { final PyTupleExpression tupleExpr = PsiTreeUtil.getParentOfType(target, PyTupleExpression.class); if (tupleExpr != null) { return PyTypeChecker.getTargetTypeFromTupleAssignment( target, tupleExpr, (PyTupleType) type); } } return type; } } return null; }
@NotNull public QualifiedResolveResult followAssignmentsChain(PyResolveContext resolveContext) { PyReferenceExpression seeker = this; QualifiedResolveResult ret = null; List<PyExpression> qualifiers = new ArrayList<PyExpression>(); PyExpression qualifier = seeker.getQualifier(); if (qualifier != null) { qualifiers.add(qualifier); } Set<PsiElement> visited = new HashSet<PsiElement>(); visited.add(this); SEARCH: while (ret == null) { ResolveResult[] targets = seeker.getReference(resolveContext).multiResolve(false); for (ResolveResult target : targets) { PsiElement elt = target.getElement(); if (elt instanceof PyTargetExpression) { PsiElement assigned_from = null; final PyTargetExpression expr = (PyTargetExpression) elt; final TypeEvalContext context = resolveContext.getTypeEvalContext(); if (context.maySwitchToAST(expr) || expr.getStub() == null) { assigned_from = expr.findAssignedValue(); } // TODO: Maybe findAssignedValueByStub() should become a part of the PyTargetExpression // interface else if (elt instanceof PyTargetExpressionImpl) { assigned_from = ((PyTargetExpressionImpl) elt).findAssignedValueByStub(context); } if (assigned_from instanceof PyReferenceExpression) { if (visited.contains(assigned_from)) { break; } visited.add(assigned_from); seeker = (PyReferenceExpression) assigned_from; if (seeker.getQualifier() != null) { qualifiers.add(seeker.getQualifier()); } continue SEARCH; } else if (assigned_from != null) ret = new QualifiedResolveResultImpl(assigned_from, qualifiers, false); } else if (ret == null && elt instanceof PyElement && target.isValidResult()) { // remember this result, but a further reference may be the next resolve result ret = new QualifiedResolveResultImpl( elt, qualifiers, target instanceof ImplicitResolveResult); } } // all resolve results checked, reassignment not detected, nothing more to do break; } if (ret == null) ret = EMPTY_RESULT; return ret; }
@Override public void visitPyNonlocalStatement(final PyNonlocalStatement node) { for (PyTargetExpression var : node.getVariables()) { final String name = var.getName(); final ScopeOwner owner = ScopeUtil.getDeclarationScopeOwner(var, name); if (owner == null || owner instanceof PyFile) { registerProblem( var, PyBundle.message("INSP.unbound.nonlocal.variable", name), ProblemHighlightType.GENERIC_ERROR_OR_WARNING); } } }
@Nullable private static PyType getTypeFromTargetExpression( @NotNull PyTargetExpression expression, @NotNull Context context) { // XXX: Requires switching from stub to AST final PyExpression assignedValue = expression.findAssignedValue(); return assignedValue != null ? getTypeForResolvedElement(assignedValue, context) : null; }
@Override protected void moveOffsetAfter(boolean success) { if (success && (myPanel != null && myPanel.getInitPlace() != InitPlace.SAME_METHOD) || myOperation.getInplaceInitPlace() != InitPlace.SAME_METHOD) { final AccessToken accessToken = ApplicationManager.getApplication().acquireWriteActionLock(getClass()); try { final PyAssignmentStatement initializer = PsiTreeUtil.getParentOfType(myTarget, PyAssignmentStatement.class); assert initializer != null; final Function<String, PyStatement> callback = FunctionUtil.<String, PyStatement>constant(initializer); final PyClass pyClass = PyUtil.getContainingClassOrSelf(initializer); InitPlace initPlace = myPanel != null ? myPanel.getInitPlace() : myOperation.getInplaceInitPlace(); if (initPlace == InitPlace.CONSTRUCTOR) { AddFieldQuickFix.addFieldToInit(myProject, pyClass, "", callback); } else if (initPlace == InitPlace.SET_UP) { addFieldToSetUp(pyClass, callback); } if (myOperation.getOccurrences().size() > 0) { initializer.delete(); } else { final PyExpression copy = PyElementGenerator.getInstance(myProject) .createExpressionFromText( LanguageLevel.forElement(myTarget), myTarget.getText()); initializer.replace(copy); } initializer.delete(); } finally { accessToken.finish(); } } }
@NotNull private static List<PsiElement> tryResolving( @NotNull PyExpression expression, @NotNull TypeEvalContext context) { final List<PsiElement> elements = Lists.newArrayList(); if (expression instanceof PyReferenceExpression) { final PyReferenceExpression referenceExpr = (PyReferenceExpression) expression; final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context); final PsiPolyVariantReference reference = referenceExpr.getReference(resolveContext); final List<PsiElement> resolved = PyUtil.multiResolveTopPriority(reference); for (PsiElement element : resolved) { if (element instanceof PyFunction) { final PyFunction function = (PyFunction) element; if (PyUtil.isInit(function)) { final PyClass cls = function.getContainingClass(); if (cls != null) { elements.add(cls); continue; } } } else if (element instanceof PyTargetExpression) { final PyTargetExpression targetExpr = (PyTargetExpression) element; // XXX: Requires switching from stub to AST final PyExpression assignedValue = targetExpr.findAssignedValue(); if (assignedValue != null) { elements.add(assignedValue); continue; } } if (element != null) { elements.add(element); } } } return !elements.isEmpty() ? elements : Collections.singletonList(expression); }
private void buildFromAttributeDoc() { PyClass cls = PsiTreeUtil.getParentOfType(myElement, PyClass.class); assert cls != null; String type = PyUtil.isInstanceAttribute((PyExpression) myElement) ? "Instance attribute " : "Class attribute "; myProlog .addItem(type) .addWith(TagBold, $().addWith(TagCode, $(((PyTargetExpression) myElement).getName()))) .addItem(" of class ") .addWith(PythonDocumentationProvider.LinkMyClass, $().addWith(TagCode, $(cls.getName()))) .addItem(BR); final String docString = ((PyTargetExpression) myElement).getDocStringValue(); if (docString != null) { addFormattedDocString(myElement, docString, myBody, myEpilog); } }
@Override protected PsiElement checkLocalScope() { return myTarget.getContainingFile(); }