@Override public void doApply( @NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyWithStatement withStatement) throws IncorrectOperationException { final PsiElement colonToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.COLON); final PsiElement withToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD); final Document document = editor.getDocument(); if (colonToken == null && withToken != null) { int insertAt = withToken.getTextRange().getEndOffset(); String textToInsert = ":"; final PyWithItem lastItem = ArrayUtil.getLastElement(withStatement.getWithItems()); if (lastItem == null || lastItem.getExpression() == null) { textToInsert = " :"; processor.registerUnresolvedError(insertAt + 1); } else { final PyExpression expression = lastItem.getExpression(); insertAt = expression.getTextRange().getEndOffset(); final PsiElement asToken = PyUtil.getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD); if (asToken != null) { insertAt = asToken.getTextRange().getEndOffset(); final PyExpression target = lastItem.getTarget(); if (target != null) { insertAt = target.getTextRange().getEndOffset(); } else { textToInsert = " :"; processor.registerUnresolvedError(insertAt + 1); } } } document.insertString(insertAt, textToInsert); } }
@Override public void visitPyAssignmentStatement(PyAssignmentStatement node) { final PyExpression value = node.getAssignedValue(); if (value instanceof PyCallExpression) { final PyType type = myTypeEvalContext.getType(value); final PyExpression callee = ((PyCallExpression) value).getCallee(); if (type instanceof PyNoneType && callee != null) { final PyTypeChecker.AnalyzeCallResults analyzeCallResults = PyTypeChecker.analyzeCall(((PyCallExpression) value), myTypeEvalContext); if (analyzeCallResults != null) { final PyCallable callable = analyzeCallResults.getCallable(); if (PySdkUtil.isElementInSkeletons(callable)) { return; } if (callable instanceof PyFunction) { final PyFunction function = (PyFunction) callable; // Currently we don't infer types returned by decorators if (hasInheritors(function) || PyUtil.hasCustomDecorators(function)) { return; } } registerProblem( node, PyBundle.message("INSP.none.function.assignment", callee.getName()), new PyRemoveAssignmentQuickFix()); } } } }
@NotNull private static PyExpression invertExpression(@NotNull final PsiElement expression) { final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(expression.getProject()); if (expression instanceof PyBoolLiteralExpression) { final String value = ((PyBoolLiteralExpression) expression).getValue() ? PyNames.FALSE : PyNames.TRUE; return elementGenerator.createExpressionFromText(LanguageLevel.forElement(expression), value); } if (expression instanceof PyReferenceExpression && (PyNames.FALSE.equals(expression.getText()) || PyNames.TRUE.equals(expression.getText()))) { final String value = PyNames.TRUE.equals(expression.getText()) ? PyNames.FALSE : PyNames.TRUE; return elementGenerator.createExpressionFromText(LanguageLevel.forElement(expression), value); } else if (expression instanceof PyPrefixExpression) { if (((PyPrefixExpression) expression).getOperator() == PyTokenTypes.NOT_KEYWORD) { final PyExpression operand = ((PyPrefixExpression) expression).getOperand(); if (operand != null) return elementGenerator.createExpressionFromText( LanguageLevel.forElement(expression), operand.getText()); } } return elementGenerator.createExpressionFromText( LanguageLevel.forElement(expression), "not " + expression.getText()); }
private PsiElement performReplace( @NotNull final PsiElement declaration, final IntroduceOperation operation) { final PyExpression expression = operation.getInitializer(); final Project project = operation.getProject(); return new WriteCommandAction<PsiElement>(project, expression.getContainingFile()) { protected void run(final Result<PsiElement> result) throws Throwable { result.setResult(addDeclaration(operation, declaration)); PyExpression newExpression = createExpression(project, operation.getName(), declaration); if (operation.isReplaceAll()) { List<PsiElement> newOccurrences = new ArrayList<PsiElement>(); for (PsiElement occurrence : operation.getOccurrences()) { final PsiElement replaced = replaceExpression(occurrence, newExpression, operation); if (replaced != null) { newOccurrences.add(replaced); } } operation.setOccurrences(newOccurrences); } else { final PsiElement replaced = replaceExpression(expression, newExpression, operation); operation.setOccurrences(Collections.singletonList(replaced)); } postRefactoring(operation.getElement()); } }.execute().getResultObject(); }
@NotNull @Override public PsiPolyVariantReference getReference(PyResolveContext context) { final PsiFile file = getContainingFile(); final PyExpression qualifier = getQualifier(); // Handle import reference final PsiElement importParent = PsiTreeUtil.getParentOfType(this, PyImportElement.class, PyFromImportStatement.class); if (importParent != null) { return PyImportReference.forElement(this, importParent, context); } // Return special reference final ConsoleCommunication communication = file.getCopyableUserData(PydevConsoleRunner.CONSOLE_KEY); if (communication != null) { if (qualifier != null) { return new PydevConsoleReference(this, communication, qualifier.getText() + "."); } return new PydevConsoleReference(this, communication, ""); } if (qualifier != null) { return new PyQualifiedReference(this, context); } return new PyReferenceImpl(this, context); }
@Override public void visitPyReferenceExpression(PyReferenceExpression node) { final PyExpression qualifier = node.getQualifier(); if (qualifier == null || PyNames.CANONICAL_SELF.equals(qualifier.getText())) return; if (myTypeEvalContext.getType(qualifier) instanceof PyNamedTupleType) return; final String name = node.getName(); final List<LocalQuickFix> quickFixes = new ArrayList<LocalQuickFix>(); quickFixes.add(new PyRenameElementQuickFix()); if (name != null && name.startsWith("_") && !name.startsWith("__") && !name.endsWith("__")) { final PsiReference reference = node.getReference(getResolveContext()); if (reference == null) return; final PsiElement resolvedExpression = reference.resolve(); final PyClass resolvedClass = getClassOwner(resolvedExpression); if (resolvedExpression instanceof PyTargetExpression) { final String newName = StringUtil.trimLeading(name, '_'); if (resolvedClass != null) { final String qFixName = resolvedClass.getProperties().containsKey(newName) ? PyBundle.message("QFIX.use.property") : PyBundle.message("QFIX.add.property"); quickFixes.add(new PyAddPropertyForFieldQuickFix(qFixName)); final Collection<String> usedNames = PyRefactoringUtil.collectUsedNames(resolvedClass); if (!usedNames.contains(newName)) { quickFixes.add(new PyMakePublicQuickFix()); } } } final PyClass parentClass = getClassOwner(node); if (parentClass != null) { if (PyTestUtil.isPyTestClass(parentClass) && ignoreTestFunctions) return; if (parentClass.isSubclass(resolvedClass)) return; PyClass outerClass = getClassOwner(parentClass); while (outerClass != null) { if (outerClass.isSubclass(resolvedClass)) return; outerClass = getClassOwner(outerClass); } } final PyType type = myTypeEvalContext.getType(qualifier); final String bundleKey = type instanceof PyModuleType ? "INSP.protected.member.$0.access.module" : "INSP.protected.member.$0.access"; registerProblem( node, PyBundle.message(bundleKey, name), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, null, quickFixes.toArray(new LocalQuickFix[quickFixes.size() - 1])); } }
protected Collection<String> generateSuggestedNames(PyExpression expression) { Collection<String> candidates = new LinkedHashSet<String>() { @Override public boolean add(String s) { if (PyNames.isReserved(s)) { return false; } return super.add(s); } }; String text = expression.getText(); final Pair<PsiElement, TextRange> selection = expression.getUserData(PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE); if (selection != null) { text = selection.getSecond().substring(text); } if (expression instanceof PyCallExpression) { final PyExpression callee = ((PyCallExpression) expression).getCallee(); if (callee != null) { text = callee.getText(); } } if (text != null) { candidates.addAll(NameSuggesterUtil.generateNames(text)); } final TypeEvalContext context = TypeEvalContext.userInitiated(expression.getContainingFile()); PyType type = context.getType(expression); if (type != null && type != PyNoneType.INSTANCE) { String typeName = type.getName(); if (typeName != null) { if (type.isBuiltin()) { typeName = typeName.substring(0, 1); } candidates.addAll(NameSuggesterUtil.generateNamesByType(typeName)); } } final PyKeywordArgument kwArg = PsiTreeUtil.getParentOfType(expression, PyKeywordArgument.class); if (kwArg != null && kwArg.getValueExpression() == expression) { candidates.add(kwArg.getKeyword()); } final PyArgumentList argList = PsiTreeUtil.getParentOfType(expression, PyArgumentList.class); if (argList != null) { final CallArgumentsMapping result = argList.analyzeCall(PyResolveContext.noImplicits()); if (result.getMarkedCallee() != null) { final PyNamedParameter namedParameter = result.getPlainMappedParams().get(expression); if (namedParameter != null) { candidates.add(namedParameter.getName()); } } } return candidates; }
public PyAssignmentStatement createDeclaration(IntroduceOperation operation) { final Project project = operation.getProject(); final PyExpression initializer = operation.getInitializer(); InitializerTextBuilder builder = new InitializerTextBuilder(); initializer.accept(builder); String assignmentText = operation.getName() + " = " + builder.result(); PsiElement anchor = operation.isReplaceAll() ? findAnchor(operation.getOccurrences()) : PsiTreeUtil.getParentOfType(initializer, PyStatement.class); return createDeclaration(project, assignmentText, anchor); }
@Nullable public PyExpression getOppositeExpression(PyExpression expression) throws IllegalArgumentException { PyExpression right = getRightExpression(); PyExpression left = getLeftExpression(); if (expression.equals(left)) { return right; } if (expression.equals(right)) { return left; } throw new IllegalArgumentException( "expression " + expression + " is neither left exp or right exp"); }
/** * Looks for two standard decorators to a function, or a wrapping assignment that closely follows * it. * * @return a flag describing what was detected. */ @Nullable public Modifier getModifier() { String deconame = getClassOrStaticMethodDecorator(); if (PyNames.CLASSMETHOD.equals(deconame)) { return CLASSMETHOD; } else if (PyNames.STATICMETHOD.equals(deconame)) { return STATICMETHOD; } // implicit staticmethod __new__ PyClass cls = getContainingClass(); if (cls != null && PyNames.NEW.equals(getName()) && cls.isNewStyleClass()) { return STATICMETHOD; } // if (getStub() != null) { return getWrappersFromStub(); } String func_name = getName(); if (func_name != null) { PyAssignmentStatement assignment = PsiTreeUtil.getNextSiblingOfType(this, PyAssignmentStatement.class); if (assignment != null) { for (Pair<PyExpression, PyExpression> pair : assignment.getTargetsToValuesMapping()) { PyExpression value = pair.getSecond(); if (value instanceof PyCallExpression) { PyExpression target = pair.getFirst(); if (target instanceof PyTargetExpression && func_name.equals(target.getName())) { Pair<String, PyFunction> interpreted = interpretAsModifierWrappingCall((PyCallExpression) value, this); if (interpreted != null) { PyFunction original = interpreted.getSecond(); if (original == this) { String wrapper_name = interpreted.getFirst(); if (PyNames.CLASSMETHOD.equals(wrapper_name)) { return CLASSMETHOD; } else if (PyNames.STATICMETHOD.equals(wrapper_name)) { return STATICMETHOD; } } } } } } } } return null; }
@Override public void visitPyCallExpression(final PyCallExpression node) { // TODO: refactor, messy code final PyExpression callee = node.getCallee(); if (callee != null) { final PsiReference calleeRef = callee.getReference(); if (calleeRef != null) { final PsiElement calleeDeclaration = calleeRef.resolve(); if (calleeDeclaration instanceof PyFunction) { final PyFunction calleeFunction = (PyFunction) calleeDeclaration; final PyClass clazz = calleeFunction.getContainingClass(); if (clazz != null) { if (PyUtil.isInit(calleeFunction)) { return; // Init call should not be marked as dependency } myResult.putValue(clazz, calleeFunction); } } } } }
/** @param self should be this */ @NotNull private static List<PyAssignmentStatement> findAttributesStatic(@NotNull final PsiElement self) { final List<PyAssignmentStatement> result = new ArrayList<>(); for (final PyAssignmentStatement statement : new PsiQuery(self).siblings(PyAssignmentStatement.class).getElements()) { for (final PyQualifiedExpression targetExpression : new PsiQuery(statement.getTargets()).filter(PyQualifiedExpression.class).getElements()) { final PyExpression qualifier = targetExpression.getQualifier(); if (qualifier == null) { continue; } final PsiReference qualifierReference = qualifier.getReference(); if (qualifierReference == null) { continue; } if (qualifierReference.isReferenceTo(self)) { result.add(statement); } } } return result; }
private static boolean isAbstract(@NotNull PyClass pyClass) { final PyType metaClass = pyClass.getMetaClassType( TypeEvalContext.userInitiated(pyClass.getProject(), pyClass.getContainingFile())); if (metaClass instanceof PyClassLikeType && PyNames.ABC_META_CLASS.equals(metaClass.getName())) { return true; } if (metaClass == null) { final PyExpression metaClassExpr = as(pyClass.getMetaClassExpression(), PyReferenceExpression.class); if (metaClassExpr != null && PyNames.ABC_META_CLASS.equals(metaClassExpr.getName())) { return true; } } for (PyFunction method : pyClass.getMethods(false)) { if (PyUtil.isDecoratedAsAbstract(method)) { return true; } } return false; }
@Override public boolean isAvailableOnElement(@NotNull PsiElement element) { final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(element); if (virtualFile != null && ProjectRootManager.getInstance(element.getProject()) .getFileIndex() .isInLibraryClasses(virtualFile)) return false; if (element instanceof PyTargetExpression) { final PyAssignmentStatement assignmentStatement = PsiTreeUtil.getParentOfType(element, PyAssignmentStatement.class); if (assignmentStatement != null) { final PyExpression assignedValue = assignmentStatement.getAssignedValue(); if (assignedValue == null) return false; final String name = assignedValue.getText(); return name != null && (PyNames.TRUE.equals(name) || PyNames.FALSE.equals(name)); } } if (element instanceof PyNamedParameter) { final PyExpression defaultValue = ((PyNamedParameter) element).getDefaultValue(); if (defaultValue instanceof PyBoolLiteralExpression) return true; } return element.getParent() instanceof PyBoolLiteralExpression; }
private static boolean isInBuiltins(PyExpression callee) { if (callee instanceof PyQualifiedExpression && (((PyQualifiedExpression) callee).getQualifier() != null)) { return false; } PsiReference reference = callee.getReference(); if (reference != null) { PsiElement resolved = reference.resolve(); if (resolved != null && PyBuiltinCache.getInstance(callee).hasInBuiltins(resolved)) { return true; } } return false; }
@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; }