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;
  }
  @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());
  }
  @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]));
      }
    }
 @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;
 }