void (@NotNull PyFunction node) { final PyClass containingClass = node.getContainingClass(); if (containingClass == null) return; final String name = node.getName(); if (name != null && name.startsWith("_")) return; if (!isApplicable(containingClass, myTypeEvalContext)) { return; } if (node.getModifier() != null) { return; } final Map<String, Property> localProperties = containingClass.getProperties(); final Map<String, PyTargetExpression> declaredAttributes = new HashMap<>(); final Set<String> inheritedProperties = new HashSet<>(); StreamEx.of(containingClass.getClassAttributes()) .filter(attribute -> !localProperties.containsKey(attribute.getName())) .forEach(attribute -> declaredAttributes.put(attribute.getName(), attribute)); final PyFunction initMethod = containingClass.findMethodByName(PyNames.INIT, false, myTypeEvalContext); if (initMethod != null) { PyClassImpl.collectInstanceAttributes(initMethod, declaredAttributes); } for (PyClass superClass : containingClass.getAncestorClasses(myTypeEvalContext)) { final PyFunction superInit = superClass.findMethodByName(PyNames.INIT, false, myTypeEvalContext); if (superInit != null) { PyClassImpl.collectInstanceAttributes(superInit, declaredAttributes); } for (PyTargetExpression classAttr : superClass.getClassAttributes()) { declaredAttributes.put(classAttr.getName(), classAttr); } inheritedProperties.addAll(superClass.getProperties().keySet()); } final Map<String, PyTargetExpression> attributes = new HashMap<>(); PyClassImpl.collectInstanceAttributes(node, attributes); for (PyTargetExpression attribute : attributes.values()) { final String attributeName = attribute.getName(); if (attributeName == null) continue; if (!declaredAttributes.containsKey(attributeName) && !inheritedProperties.contains(attributeName) && !localProperties.containsKey(attributeName) && !isDefinedByProperty(attribute, localProperties.values(), declaredAttributes)) { final PyExpression assignedValue = attribute.findAssignedValue(); if (assignedValue == null) continue; if (expressionReferencesLocalName(assignedValue, node)) { registerProblem(attribute, PyPsiBundle.message("INSP.attribute.outside.init", attributeName), new AddFieldQuickFix(attributeName, "None", containingClass.getName(), false)); } else { registerProblem(attribute, PyPsiBundle.message("INSP.attribute.outside.init", attributeName), new PyMoveAttributeToInitQuickFix(), new AddFieldQuickFix(attributeName, "None", containingClass.getName(), false)); } } } }