From b2e337f6890aa27ae7b44e4aa52d1adbd6a2ec7f Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 15 Jun 2017 19:44:33 +0300 Subject: [PATCH] PY-18816 Add dedicated fields for type annotations in suitable stubs --- .../python/psi/PyAnnotationOwner.java | 3 ++ .../psi/stubs/PyAnnotationOwnerStub.java | 29 +++++++++++++ .../python/psi/stubs/PyFunctionStub.java | 3 +- .../psi/stubs/PyNamedParameterStub.java | 5 +-- .../psi/stubs/PyTargetExpressionStub.java | 5 +-- .../psi/stubs/PyTypeCommentOwnerStub.java | 29 +++++++++++++ .../PyTypeDeclarationStatementImpl.java | 6 +++ .../python/psi/PyFileElementType.java | 2 +- .../psi/impl/PyAssignmentStatementImpl.java | 6 +++ .../python/psi/impl/PyBaseElementImpl.java | 41 ++++++++++++++++++- .../python/psi/impl/PyFunctionImpl.java | 20 ++++----- .../python/psi/impl/PyNamedParameterImpl.java | 16 ++++---- .../psi/impl/PyTargetExpressionImpl.java | 19 ++++----- .../psi/impl/stubs/PyFunctionElementType.java | 24 +++++++---- .../psi/impl/stubs/PyFunctionStubImpl.java | 20 +++++++-- .../stubs/PyNamedParameterElementType.java | 8 ++-- .../impl/stubs/PyNamedParameterStubImpl.java | 11 ++++- .../stubs/PyTargetExpressionElementType.java | 19 +++++---- .../stubs/PyTargetExpressionStubImpl.java | 17 ++++++-- 19 files changed, 212 insertions(+), 71 deletions(-) create mode 100644 python/psi-api/src/com/jetbrains/python/psi/stubs/PyAnnotationOwnerStub.java create mode 100644 python/psi-api/src/com/jetbrains/python/psi/stubs/PyTypeCommentOwnerStub.java diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyAnnotationOwner.java b/python/psi-api/src/com/jetbrains/python/psi/PyAnnotationOwner.java index 952e83e00ee8..fa96afd6a16a 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyAnnotationOwner.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyAnnotationOwner.java @@ -23,4 +23,7 @@ import org.jetbrains.annotations.Nullable; public interface PyAnnotationOwner { @Nullable PyAnnotation getAnnotation(); + + @Nullable + String getAnnotationContent(); } diff --git a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyAnnotationOwnerStub.java b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyAnnotationOwnerStub.java new file mode 100644 index 000000000000..61883060cd56 --- /dev/null +++ b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyAnnotationOwnerStub.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.psi.stubs; + +import org.jetbrains.annotations.Nullable; + +/** + * @author Mikhail Golubev + */ +public interface PyAnnotationOwnerStub { + /** + * @return text of the annotation element without ":" and "->" + */ + @Nullable + String getAnnotation(); +} diff --git a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyFunctionStub.java b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyFunctionStub.java index c6cb3d179db3..416412363a20 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyFunctionStub.java +++ b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyFunctionStub.java @@ -18,9 +18,8 @@ package com.jetbrains.python.psi.stubs; import com.intellij.psi.stubs.NamedStub; import com.jetbrains.python.psi.PyFunction; -public interface PyFunctionStub extends NamedStub { +public interface PyFunctionStub extends NamedStub, PyAnnotationOwnerStub, PyTypeCommentOwnerStub { String getDocString(); String getDeprecationMessage(); - String getTypeComment(); boolean isAsync(); } \ No newline at end of file diff --git a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyNamedParameterStub.java b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyNamedParameterStub.java index 8f4e93bd3f48..d744c10e8463 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyNamedParameterStub.java +++ b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyNamedParameterStub.java @@ -21,12 +21,9 @@ package com.jetbrains.python.psi.stubs; import com.intellij.psi.stubs.NamedStub; import com.jetbrains.python.psi.PyNamedParameter; -import org.jetbrains.annotations.Nullable; -public interface PyNamedParameterStub extends NamedStub { +public interface PyNamedParameterStub extends NamedStub, PyAnnotationOwnerStub, PyTypeCommentOwnerStub { boolean isPositionalContainer(); boolean isKeywordContainer(); boolean hasDefaultValue(); - @Nullable - String getTypeComment(); } \ No newline at end of file diff --git a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java index 4f7574069f6c..2c9ce93f3586 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java +++ b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTargetExpressionStub.java @@ -24,7 +24,7 @@ import org.jetbrains.annotations.Nullable; /** * @author yole */ -public interface PyTargetExpressionStub extends NamedStub { +public interface PyTargetExpressionStub extends NamedStub, PyTypeCommentOwnerStub, PyAnnotationOwnerStub { enum InitializerType { ReferenceExpression(1), CallExpression(2), @@ -63,7 +63,4 @@ public interface PyTargetExpressionStub extends NamedStub { @Nullable String getDocString(); - - @Nullable - String getTypeComment(); } diff --git a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTypeCommentOwnerStub.java b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTypeCommentOwnerStub.java new file mode 100644 index 000000000000..aa74ce2bb310 --- /dev/null +++ b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTypeCommentOwnerStub.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.psi.stubs; + +import org.jetbrains.annotations.Nullable; + +/** + * @author Mikhail Golubev + */ +public interface PyTypeCommentOwnerStub { + /** + * @return text of the respective type comment with "# type: " prefix stripped + */ + @Nullable + String getTypeComment(); +} diff --git a/python/src/com/jetbrains/python/PyTypeDeclarationStatementImpl.java b/python/src/com/jetbrains/python/PyTypeDeclarationStatementImpl.java index 85e79386635f..106ad71b77e8 100644 --- a/python/src/com/jetbrains/python/PyTypeDeclarationStatementImpl.java +++ b/python/src/com/jetbrains/python/PyTypeDeclarationStatementImpl.java @@ -44,6 +44,12 @@ public class PyTypeDeclarationStatementImpl extends PyElementImpl implements PyT return findChildByClass(PyAnnotation.class); } + @Nullable + @Override + public String getAnnotationContent() { + return getAnnotationContentFromPsi(this); + } + @Override protected void acceptPyVisitor(PyElementVisitor pyVisitor) { pyVisitor.visitPyTypeDeclarationStatement(this); diff --git a/python/src/com/jetbrains/python/psi/PyFileElementType.java b/python/src/com/jetbrains/python/psi/PyFileElementType.java index cf6762d242f5..56458a33fe88 100644 --- a/python/src/com/jetbrains/python/psi/PyFileElementType.java +++ b/python/src/com/jetbrains/python/psi/PyFileElementType.java @@ -62,7 +62,7 @@ public class PyFileElementType extends IStubFileElementType { @Override public int getStubVersion() { // Don't forget to update versions of indexes that use the updated stub-based elements - return 60; + return 61; } @Nullable diff --git a/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java index 08281fc811a3..238534a1d321 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyAssignmentStatementImpl.java @@ -102,6 +102,12 @@ public class PyAssignmentStatementImpl extends PyElementImpl implements PyAssign return findChildByClass(PyAnnotation.class); } + @Nullable + @Override + public String getAnnotationContent() { + return getAnnotationContentFromPsi(this); + } + private static void addCandidate(List candidates, PyExpression psi) { if (psi instanceof PyParenthesizedExpression) { addCandidate(candidates, ((PyParenthesizedExpression)psi).getContainedExpression()); diff --git a/python/src/com/jetbrains/python/psi/impl/PyBaseElementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyBaseElementImpl.java index fc25e07f947e..c31a9ffd75e7 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyBaseElementImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyBaseElementImpl.java @@ -28,8 +28,11 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.jetbrains.python.PythonFileType; import com.jetbrains.python.PythonLanguage; +import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.resolve.PyResolveContext; +import com.jetbrains.python.psi.stubs.PyAnnotationOwnerStub; +import com.jetbrains.python.psi.stubs.PyTypeCommentOwnerStub; import com.jetbrains.python.psi.types.TypeEvalContext; import com.jetbrains.python.pyi.PyiUtil; import org.jetbrains.annotations.NotNull; @@ -182,7 +185,7 @@ public class PyBaseElementImpl extends StubBasedPsiElemen final PsiReference[] references; if (element instanceof PyReferenceOwner) { final PsiPolyVariantReference reference = ((PyReferenceOwner)element).getReference(resolveContext); - references = reference == null ? PsiReference.EMPTY_ARRAY : new PsiReference[] {reference}; + references = reference == null ? PsiReference.EMPTY_ARRAY : new PsiReference[]{reference}; } else { references = element.getReferences(); @@ -196,4 +199,40 @@ public class PyBaseElementImpl extends StubBasedPsiElemen } } } + + @Nullable + protected static & PyAnnotationOwner> + String getAnnotationContentFromStubOrPsi(@NotNull T elem) { + final PyAnnotationOwnerStub stub = elem.getStub(); + if (stub != null) { + return stub.getAnnotation(); + } + return getAnnotationContentFromPsi(elem); + } + + @Nullable + protected static String getAnnotationContentFromPsi(@NotNull T elem) { + final PyAnnotation annotation = elem.getAnnotation(); + if (annotation != null) { + final PyExpression annotationValue = annotation.getValue(); + if (annotationValue != null) { + return annotationValue.getText(); + } + } + return null; + } + + @Nullable + protected static & PyTypeCommentOwner> + String getTypeCommentAnnotationFromStubOrPsi(@NotNull T elem) { + final PyTypeCommentOwnerStub stub = elem.getStub(); + if (stub != null) { + return stub.getTypeComment(); + } + final PsiComment comment = elem.getTypeComment(); + if (comment != null) { + return PyTypingTypeProvider.getTypeCommentValue(comment.getText()); + } + return null; + } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index beb6c3cb6d71..ed054704cc21 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -46,9 +46,7 @@ import com.jetbrains.python.documentation.docstrings.DocStringUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.resolve.PyResolveImportUtil; import com.jetbrains.python.psi.resolve.QualifiedNameFinder; -import com.jetbrains.python.psi.stubs.PyClassStub; -import com.jetbrains.python.psi.stubs.PyFunctionStub; -import com.jetbrains.python.psi.stubs.PyTargetExpressionStub; +import com.jetbrains.python.psi.stubs.*; import com.jetbrains.python.psi.types.*; import com.jetbrains.python.sdk.PythonSdkType; import icons.PythonIcons; @@ -601,6 +599,12 @@ public class PyFunctionImpl extends PyBaseElementImpl implements return getStubOrPsiChild(PyElementTypes.ANNOTATION); } + @Nullable + @Override + public String getAnnotationContent() { + return getAnnotationContentFromStubOrPsi(this); + } + @Nullable @Override public PsiComment getTypeComment() { @@ -622,15 +626,7 @@ public class PyFunctionImpl extends PyBaseElementImpl implements @Nullable @Override public String getTypeCommentAnnotation() { - final PyFunctionStub stub = getStub(); - if (stub != null) { - return stub.getTypeComment(); - } - final PsiComment comment = getTypeComment(); - if (comment != null) { - return PyTypingTypeProvider.getTypeCommentValue(comment.getText()); - } - return null; + return getTypeCommentAnnotationFromStubOrPsi(this); } @NotNull diff --git a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java index 9c18595f9242..928009dd724a 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java @@ -191,6 +191,12 @@ public class PyNamedParameterImpl extends PyBaseElementImpl implements PyFuncti private final String myDeprecationMessage; private final boolean myAsync; private final String myTypeComment; + private final String myAnnotation; - public PyFunctionStubImpl(@Nullable String name, @Nullable String docString, @Nullable String deprecationMessage, boolean isAsync, - @Nullable String typeComment, final StubElement parent, @NotNull IStubElementType stubElementType) { + public PyFunctionStubImpl(@Nullable String name, + @Nullable String docString, + @Nullable String deprecationMessage, + boolean isAsync, + @Nullable String typeCommentContent, + @Nullable String annotation, + final StubElement parent, + @NotNull IStubElementType stubElementType) { super(parent, stubElementType); myName = name; myDocString = docString; myDeprecationMessage = deprecationMessage; myAsync = isAsync; - myTypeComment = typeComment; + myTypeComment = typeCommentContent; + myAnnotation = annotation; } @Nullable @@ -64,6 +72,12 @@ public class PyFunctionStubImpl extends StubBase implements PyFuncti return myTypeComment; } + @Nullable + @Override + public String getAnnotation() { + return myAnnotation; + } + @Override public boolean isAsync() { return myAsync; diff --git a/python/src/com/jetbrains/python/psi/impl/stubs/PyNamedParameterElementType.java b/python/src/com/jetbrains/python/psi/impl/stubs/PyNamedParameterElementType.java index 626effc7da0a..b719498eb389 100644 --- a/python/src/com/jetbrains/python/psi/impl/stubs/PyNamedParameterElementType.java +++ b/python/src/com/jetbrains/python/psi/impl/stubs/PyNamedParameterElementType.java @@ -56,7 +56,7 @@ public class PyNamedParameterElementType extends PyStubElementType impleme private final boolean myKeywordContainer; private final boolean myHasDefaultValue; private final String myTypeCommentAnnotation; + private final String myAnnotation; public PyNamedParameterStubImpl(String name, boolean isPositionalContainer, boolean isKeywordContainer, boolean hasDefaultValue, @Nullable String typeCommentAnnotation, + @Nullable String annotation, StubElement parent, IStubElementType stubElementType) { super(parent, stubElementType); @@ -46,6 +48,7 @@ public class PyNamedParameterStubImpl extends StubBase impleme myKeywordContainer = isKeywordContainer; myHasDefaultValue = hasDefaultValue; myTypeCommentAnnotation = typeCommentAnnotation; + myAnnotation = annotation; } public boolean isPositionalContainer() { @@ -65,7 +68,13 @@ public class PyNamedParameterStubImpl extends StubBase impleme public String getTypeComment() { return myTypeCommentAnnotation; } - + + @Nullable + @Override + public String getAnnotation() { + return myAnnotation; + } + public String getName() { return myName; } diff --git a/python/src/com/jetbrains/python/psi/impl/stubs/PyTargetExpressionElementType.java b/python/src/com/jetbrains/python/psi/impl/stubs/PyTargetExpressionElementType.java index e31678699ee7..8934ae3c417e 100644 --- a/python/src/com/jetbrains/python/psi/impl/stubs/PyTargetExpressionElementType.java +++ b/python/src/com/jetbrains/python/psi/impl/stubs/PyTargetExpressionElementType.java @@ -74,10 +74,12 @@ public class PyTargetExpressionElementType extends PyStubElementType imp private final QualifiedName myInitializer; private final boolean myQualified; private final String myTypeComment; - + private final String myAnnotation; + @Nullable private final String myDocString; private final CustomTargetExpressionStub myCustomStub; public PyTargetExpressionStubImpl(String name, @Nullable String docString, - @Nullable String typeComment, + @Nullable String typeComment, + @Nullable String annotation, CustomTargetExpressionStub customStub, StubElement parent) { super(parent, PyElementTypes.TARGET_EXPRESSION); myName = name; myTypeComment = typeComment; + myAnnotation = annotation; myInitializerType = InitializerType.Custom; myInitializer = null; myQualified = false; @@ -51,16 +54,18 @@ public class PyTargetExpressionStubImpl extends StubBase imp myDocString = docString; } - public PyTargetExpressionStubImpl(final String name, + public PyTargetExpressionStubImpl(final String name, @Nullable String docString, final InitializerType initializerType, final QualifiedName initializer, final boolean qualified, @Nullable String typeComment, + String annotation, final StubElement parentStub) { super(parentStub, PyElementTypes.TARGET_EXPRESSION); myName = name; myTypeComment = typeComment; + myAnnotation = annotation; assert initializerType != InitializerType.Custom; myInitializerType = initializerType; myInitializer = initializer; @@ -107,6 +112,12 @@ public class PyTargetExpressionStubImpl extends StubBase imp return myTypeComment; } + @Nullable + @Override + public String getAnnotation() { + return myAnnotation; + } + @Override public String toString() { return "PyTargetExpressionStub(name=" + myName + ")";