From 02c18e9429aa6be7db0fe3dac187b3655bd243eb Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Tue, 29 Aug 2017 18:10:07 +0300 Subject: [PATCH] Store parameter default value text in stub. Avoid stub-to-ast switch while building parameter presentable text. --- .../src/com/jetbrains/python/PyNames.java | 1 + .../com/jetbrains/python/psi/PyParameter.java | 5 +++-- .../psi/stubs/PyNamedParameterStub.java | 6 ++++-- .../psi/stubs/PyTupleParameterStub.java | 5 ++++- .../python/psi/types/PyCallableParameter.java | 3 +++ .../typing/PyTypingTypeProvider.java | 3 ++- .../python/psi/impl/ParamHelper.java | 13 ++++++++++++ .../python/psi/impl/PyNamedParameterImpl.java | 7 ++++--- .../psi/impl/PySingleStarParameterImpl.java | 8 ++++--- .../python/psi/impl/PyTupleParameterImpl.java | 21 ++++++++++++++++--- .../stubs/PyNamedParameterElementType.java | 17 ++++++++++----- .../impl/stubs/PyNamedParameterStubImpl.java | 18 ++++++++++------ .../stubs/PyTupleParameterElementType.java | 16 ++++++++++---- .../impl/stubs/PyTupleParameterStubImpl.java | 15 +++++++++++-- .../psi/types/PyCallableParameterImpl.java | 21 ++++++++++++------- 15 files changed, 119 insertions(+), 40 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/PyNames.java b/python/psi-api/src/com/jetbrains/python/PyNames.java index 9378db6f0e22..d42eedb7648d 100644 --- a/python/psi-api/src/com/jetbrains/python/PyNames.java +++ b/python/psi-api/src/com/jetbrains/python/PyNames.java @@ -97,6 +97,7 @@ public class PyNames { public static final String NONE = "None"; public static final String TRUE = "True"; public static final String FALSE = "False"; + public static final String ELLIPSIS = "..."; public static final String TYPES_FUNCTION_TYPE = "types.FunctionType"; public static final String TYPES_METHOD_TYPE = "types.UnboundMethodType"; diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyParameter.java b/python/psi-api/src/com/jetbrains/python/psi/PyParameter.java index 7a4bfd6fbed9..22b9bc75b5b3 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyParameter.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyParameter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -42,7 +42,8 @@ public interface PyParameter extends PyElement { boolean hasDefaultValue(); - boolean hasDefaultNoneValue(); + @Nullable + String getDefaultValueText(); /** * @return true if the parameter is the 'self' parameter of an instance attribute function or a function 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 e47d05621132..eb502d61e85d 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -21,10 +21,12 @@ 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, PyAnnotationOwnerStub, PyTypeCommentOwnerStub { boolean isPositionalContainer(); boolean isKeywordContainer(); boolean hasDefaultValue(); - boolean hasDefaultNoneValue(); + @Nullable + String getDefaultValueText(); } \ No newline at end of file diff --git a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTupleParameterStub.java b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTupleParameterStub.java index f1b21bde35df..8ff63973be9a 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTupleParameterStub.java +++ b/python/psi-api/src/com/jetbrains/python/psi/stubs/PyTupleParameterStub.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -17,10 +17,13 @@ package com.jetbrains.python.psi.stubs; import com.intellij.psi.stubs.StubElement; import com.jetbrains.python.psi.PyTupleParameter; +import org.jetbrains.annotations.Nullable; /** * Tuple parameter stub, collects nested parameters from stubs. */ public interface PyTupleParameterStub extends StubElement { boolean hasDefaultValue(); + @Nullable + String getDefaultValueText(); } diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableParameter.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableParameter.java index cdf864920b98..943b565ccd09 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableParameter.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableParameter.java @@ -50,6 +50,9 @@ public interface PyCallableParameter { boolean hasDefaultValue(); + @Nullable + String getDefaultValueText(); + boolean isPositionalContainer(); boolean isKeywordContainer(); diff --git a/python/src/com/jetbrains/python/codeInsight/typing/PyTypingTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/typing/PyTypingTypeProvider.java index 237d7ec41cb9..4a57959b4a0d 100644 --- a/python/src/com/jetbrains/python/codeInsight/typing/PyTypingTypeProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/typing/PyTypingTypeProvider.java @@ -230,7 +230,8 @@ public class PyTypingTypeProvider extends PyTypeProviderBase { return Ref.create(PyTypeUtil.toKeywordContainerType(parameter, annotationValueType)); } - if (parameter.hasDefaultNoneValue()) { + final String defaultValue = parameter.getDefaultValueText(); + if (PyNames.NONE.equals(defaultValue) || PyNames.ELLIPSIS.equals(defaultValue)) { return Ref.create(PyUnionType.union(annotationValueType, PyNoneType.INSTANCE)); } diff --git a/python/src/com/jetbrains/python/psi/impl/ParamHelper.java b/python/src/com/jetbrains/python/psi/impl/ParamHelper.java index 01fe69b72972..745952f01d29 100644 --- a/python/src/com/jetbrains/python/psi/impl/ParamHelper.java +++ b/python/src/com/jetbrains/python/psi/impl/ParamHelper.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.psi.impl; +import com.intellij.openapi.util.Pair; import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.types.PyCallableParameter; @@ -121,6 +122,18 @@ public class ParamHelper { return result.toString(); } + @Nullable + public static String getDefaultValueText(@Nullable PyExpression defaultValue) { + if (defaultValue instanceof PyStringLiteralExpression) { + final Pair quotes = PyStringLiteralUtil.getQuotes(defaultValue.getText()); + if (quotes != null) { + return quotes.getFirst() + ((PyStringLiteralExpression)defaultValue).getStringValue() + quotes.getSecond(); + } + } + + return defaultValue == null ? null : defaultValue.getText(); + } + public interface ParamWalker { /** * Is called when a tuple parameter is encountered, before visiting any parameters nested in it. diff --git a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java index 8c5b2341d3ff..cde3dcf49b6e 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java @@ -174,13 +174,14 @@ public class PyNamedParameterImpl extends PyBaseElementImpl 0) { @@ -52,6 +59,7 @@ public class PyTupleParameterImpl extends PyBaseElementImpl impleme private final boolean myHasDefaultValue; private final String myTypeCommentAnnotation; private final String myAnnotation; - private final boolean myHasDefaultNoneValue; + @Nullable + private final String myDefaultValueText; public PyNamedParameterStubImpl(String name, boolean isPositionalContainer, boolean isKeywordContainer, boolean hasDefaultValue, - boolean hasDefaultNoneValue, + @Nullable String defaultValueText, @Nullable String typeCommentAnnotation, @Nullable String annotation, StubElement parent, @@ -51,24 +52,28 @@ public class PyNamedParameterStubImpl extends StubBase impleme myHasDefaultValue = hasDefaultValue; myTypeCommentAnnotation = typeCommentAnnotation; myAnnotation = annotation; - myHasDefaultNoneValue = hasDefaultNoneValue; + myDefaultValueText = defaultValueText; } + @Override public boolean isPositionalContainer() { return myPositionalContainer; } + @Override public boolean isKeywordContainer() { return myKeywordContainer; } + @Override public boolean hasDefaultValue() { return myHasDefaultValue; } + @Nullable @Override - public boolean hasDefaultNoneValue() { - return myHasDefaultNoneValue; + public String getDefaultValueText() { + return myDefaultValueText; } @Nullable @@ -83,6 +88,7 @@ public class PyNamedParameterStubImpl extends StubBase impleme return myAnnotation; } + @Override public String getName() { return myName; } diff --git a/python/src/com/jetbrains/python/psi/impl/stubs/PyTupleParameterElementType.java b/python/src/com/jetbrains/python/psi/impl/stubs/PyTupleParameterElementType.java index 713934eec0ec..6d58f5aca0e7 100644 --- a/python/src/com/jetbrains/python/psi/impl/stubs/PyTupleParameterElementType.java +++ b/python/src/com/jetbrains/python/psi/impl/stubs/PyTupleParameterElementType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubInputStream; import com.intellij.psi.stubs.StubOutputStream; +import com.intellij.util.io.StringRef; import com.jetbrains.python.psi.PyStubElementType; import com.jetbrains.python.psi.PyTupleParameter; import com.jetbrains.python.psi.impl.PyTupleParameterImpl; @@ -37,27 +38,34 @@ public class PyTupleParameterElementType extends PyStubElementType implements PyTupleParameterStub { private final boolean myHasDefaultValue; + @Nullable + private final String myDefaultValueText; - protected PyTupleParameterStubImpl(boolean hasDefaultValue, StubElement parent) { + protected PyTupleParameterStubImpl(boolean hasDefaultValue, @Nullable String defaultValueText, StubElement parent) { super(parent, PyElementTypes.TUPLE_PARAMETER); myHasDefaultValue = hasDefaultValue; + myDefaultValueText = defaultValueText; } + @Override public boolean hasDefaultValue() { return myHasDefaultValue; } + + @Nullable + @Override + public String getDefaultValueText() { + return myDefaultValueText; + } } diff --git a/python/src/com/jetbrains/python/psi/types/PyCallableParameterImpl.java b/python/src/com/jetbrains/python/psi/types/PyCallableParameterImpl.java index 659751181cc7..ca67de13719a 100644 --- a/python/src/com/jetbrains/python/psi/types/PyCallableParameterImpl.java +++ b/python/src/com/jetbrains/python/psi/types/PyCallableParameterImpl.java @@ -112,6 +112,13 @@ public class PyCallableParameterImpl implements PyCallableParameter { return myElement == null ? myDefaultValue != null : myElement.hasDefaultValue(); } + @Nullable + @Override + public String getDefaultValueText() { + if (myElement != null) return myElement.getDefaultValueText(); + return myDefaultValue == null ? null : myDefaultValue.getText(); + } + @Override public boolean isPositionalContainer() { final PyNamedParameter namedParameter = PyUtil.as(myElement, PyNamedParameter.class); @@ -148,21 +155,19 @@ public class PyCallableParameterImpl implements PyCallableParameter { sb.append(PythonDocumentationProvider.getTypeDescription(argumentType, context)); } - final PyExpression defaultValue = getDefaultValue(); + final String defaultValue = getDefaultValueText(); if (defaultValueShouldBeIncluded(includeDefaultValue, defaultValue, argumentType)) { - final Pair quotes = defaultValue instanceof PyStringLiteralExpression - ? PyStringLiteralUtil.getQuotes(defaultValue.getText()) - : null; + final Pair quotes = PyStringLiteralUtil.getQuotes(defaultValue); sb.append("="); if (quotes != null) { - final String value = ((PyStringLiteralExpression)defaultValue).getStringValue(); + final String value = defaultValue.substring(quotes.getFirst().length(), defaultValue.length() - quotes.getSecond().length()); sb.append(quotes.getFirst()); StringUtil.escapeStringCharacters(value.length(), value, sb); sb.append(quotes.getSecond()); } else { - sb.append(PyUtil.getReadableRepr(defaultValue, true)); + sb.append(defaultValue); } } @@ -208,11 +213,11 @@ public class PyCallableParameterImpl implements PyCallableParameter { } private static boolean defaultValueShouldBeIncluded(boolean includeDefaultValue, - @Nullable PyExpression defaultValue, + @Nullable String defaultValue, @Nullable PyType type) { if (!includeDefaultValue || defaultValue == null) return false; // In case of `None` default value, it will be listed in the type as `Optional[...]` or `Union[..., None, ...]` - return type == null || !PyNames.NONE.equals(defaultValue.getText()); + return type == null || !PyNames.NONE.equals(defaultValue); } }