Fix resolution of @type tags in class docstrings to instance attributes

by getting rid of the duplicate condition inspection warned about.
This commit is contained in:
Mikhail Golubev
2018-10-08 13:34:18 +03:00
parent 31631a5175
commit 23fc949735
3 changed files with 32 additions and 14 deletions
@@ -60,21 +60,23 @@ public class DocStringParameterReference extends PsiReferenceBase<PyStringLitera
final PyFunction init = ((PyClass)owner).findMethodByName(PyNames.INIT, false, null);
if (init != null) {
PsiElement element = resolveParameter(init);
if (element == null && (myType.equals(ReferenceType.CLASS_VARIABLE) ||
myType.equals(ReferenceType.PARAMETER_TYPE)))
if (element == null && (myType.equals(ReferenceType.CLASS_VARIABLE) || myType.equals(ReferenceType.PARAMETER_TYPE))) {
element = resolveClassVariable((PyClass)owner);
if (element == null && (myType.equals(ReferenceType.INSTANCE_VARIABLE) ||
myType.equals(ReferenceType.PARAMETER_TYPE)))
}
if (element == null && (myType.equals(ReferenceType.INSTANCE_VARIABLE) || myType.equals(ReferenceType.PARAMETER_TYPE))) {
element = resolveInstanceVariable((PyClass)owner);
}
return element;
}
else {
if (myType.equals(ReferenceType.CLASS_VARIABLE) ||
myType.equals(ReferenceType.PARAMETER_TYPE))
return resolveClassVariable((PyClass)owner);
if (myType.equals(ReferenceType.INSTANCE_VARIABLE) ||
myType.equals(ReferenceType.PARAMETER_TYPE))
return resolveInstanceVariable((PyClass)owner);
PsiElement element = null;
if (myType.equals(ReferenceType.CLASS_VARIABLE) || myType.equals(ReferenceType.PARAMETER_TYPE)) {
element = resolveClassVariable((PyClass)owner);
}
if (element == null && (myType.equals(ReferenceType.INSTANCE_VARIABLE) || myType.equals(ReferenceType.PARAMETER_TYPE))) {
element = resolveInstanceVariable((PyClass)owner);
}
return element;
}
}
if (owner instanceof PyFile && myType == ReferenceType.GLOBAL_VARIABLE) {
@@ -97,8 +99,9 @@ public class DocStringParameterReference extends PsiReferenceBase<PyStringLitera
private PsiElement resolveInstanceVariable(final PyClass owner) {
final List<PyTargetExpression> attributes = owner.getInstanceAttributes();
for (PyTargetExpression element : attributes) {
if (getCanonicalText().equals(element.getName()))
if (getCanonicalText().equals(element.getName())) {
return element;
}
}
return null;
}
@@ -107,8 +110,9 @@ public class DocStringParameterReference extends PsiReferenceBase<PyStringLitera
private PsiElement resolveClassVariable(@NotNull final PyClass owner) {
final List<PyTargetExpression> attributes = owner.getClassAttributes();
for (PyTargetExpression element : attributes) {
if (getCanonicalText().equals(element.getName()))
if (getCanonicalText().equals(element.getName())) {
return element;
}
}
return null;
}
@@ -149,13 +153,15 @@ public class DocStringParameterReference extends PsiReferenceBase<PyStringLitera
if (expression != null) {
PsiReference[] references = expression.getReferences();
for (PsiReference ref : references) {
if (ref instanceof DocStringParameterReference && ((DocStringParameterReference)ref).getType().equals(myType))
if (ref instanceof DocStringParameterReference && ((DocStringParameterReference)ref).getType().equals(myType)) {
usedParameters.add(ref.getCanonicalText());
}
}
}
for (PyNamedParameter param : namedParameters) {
if (!usedParameters.contains(param.getName()))
if (!usedParameters.contains(param.getName())) {
result.add(param);
}
}
return result;
@@ -0,0 +1,8 @@
class MyClass:
"""
@type attr: str
<ref>
"""
def m(self):
self.attr = 'foo'
@@ -532,6 +532,10 @@ public class PyResolveTest extends PyResolveTestCase {
runWithDocStringFormat(DocStringFormat.GOOGLE, () -> assertResolvesTo(PyTargetExpression.class, "module_level_variable1"));
}
public void testEpyDocTypeReferenceForInstanceAttributeInClassLevelDocstring() {
runWithDocStringFormat(DocStringFormat.EPYTEXT, () -> assertResolvesTo(PyTargetExpression.class, "attr"));
}
// PY-7541
public void testLoopToUpperReassignment() {
final PsiReference ref = findReferenceByMarker();