mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 13:02:30 +07:00
PY-61639 Extracted PythonEnterHandler
GitOrigin-RevId: 8fd0c063c917e07c3f1bf98533c3de867f770ee9
This commit is contained in:
committed by
intellij-monorepo-bot
parent
1a73bd2d21
commit
25b8ebcf83
2
.idea/modules.xml
generated
2
.idea/modules.xml
generated
@@ -1149,6 +1149,8 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/python/intellij.python.pydev.iml" filepath="$PROJECT_DIR$/python/intellij.python.pydev.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/python/python-rest/intellij.python.reStructuredText.iml" filepath="$PROJECT_DIR$/python/python-rest/intellij.python.reStructuredText.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/python/python-sdk/intellij.python.sdk.iml" filepath="$PROJECT_DIR$/python/python-sdk/intellij.python.sdk.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/python/python-syntax/intellij.python.syntax.iml" filepath="$PROJECT_DIR$/python/python-syntax/intellij.python.syntax.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/python/python-syntax-core/intellij.python.syntax.core.iml" filepath="$PROJECT_DIR$/python/python-syntax-core/intellij.python.syntax.core.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/python/python-terminal/intellij.python.terminal.iml" filepath="$PROJECT_DIR$/python/python-terminal/intellij.python.terminal.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/python/tools/intellij.python.tools.iml" filepath="$PROJECT_DIR$/python/tools/intellij.python.tools.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/RegExpSupport/intellij.regexp.iml" filepath="$PROJECT_DIR$/RegExpSupport/intellij.regexp.iml" />
|
||||
|
||||
@@ -31,7 +31,9 @@ object PythonCommunityPluginModules {
|
||||
"intellij.commandInterface",
|
||||
"intellij.python.sdk",
|
||||
"intellij.python.featuresTrainer",
|
||||
"intellij.jupyter.core"
|
||||
"intellij.jupyter.core",
|
||||
"intellij.python.syntax",
|
||||
"intellij.python.syntax.core"
|
||||
)
|
||||
|
||||
const val pythonCommunityName: String = "python-ce"
|
||||
|
||||
@@ -147,5 +147,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.util.coroutines" />
|
||||
<orderEntry type="module" module-name="intellij.commandInterface" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="intellij.python.community.impl.poetry" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="intellij.python.syntax" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -19,5 +19,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.concurrency" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.util.io" />
|
||||
<orderEntry type="module" module-name="intellij.platform.debugger.impl" />
|
||||
<orderEntry type="module" module-name="intellij.python.syntax.core" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -90,6 +90,14 @@ public interface PyAstNamedParameter extends PyAstParameter, PsiNamedElement, Ps
|
||||
return ParamHelperCore.getDefaultValueText(getDefaultValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param includeDefaultValue if true, include the default value after an "=".
|
||||
* @return canonical representation of parameter.
|
||||
* Includes asterisks for *param and **param, and name.
|
||||
*/
|
||||
@NotNull
|
||||
String getRepr(boolean includeDefaultValue);
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
default PyAstNamedParameter getAsNamed() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.jetbrains.python.ast.docstring;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.ast.PyAstDocStringOwner;
|
||||
import com.jetbrains.python.ast.PyAstElement;
|
||||
import com.jetbrains.python.ast.PyAstExpressionStatement;
|
||||
@@ -35,4 +36,20 @@ public final class DocStringUtilCore {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns containing docstring expression of class definition, function definition or module.
|
||||
* Useful to test whether particular PSI element is or belongs to such docstring.
|
||||
*/
|
||||
@Nullable
|
||||
public static PyAstStringLiteralExpression getParentDefinitionDocString(@NotNull PsiElement element) {
|
||||
final PyAstDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(element, PyAstDocStringOwner.class);
|
||||
if (docStringOwner != null) {
|
||||
final PyAstStringLiteralExpression docString = docStringOwner.getDocStringExpression();
|
||||
if (PsiTreeUtil.isAncestor(docString, element, false)) {
|
||||
return docString;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.psi.util.QualifiedName;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.jetbrains.python.ast.*;
|
||||
import com.jetbrains.python.psi.PyElementType;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -47,6 +48,20 @@ public final class PyPsiUtilsCore {
|
||||
return PsiTreeUtil.skipWhitespacesAndCommentsForward(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns first child psi element with specified element type or {@code null} if no such element exists.
|
||||
* Semantically it's the same as {@code getChildByFilter(element, TokenSet.create(type), 0)}.
|
||||
*
|
||||
* @param element tree parent node
|
||||
* @param type element type expected
|
||||
* @return child element described
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) {
|
||||
final ASTNode child = element.getNode().findChildByType(type);
|
||||
return child != null ? child.getPsi() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns child element in the psi tree
|
||||
*
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package com.jetbrains.python.ast.impl;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.ast.*;
|
||||
@@ -76,6 +80,41 @@ public final class PyUtilCore {
|
||||
return unfoldParentheses(targets, new ArrayList<>(targets.length), false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the document from {@link PsiDocumentManager} using the anchor PSI element and, if it's not null,
|
||||
* passes it to the consumer function.
|
||||
* <p>
|
||||
* The document is first released from pending PSI operations and then committed after the function has been applied
|
||||
* in a {@code try/finally} block, so that subsequent operations on PSI could be performed.
|
||||
*
|
||||
* @see PsiDocumentManager#doPostponedOperationsAndUnblockDocument(Document)
|
||||
* @see PsiDocumentManager#commitDocument(Document)
|
||||
* @see #updateDocumentUnblockedAndCommitted(PsiElement, Function)
|
||||
*/
|
||||
public static void updateDocumentUnblockedAndCommitted(@NotNull PsiElement anchor, @NotNull Consumer<? super Document> consumer) {
|
||||
updateDocumentUnblockedAndCommitted(anchor, document -> {
|
||||
consumer.consume(document);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T updateDocumentUnblockedAndCommitted(@NotNull PsiElement anchor, @NotNull Function<? super Document, ? extends T> func) {
|
||||
final PsiDocumentManager manager = PsiDocumentManager.getInstance(anchor.getProject());
|
||||
// manager.getDocument(anchor.getContainingFile()) doesn't work with intention preview
|
||||
final Document document = anchor.getContainingFile().getViewProvider().getDocument();
|
||||
if (document != null) {
|
||||
manager.doPostponedOperationsAndUnblockDocument(document);
|
||||
try {
|
||||
return func.fun(document);
|
||||
}
|
||||
finally {
|
||||
manager.commitDocument(document);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PyAstLoopStatement getCorrespondingLoop(@NotNull PsiElement breakOrContinue) {
|
||||
return breakOrContinue instanceof PyAstContinueStatement || breakOrContinue instanceof PyAstBreakStatement
|
||||
|
||||
@@ -16,5 +16,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.analysis" />
|
||||
<orderEntry type="module" module-name="intellij.python.parser" exported="" />
|
||||
<orderEntry type="module" module-name="intellij.python.ast" exported="" />
|
||||
<orderEntry type="module" module-name="intellij.python.syntax.core" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -42,6 +42,7 @@ public interface PyNamedParameter extends PyAstNamedParameter, PyParameter, PsiN
|
||||
* @return canonical representation of parameter.
|
||||
* Includes asterisks for *param and **param, and name.
|
||||
*/
|
||||
@Override
|
||||
@NotNull
|
||||
default String getRepr(boolean includeDefaultValue) {
|
||||
return getRepr(includeDefaultValue, null);
|
||||
|
||||
@@ -218,8 +218,7 @@ public final class PyPsiUtils {
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) {
|
||||
final ASTNode child = element.getNode().findChildByType(type);
|
||||
return child != null ? child.getPsi() : null;
|
||||
return PyPsiUtilsCore.getFirstChildOfType(element, type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,5 +37,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.workspace.jps" />
|
||||
<orderEntry type="module" module-name="intellij.platform.backend.workspace" />
|
||||
<orderEntry type="module" module-name="intellij.python.parser" />
|
||||
<orderEntry type="module" module-name="intellij.python.syntax.core" exported="" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,4 +1,6 @@
|
||||
<idea-plugin>
|
||||
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<xi:include href="/META-INF/PythonSyntaxCore.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<readWriteAccessDetector implementation="com.jetbrains.python.findUsages.PyReadWriteAccessDetector"/>
|
||||
@@ -56,8 +58,6 @@
|
||||
|
||||
<filePropertyPusher implementation="com.jetbrains.python.psi.impl.PythonLanguageLevelPusher"/>
|
||||
|
||||
<applicationService serviceImplementation="com.jetbrains.python.codeInsight.PyCodeInsightSettings"/>
|
||||
|
||||
<weigher key="completion" implementationClass="com.jetbrains.python.codeInsight.completion.PythonCompletionWeigher" order="first"/>
|
||||
|
||||
<referencesSearch implementation="com.jetbrains.python.psi.search.PyInitReferenceSearchExecutor"/>
|
||||
@@ -76,8 +76,6 @@
|
||||
<preFormatProcessor implementation="com.jetbrains.python.formatter.PyPreFormatProcessor"/>
|
||||
<postFormatProcessor implementation="com.jetbrains.python.formatter.PyTrailingBlankLinesPostFormatProcessor"/>
|
||||
<postFormatProcessor implementation="com.jetbrains.python.formatter.PyFromImportPostFormatProcessor"/>
|
||||
<lang.whiteSpaceFormattingStrategy language="Python"
|
||||
implementationClass="com.jetbrains.python.formatter.PyWhiteSpaceFormattingStrategy"/>
|
||||
<lang.lineWrapStrategy language="Python" implementationClass="com.jetbrains.python.formatter.PyLineWrapPositionStrategy"/>
|
||||
|
||||
<lang.commenter language="Python" implementationClass="com.jetbrains.python.PythonCommenter"/>
|
||||
@@ -96,9 +94,6 @@
|
||||
|
||||
<applicationService serviceImplementation="com.jetbrains.python.documentation.PythonDocumentationMap"/>
|
||||
|
||||
<moduleService serviceImplementation="com.jetbrains.python.documentation.PyDocumentationSettings$ModuleService"/>
|
||||
<applicationService serviceImplementation="com.jetbrains.python.documentation.PyDocumentationSettings$AppService"/>
|
||||
|
||||
<applicationService serviceInterface="com.jetbrains.python.codeInsight.imports.ImportLocationHelper"
|
||||
serviceImplementation="com.jetbrains.python.codeInsight.imports.PyImportLocationHelper"/>
|
||||
|
||||
|
||||
@@ -194,11 +194,6 @@ QDOC.type.parameter.name=Type parameter {0}
|
||||
QDOC.type.parameter.kind=kind:
|
||||
QDOC.type.alias.statement.name.of.link=Type alias statement {0} of {1}
|
||||
|
||||
### Formatter
|
||||
formatter.panel.dict.alignment.do.not.align=Do not align
|
||||
formatter.panel.dict.alignment.align.on.colon=Align on colon
|
||||
formatter.panel.dict.alignment.align.on.value=Align on value
|
||||
|
||||
ignore.overridden.functions=Ignore overridden functions
|
||||
|
||||
### Intentions ###
|
||||
|
||||
@@ -14,7 +14,7 @@ import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PythonUiService;
|
||||
import com.jetbrains.python.documentation.PyDocumentationSettings;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringFormat;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringParser;
|
||||
import com.jetbrains.python.documentation.docstrings.PyDocstringGenerator;
|
||||
import com.jetbrains.python.documentation.doctest.PyDocstringFile;
|
||||
import com.jetbrains.python.inspections.quickfix.DocstringQuickFix;
|
||||
@@ -96,7 +96,7 @@ public final class PyGenerateDocstringIntention extends PyBaseIntentionAction {
|
||||
* @return false if no structured docstring format was specified initially and user didn't select any, true otherwise
|
||||
*/
|
||||
public static boolean ensureNotPlainDocstringFormat(@NotNull PsiElement anchor) {
|
||||
final Module module = DocStringUtil.getModuleForElement(anchor);
|
||||
final Module module = DocStringParser.getModuleForElement(anchor);
|
||||
if (module == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ public final class SpecifyTypeInDocstringIntention extends TypeIntention {
|
||||
|
||||
public static void startTemplate(PyDocstringGenerator generator) {
|
||||
Preconditions.checkNotNull(generator.getDocStringOwner(), "For this action docstring owner must be supplied");
|
||||
final PyStringLiteralExpression docStringExpression = generator.getDocStringExpression();
|
||||
final PyStringLiteralExpression docStringExpression = (PyStringLiteralExpression)generator.getDocStringExpression();
|
||||
assert docStringExpression != null;
|
||||
|
||||
final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(docStringExpression);
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.ast.PyAstFunction;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -127,8 +128,8 @@ public final class PySignatureCacheManagerImpl extends PySignatureCacheManager {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String findParameterType(@NotNull PyFunction function, @NotNull String name) {
|
||||
final PySignature signature = findSignature(function);
|
||||
public String findParameterType(@NotNull PyAstFunction function, @NotNull String name) {
|
||||
final PySignature signature = findSignature((PyFunction)function);
|
||||
if (signature != null) {
|
||||
return signature.getArgTypeQualifiedName(name);
|
||||
}
|
||||
@@ -137,10 +138,10 @@ public final class PySignatureCacheManagerImpl extends PySignatureCacheManager {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PySignature findSignature(@NotNull PyFunction function) {
|
||||
VirtualFile file = getFile(function);
|
||||
public PySignature findSignature(@NotNull PyAstFunction function) {
|
||||
VirtualFile file = getFile((PyFunction)function);
|
||||
if (file != null) {
|
||||
return readSignatureAttributeFromFile(file, getFunctionName(function));
|
||||
return readSignatureAttributeFromFile(file, getFunctionName((PyFunction)function));
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
|
||||
@@ -11,15 +11,17 @@ import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringFormat;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringParser;
|
||||
import com.jetbrains.python.psi.PyDocStringOwner;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyStringLiteralExpression;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
final class PyDocumentationSettingsDetector
|
||||
@ApiStatus.Internal
|
||||
public final class PyDocumentationSettingsDetector
|
||||
implements Function<Pair<Module, Collection<VirtualFile>>, PyDocumentationSettings.ServiceState> {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(PyDocumentationSettingsDetector.class);
|
||||
@@ -56,7 +58,7 @@ final class PyDocumentationSettingsDetector
|
||||
for (PyDocStringOwner owner : children) {
|
||||
final PyStringLiteralExpression docStringExpression = owner.getDocStringExpression();
|
||||
if (docStringExpression != null) {
|
||||
final DocStringFormat guessed = DocStringUtil.guessDocStringFormat(docStringExpression.getStringValue());
|
||||
final DocStringFormat guessed = DocStringParser.guessDocStringFormat(docStringExpression.getStringValue());
|
||||
if (guessed != PyDocumentationSettings.DEFAULT_DOC_STRING_FORMAT) {
|
||||
return guessed;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.PythonRuntimeService;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringFormat;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringParser;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
|
||||
import com.jetbrains.python.psi.PyIndentUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -33,12 +34,12 @@ public final class PyStructuredDocstringFormatter {
|
||||
public static PyDocumentationBuilder.DocstringFormatterRequest formatDocstring(@NotNull PsiElement element,
|
||||
@NotNull PyDocumentationBuilder.DocstringFormatterRequest docstringFormatterRequest,
|
||||
@NotNull List<String> flags) {
|
||||
Module module = DocStringUtil.getModuleForElement(element);
|
||||
Module module = DocStringParser.getModuleForElement(element);
|
||||
if (module == null) return new PyDocumentationBuilder.DocstringFormatterRequest();
|
||||
|
||||
final String docstring = docstringFormatterRequest.getBody();
|
||||
final String preparedDocstring = PyIndentUtil.removeCommonIndent(docstring, true).trim();
|
||||
final DocStringFormat format = DocStringUtil.guessDocStringFormat(preparedDocstring, element);
|
||||
final DocStringFormat format = DocStringParser.guessDocStringFormat(preparedDocstring, element);
|
||||
|
||||
if (format == DocStringFormat.PLAIN) {
|
||||
return null;
|
||||
|
||||
@@ -43,7 +43,7 @@ public final class DocStringSectionHeaderCompletionContributor extends Completio
|
||||
final PsiElement stringNode = parameters.getOriginalPosition();
|
||||
assert stringNode != null;
|
||||
final int offset = parameters.getOffset();
|
||||
final DocStringFormat format = DocStringUtil.getConfiguredDocStringFormat(file);
|
||||
final DocStringFormat format = DocStringParser.getConfiguredDocStringFormat(file);
|
||||
if (!(format == DocStringFormat.GOOGLE || format == DocStringFormat.NUMPY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public final class DocStringTagCompletionContributor extends CompletionContribut
|
||||
@NotNull ProcessingContext context,
|
||||
@NotNull CompletionResultSet result) {
|
||||
final PsiFile file = parameters.getOriginalFile();
|
||||
DocStringFormat format = DocStringUtil.getConfiguredDocStringFormat(file);
|
||||
DocStringFormat format = DocStringParser.getConfiguredDocStringFormat(file);
|
||||
if (format == DocStringFormat.EPYTEXT || format == DocStringFormat.REST) {
|
||||
int offset = parameters.getOffset();
|
||||
final String text = file.getText();
|
||||
|
||||
@@ -2,24 +2,14 @@
|
||||
package com.jetbrains.python.documentation.docstrings;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.documentation.PyDocumentationSettings;
|
||||
import com.jetbrains.python.ast.docstring.DocStringUtilCore;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import com.jetbrains.python.toolbox.Substring;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -52,11 +42,11 @@ public final class DocStringUtil {
|
||||
* @param anchor PSI element that will be used to retrieve docstring format from the containing file or the project module
|
||||
* @return structured docstring for one of supported formats or instance of {@link PlainDocString} if none was recognized.
|
||||
* @see DocStringFormat#ALL_NAMES_BUT_PLAIN
|
||||
* @see #guessDocStringFormat(String, PsiElement)
|
||||
* @see DocStringParser#guessDocStringFormat(String, PsiElement)
|
||||
*/
|
||||
@NotNull
|
||||
public static StructuredDocString parse(@NotNull String text, @Nullable PsiElement anchor) {
|
||||
final DocStringFormat format = guessDocStringFormat(text, anchor);
|
||||
final DocStringFormat format = DocStringParser.guessDocStringFormat(text, anchor);
|
||||
return parseDocStringContent(format, text);
|
||||
}
|
||||
|
||||
@@ -69,7 +59,7 @@ public final class DocStringUtil {
|
||||
*/
|
||||
@NotNull
|
||||
public static StructuredDocString parseDocString(@NotNull PyStringLiteralExpression stringLiteral) {
|
||||
return parseDocString(guessDocStringFormat(stringLiteral.getStringValue(), stringLiteral), stringLiteral);
|
||||
return parseDocString(DocStringParser.guessDocStringFormat(stringLiteral.getStringValue(), stringLiteral), stringLiteral);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -80,15 +70,7 @@ public final class DocStringUtil {
|
||||
@NotNull
|
||||
public static StructuredDocString parseDocString(@NotNull DocStringFormat format, @NotNull ASTNode node) {
|
||||
//Preconditions.checkArgument(node.getElementType() == PyTokenTypes.DOCSTRING);
|
||||
return parseDocString(format, node.getText());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stringText docstring text with possible string prefix and quotes
|
||||
*/
|
||||
@NotNull
|
||||
public static StructuredDocString parseDocString(@NotNull DocStringFormat format, @NotNull String stringText) {
|
||||
return parseDocString(format, stripPrefixAndQuotes(stringText));
|
||||
return DocStringParser.parseDocString(format, node.getText());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,120 +79,7 @@ public final class DocStringUtil {
|
||||
*/
|
||||
@NotNull
|
||||
public static StructuredDocString parseDocStringContent(@NotNull DocStringFormat format, @NotNull String stringContent) {
|
||||
return parseDocString(format, new Substring(stringContent));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static StructuredDocString parseDocString(@NotNull DocStringFormat format, @NotNull Substring content) {
|
||||
return switch (format) {
|
||||
case REST -> new SphinxDocString(content);
|
||||
case EPYTEXT -> new EpydocString(content);
|
||||
case GOOGLE -> new GoogleCodeStyleDocString(content);
|
||||
case NUMPY -> new NumpyDocString(content);
|
||||
case PLAIN -> new PlainDocString(content);
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Substring stripPrefixAndQuotes(@NotNull String text) {
|
||||
final TextRange contentRange = PyStringLiteralUtil.getContentRange(text);
|
||||
return new Substring(text, contentRange.getStartOffset(), contentRange.getEndOffset());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return docstring format inferred heuristically solely from its content. For more reliable result use anchored version
|
||||
* {@link #guessDocStringFormat(String, PsiElement)} of this method.
|
||||
* @see #guessDocStringFormat(String, PsiElement)
|
||||
*/
|
||||
@NotNull
|
||||
public static DocStringFormat guessDocStringFormat(@NotNull String text) {
|
||||
if (isLikeEpydocDocString(text)) {
|
||||
return DocStringFormat.EPYTEXT;
|
||||
}
|
||||
if (isLikeSphinxDocString(text)) {
|
||||
return DocStringFormat.REST;
|
||||
}
|
||||
if (isLikeNumpyDocstring(text)) {
|
||||
return DocStringFormat.NUMPY;
|
||||
}
|
||||
if (isLikeGoogleDocString(text)) {
|
||||
return DocStringFormat.GOOGLE;
|
||||
}
|
||||
return DocStringFormat.PLAIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param text docstring text <em>with both quotes and string prefix stripped</em>
|
||||
* @param anchor PSI element that will be used to retrieve docstring format from the containing file or the project module
|
||||
* @return docstring inferred heuristically and if unsuccessful fallback to configured format retrieved from anchor PSI element
|
||||
* @see #getConfiguredDocStringFormat(PsiElement)
|
||||
*/
|
||||
@NotNull
|
||||
public static DocStringFormat guessDocStringFormat(@NotNull String text, @Nullable PsiElement anchor) {
|
||||
final DocStringFormat guessed = guessDocStringFormat(text);
|
||||
return guessed == DocStringFormat.PLAIN && anchor != null ? getConfiguredDocStringFormatOrPlain(anchor) : guessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param anchor PSI element that will be used to retrieve docstring format from the containing file or the project module
|
||||
* @return docstring format configured for file or module containing given anchor PSI element
|
||||
* @see PyDocumentationSettings#getFormatForFile(PsiFile)
|
||||
*/
|
||||
@Nullable
|
||||
public static DocStringFormat getConfiguredDocStringFormat(@NotNull PsiElement anchor) {
|
||||
final Module module = getModuleForElement(anchor);
|
||||
if (module == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(module);
|
||||
return settings.getFormatForFile(anchor.getContainingFile());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DocStringFormat getConfiguredDocStringFormatOrPlain(@NotNull PsiElement anchor) {
|
||||
return ObjectUtils.chooseNotNull(getConfiguredDocStringFormat(anchor), DocStringFormat.PLAIN);
|
||||
}
|
||||
|
||||
public static boolean isLikeSphinxDocString(@NotNull String text) {
|
||||
return text.contains(":param ") ||
|
||||
text.contains(":key ") || text.contains(":keyword ") ||
|
||||
text.contains(":return:") || text.contains(":returns:") ||
|
||||
text.contains(":raise ") || text.contains(":raises ") || text.contains(":except ") || text.contains(":exception ") ||
|
||||
text.contains(":rtype") || text.contains(":type") ||
|
||||
text.contains(":var") || text.contains(":ivar") || text.contains(":cvar");
|
||||
}
|
||||
|
||||
public static boolean isLikeEpydocDocString(@NotNull String text) {
|
||||
return text.contains("@param ") ||
|
||||
text.contains("@kwarg ") || text.contains("@keyword ") || text.contains("@kwparam ") ||
|
||||
text.contains("@raise ") || text.contains("@raises ") || text.contains("@except ") || text.contains("@exception ") ||
|
||||
text.contains("@return:") ||
|
||||
text.contains("@rtype") || text.contains("@type") ||
|
||||
text.contains("@var") || text.contains("@ivar") || text.contains("@cvar");
|
||||
}
|
||||
|
||||
public static boolean isLikeGoogleDocString(@NotNull String text) {
|
||||
for (@NonNls String title : StringUtil.findMatches(text, GoogleCodeStyleDocString.SECTION_HEADER, 1)) {
|
||||
if (SectionBasedDocString.isValidSectionTitle(title)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isLikeNumpyDocstring(@NotNull String text) {
|
||||
final String[] lines = StringUtil.splitByLines(text, false);
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
final String line = lines[i];
|
||||
if (NumpyDocString.SECTION_HEADER.matcher(line).matches() && i > 0) {
|
||||
@NonNls final String lineBefore = lines[i - 1];
|
||||
if (SectionBasedDocString.SECTION_NAMES.contains(StringUtil.toLowerCase(lineBefore.trim()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return DocStringParser.parseDocString(format, new Substring(stringContent));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,14 +105,7 @@ public final class DocStringUtil {
|
||||
*/
|
||||
@Nullable
|
||||
public static PyStringLiteralExpression getParentDefinitionDocString(@NotNull PsiElement element) {
|
||||
final PyDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(element, PyDocStringOwner.class);
|
||||
if (docStringOwner != null) {
|
||||
final PyStringLiteralExpression docString = docStringOwner.getDocStringExpression();
|
||||
if (PsiTreeUtil.isAncestor(docString, element, false)) {
|
||||
return docString;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return (PyStringLiteralExpression)DocStringUtilCore.getParentDefinitionDocString(element);
|
||||
}
|
||||
|
||||
public static boolean isDocStringExpression(@NotNull PyExpression expression) {
|
||||
@@ -290,16 +152,4 @@ public final class DocStringUtil {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Might return {@code null} in some rare cases when PSI element doesn't have an associated module.
|
||||
// For instance, an empty IDEA project with a Python scratch file.
|
||||
@Nullable
|
||||
public static Module getModuleForElement(@NotNull PsiElement element) {
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(element.getContainingFile());
|
||||
if (module != null) {
|
||||
return module;
|
||||
}
|
||||
|
||||
return ArrayUtil.getFirstElement(ModuleManager.getInstance(element.getProject()).getModules());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.jetbrains.python.editor;
|
||||
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.jetbrains.python.psi.*;
|
||||
|
||||
public final class PyEditorHandlerConfig {
|
||||
private PyEditorHandlerConfig() {
|
||||
}
|
||||
|
||||
public static final Class[] IMPLICIT_WRAP_CLASSES = new Class[] {
|
||||
PyListLiteralExpression.class,
|
||||
PySetLiteralExpression.class,
|
||||
PyDictLiteralExpression.class,
|
||||
PyDictLiteralExpression.class,
|
||||
PyParenthesizedExpression.class,
|
||||
PyArgumentList.class,
|
||||
PyParameterList.class,
|
||||
PyGroupPattern.class,
|
||||
PySequencePattern.class,
|
||||
PyMappingPattern.class,
|
||||
PyPatternArgumentList.class,
|
||||
PyTypeParameterList.class,
|
||||
};
|
||||
public static final Class[] WRAPPABLE_CLASSES = new Class[]{
|
||||
PsiComment.class,
|
||||
PyParenthesizedExpression.class,
|
||||
PyListCompExpression.class,
|
||||
PyDictCompExpression.class,
|
||||
PySetCompExpression.class,
|
||||
PyDictLiteralExpression.class,
|
||||
PySetLiteralExpression.class,
|
||||
PyListLiteralExpression.class,
|
||||
PyArgumentList.class,
|
||||
PyParameterList.class,
|
||||
PyDecoratorList.class,
|
||||
PySliceExpression.class,
|
||||
PySubscriptionExpression.class,
|
||||
PyGeneratorExpression.class,
|
||||
PyGroupPattern.class,
|
||||
PyMappingPattern.class,
|
||||
PyPatternArgumentList.class,
|
||||
PyTypeParameterList.class,
|
||||
};
|
||||
|
||||
static final Class[] CLASSES_TO_PARENTHESISE_ON_ENTER = new Class[]{
|
||||
PyBinaryExpression.class,
|
||||
PyCallExpression.class,
|
||||
PyFromImportStatement.class,
|
||||
PyTupleExpression.class,
|
||||
PyWithStatement.class,
|
||||
PySequencePattern.class,
|
||||
PyReferenceExpression.class,
|
||||
};
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import com.intellij.psi.SmartPsiElementPointer;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.ast.PyAstStringLiteralExpression;
|
||||
import com.jetbrains.python.documentation.docstrings.PyDocstringGenerator;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -93,7 +94,7 @@ public class DocstringQuickFix extends PsiUpdateModCommandQuickFix {
|
||||
.forDocStringOwner(docStringOwner)
|
||||
.withInferredParameters(false)
|
||||
.addFirstEmptyLine();
|
||||
final PyStringLiteralExpression updated = docstringGenerator.buildAndInsert().getDocStringExpression();
|
||||
final PyAstStringLiteralExpression updated = docstringGenerator.buildAndInsert().getDocStringExpression();
|
||||
if (updated != null && editor != null) {
|
||||
final int offset = updated.getTextOffset();
|
||||
editor.getCaretModel().moveToOffset(offset);
|
||||
|
||||
@@ -727,27 +727,12 @@ public final class PyUtil {
|
||||
* @see #updateDocumentUnblockedAndCommitted(PsiElement, Function)
|
||||
*/
|
||||
public static void updateDocumentUnblockedAndCommitted(@NotNull PsiElement anchor, @NotNull Consumer<? super Document> consumer) {
|
||||
updateDocumentUnblockedAndCommitted(anchor, document -> {
|
||||
consumer.consume(document);
|
||||
return null;
|
||||
});
|
||||
PyUtilCore.updateDocumentUnblockedAndCommitted(anchor, consumer);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T updateDocumentUnblockedAndCommitted(@NotNull PsiElement anchor, @NotNull Function<? super Document, ? extends T> func) {
|
||||
final PsiDocumentManager manager = PsiDocumentManager.getInstance(anchor.getProject());
|
||||
// manager.getDocument(anchor.getContainingFile()) doesn't work with intention preview
|
||||
final Document document = anchor.getContainingFile().getViewProvider().getDocument();
|
||||
if (document != null) {
|
||||
manager.doPostponedOperationsAndUnblockDocument(document);
|
||||
try {
|
||||
return func.fun(document);
|
||||
}
|
||||
finally {
|
||||
manager.commitDocument(document);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return PyUtilCore.updateDocumentUnblockedAndCommitted(anchor, func);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringParser;
|
||||
import com.jetbrains.python.documentation.docstrings.PyDocstringGenerator;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -78,7 +78,7 @@ public class PyFunctionBuilder {
|
||||
*/
|
||||
public PyFunctionBuilder(@NotNull String name, @NotNull PsiElement settingsAnchor) {
|
||||
myName = name;
|
||||
myDocStringGenerator = PyDocstringGenerator.create(DocStringUtil.getConfiguredDocStringFormatOrPlain(settingsAnchor),
|
||||
myDocStringGenerator = PyDocstringGenerator.create(DocStringParser.getConfiguredDocStringFormatOrPlain(settingsAnchor),
|
||||
PyIndentUtil.getIndentFromSettings(settingsAnchor.getContainingFile()),
|
||||
settingsAnchor);
|
||||
mySettingAnchor = settingsAnchor;
|
||||
|
||||
@@ -64,7 +64,7 @@ public final class DocStringAnnotator extends PyAnnotator {
|
||||
|
||||
private void annotateDocStringStmt(final PyStringLiteralExpression stmt) {
|
||||
if (stmt != null) {
|
||||
final DocStringFormat format = DocStringUtil.getConfiguredDocStringFormat(stmt);
|
||||
final DocStringFormat format = DocStringParser.getConfiguredDocStringFormat(stmt);
|
||||
final String[] tags;
|
||||
if (format == DocStringFormat.EPYTEXT) {
|
||||
tags = EpydocString.ALL_TAGS;
|
||||
|
||||
24
python/python-syntax-core/intellij.python.syntax.core.iml
Normal file
24
python/python-syntax-core/intellij.python.syntax.core.iml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="intellij.platform.editor" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core" />
|
||||
<orderEntry type="module" module-name="intellij.python.parser" />
|
||||
<orderEntry type="module" module-name="intellij.platform.projectModel" />
|
||||
<orderEntry type="module" module-name="intellij.python.ast" />
|
||||
<orderEntry type="module" module-name="intellij.platform.codeStyle.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.codeStyle" />
|
||||
<orderEntry type="library" name="fastutil-min" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core.impl" />
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.projectModel.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.analysis" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,12 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<applicationService serviceImplementation="com.jetbrains.python.codeInsight.PyCodeInsightSettings"/>
|
||||
<lang.whiteSpaceFormattingStrategy language="Python"
|
||||
implementationClass="com.jetbrains.python.formatter.PyWhiteSpaceFormattingStrategy"/>
|
||||
|
||||
<moduleService serviceImplementation="com.jetbrains.python.documentation.PyDocumentationSettings$ModuleService"/>
|
||||
<applicationService serviceImplementation="com.jetbrains.python.documentation.PyDocumentationSettings$AppService"/>
|
||||
<applicationService serviceInterface="com.jetbrains.python.PythonCodeStyleService"
|
||||
serviceImplementation="com.jetbrains.python.PythonCodeStyleServiceImpl"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -0,0 +1,4 @@
|
||||
### Formatter
|
||||
formatter.panel.dict.alignment.do.not.align=Do not align
|
||||
formatter.panel.dict.alignment.align.on.colon=Align on colon
|
||||
formatter.panel.dict.alignment.align.on.value=Align on value
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.DynamicBundle;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.PropertyKey;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public final class PySyntaxCoreBundle extends DynamicBundle {
|
||||
@NonNls public static final String BUNDLE = "messages.PySyntaxCoreBundle";
|
||||
public static final PySyntaxCoreBundle INSTANCE = new PySyntaxCoreBundle();
|
||||
|
||||
private PySyntaxCoreBundle() { super(BUNDLE); }
|
||||
|
||||
@NotNull
|
||||
public static @Nls String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) {
|
||||
return INSTANCE.getMessage(key, params);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Supplier<@Nls String> messagePointer(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) {
|
||||
return INSTANCE.getLazyMessage(key, params);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package com.jetbrains.python.debugger;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.ast.PyAstFunction;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -38,10 +38,10 @@ public abstract class PySignatureCacheManager {
|
||||
public abstract void recordSignature(@NotNull PySignature signature);
|
||||
|
||||
@Nullable
|
||||
public abstract String findParameterType(@NotNull PyFunction function, @NotNull String name);
|
||||
public abstract String findParameterType(@NotNull PyAstFunction function, @NotNull String name);
|
||||
|
||||
@Nullable
|
||||
public abstract PySignature findSignature(@NotNull PyFunction function);
|
||||
public abstract PySignature findSignature(@NotNull PyAstFunction function);
|
||||
|
||||
public abstract boolean clearCache();
|
||||
}
|
||||
@@ -9,14 +9,13 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.xmlb.annotations.OptionTag;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.defaultProjectAwareService.PyDefaultProjectAwareModuleConfiguratorImpl;
|
||||
import com.jetbrains.python.ast.PyAstFile;
|
||||
import com.jetbrains.python.ast.PyAstTargetExpression;
|
||||
import com.jetbrains.python.ast.impl.PyPsiUtilsCore;
|
||||
import com.jetbrains.python.defaultProjectAwareService.PyDefaultProjectAwareService;
|
||||
import com.jetbrains.python.defaultProjectAwareService.PyDefaultProjectAwareServiceClasses;
|
||||
import com.jetbrains.python.defaultProjectAwareService.PyDefaultProjectAwareServiceModuleConfigurator;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringFormat;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyTargetExpression;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -29,11 +28,11 @@ public abstract class PyDocumentationSettings
|
||||
PyDocumentationSettings.AppService,
|
||||
PyDocumentationSettings.ModuleService> {
|
||||
|
||||
private static final PyDefaultProjectAwareServiceClasses<ServiceState, PyDocumentationSettings, AppService, ModuleService>
|
||||
@ApiStatus.Internal
|
||||
public static final PyDefaultProjectAwareServiceClasses<ServiceState, PyDocumentationSettings, AppService, ModuleService>
|
||||
SERVICE_CLASSES = new PyDefaultProjectAwareServiceClasses<>(AppService.class, ModuleService.class);
|
||||
|
||||
final static DocStringFormat DEFAULT_DOC_STRING_FORMAT = DocStringFormat.REST;
|
||||
private static final PyDocumentationSettingsDetector DETECTOR = new PyDocumentationSettingsDetector();
|
||||
|
||||
protected PyDocumentationSettings() {
|
||||
super(new ServiceState());
|
||||
@@ -43,11 +42,6 @@ public abstract class PyDocumentationSettings
|
||||
return SERVICE_CLASSES.getService(module);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PyDefaultProjectAwareServiceModuleConfigurator getConfigurator() {
|
||||
return new PyDefaultProjectAwareModuleConfiguratorImpl<>(SERVICE_CLASSES, DETECTOR);
|
||||
}
|
||||
|
||||
|
||||
public final boolean isNumpyFormat(PsiFile file) {
|
||||
return isFormat(file, DocStringFormat.NUMPY);
|
||||
@@ -58,7 +52,7 @@ public abstract class PyDocumentationSettings
|
||||
}
|
||||
|
||||
private boolean isFormat(@Nullable PsiFile file, @NotNull DocStringFormat format) {
|
||||
return file instanceof PyFile ? getFormatForFile(file) == format : getState().getFormat() == format;
|
||||
return file instanceof PyAstFile ? getFormatForFile(file) == format : getState().getFormat() == format;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -69,10 +63,10 @@ public abstract class PyDocumentationSettings
|
||||
|
||||
@Nullable
|
||||
public static DocStringFormat getFormatFromDocformatAttribute(@NotNull PsiFile file) {
|
||||
if (file instanceof PyFile) {
|
||||
final PyTargetExpression expr = ((PyFile)file).findTopLevelAttribute(PyNames.DOCFORMAT);
|
||||
if (file instanceof PyAstFile) {
|
||||
final PyAstTargetExpression expr = ((PyAstFile)file).findTopLevelAttribute(PyNames.DOCFORMAT);
|
||||
if (expr != null) {
|
||||
final String docformat = PyPsiUtils.strValue(expr.findAssignedValue());
|
||||
final String docformat = PyPsiUtilsCore.strValue(expr.findAssignedValue());
|
||||
if (docformat != null) {
|
||||
final List<String> words = StringUtil.split(docformat, " ");
|
||||
if (words.size() > 0) {
|
||||
@@ -0,0 +1,153 @@
|
||||
package com.jetbrains.python.documentation.docstrings;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.jetbrains.python.documentation.PyDocumentationSettings;
|
||||
import com.jetbrains.python.psi.PyStringLiteralUtil;
|
||||
import com.jetbrains.python.psi.StructuredDocString;
|
||||
import com.jetbrains.python.toolbox.Substring;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class DocStringParser {
|
||||
/**
|
||||
* @param stringText docstring text with possible string prefix and quotes
|
||||
*/
|
||||
@NotNull
|
||||
public static StructuredDocString parseDocString(@NotNull DocStringFormat format, @NotNull String stringText) {
|
||||
return parseDocString(format, stripPrefixAndQuotes(stringText));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static StructuredDocString parseDocString(@NotNull DocStringFormat format, @NotNull Substring content) {
|
||||
return switch (format) {
|
||||
case REST -> new SphinxDocString(content);
|
||||
case EPYTEXT -> new EpydocString(content);
|
||||
case GOOGLE -> new GoogleCodeStyleDocString(content);
|
||||
case NUMPY -> new NumpyDocString(content);
|
||||
case PLAIN -> new PlainDocString(content);
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Substring stripPrefixAndQuotes(@NotNull String text) {
|
||||
final TextRange contentRange = PyStringLiteralUtil.getContentRange(text);
|
||||
return new Substring(text, contentRange.getStartOffset(), contentRange.getEndOffset());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return docstring format inferred heuristically solely from its content. For more reliable result use anchored version
|
||||
* {@link #guessDocStringFormat(String, PsiElement)} of this method.
|
||||
* @see #guessDocStringFormat(String, PsiElement)
|
||||
*/
|
||||
@NotNull
|
||||
public static DocStringFormat guessDocStringFormat(@NotNull String text) {
|
||||
if (isLikeEpydocDocString(text)) {
|
||||
return DocStringFormat.EPYTEXT;
|
||||
}
|
||||
if (isLikeSphinxDocString(text)) {
|
||||
return DocStringFormat.REST;
|
||||
}
|
||||
if (isLikeNumpyDocstring(text)) {
|
||||
return DocStringFormat.NUMPY;
|
||||
}
|
||||
if (isLikeGoogleDocString(text)) {
|
||||
return DocStringFormat.GOOGLE;
|
||||
}
|
||||
return DocStringFormat.PLAIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param text docstring text <em>with both quotes and string prefix stripped</em>
|
||||
* @param anchor PSI element that will be used to retrieve docstring format from the containing file or the project module
|
||||
* @return docstring inferred heuristically and if unsuccessful fallback to configured format retrieved from anchor PSI element
|
||||
* @see #getConfiguredDocStringFormat(PsiElement)
|
||||
*/
|
||||
@NotNull
|
||||
public static DocStringFormat guessDocStringFormat(@NotNull String text, @Nullable PsiElement anchor) {
|
||||
final DocStringFormat guessed = guessDocStringFormat(text);
|
||||
return guessed == DocStringFormat.PLAIN && anchor != null ? getConfiguredDocStringFormatOrPlain(anchor) : guessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param anchor PSI element that will be used to retrieve docstring format from the containing file or the project module
|
||||
* @return docstring format configured for file or module containing given anchor PSI element
|
||||
* @see PyDocumentationSettings#getFormatForFile(PsiFile)
|
||||
*/
|
||||
@Nullable
|
||||
public static DocStringFormat getConfiguredDocStringFormat(@NotNull PsiElement anchor) {
|
||||
final Module module = getModuleForElement(anchor);
|
||||
if (module == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(module);
|
||||
return settings.getFormatForFile(anchor.getContainingFile());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DocStringFormat getConfiguredDocStringFormatOrPlain(@NotNull PsiElement anchor) {
|
||||
return ObjectUtils.chooseNotNull(getConfiguredDocStringFormat(anchor), DocStringFormat.PLAIN);
|
||||
}
|
||||
|
||||
public static boolean isLikeSphinxDocString(@NotNull String text) {
|
||||
return text.contains(":param ") ||
|
||||
text.contains(":key ") || text.contains(":keyword ") ||
|
||||
text.contains(":return:") || text.contains(":returns:") ||
|
||||
text.contains(":raise ") || text.contains(":raises ") || text.contains(":except ") || text.contains(":exception ") ||
|
||||
text.contains(":rtype") || text.contains(":type") ||
|
||||
text.contains(":var") || text.contains(":ivar") || text.contains(":cvar");
|
||||
}
|
||||
|
||||
public static boolean isLikeEpydocDocString(@NotNull String text) {
|
||||
return text.contains("@param ") ||
|
||||
text.contains("@kwarg ") || text.contains("@keyword ") || text.contains("@kwparam ") ||
|
||||
text.contains("@raise ") || text.contains("@raises ") || text.contains("@except ") || text.contains("@exception ") ||
|
||||
text.contains("@return:") ||
|
||||
text.contains("@rtype") || text.contains("@type") ||
|
||||
text.contains("@var") || text.contains("@ivar") || text.contains("@cvar");
|
||||
}
|
||||
|
||||
public static boolean isLikeGoogleDocString(@NotNull String text) {
|
||||
for (@NonNls String title : StringUtil.findMatches(text, GoogleCodeStyleDocString.SECTION_HEADER, 1)) {
|
||||
if (SectionBasedDocString.isValidSectionTitle(title)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isLikeNumpyDocstring(@NotNull String text) {
|
||||
final String[] lines = StringUtil.splitByLines(text, false);
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
final String line = lines[i];
|
||||
if (NumpyDocString.SECTION_HEADER.matcher(line).matches() && i > 0) {
|
||||
@NonNls final String lineBefore = lines[i - 1];
|
||||
if (SectionBasedDocString.SECTION_NAMES.contains(StringUtil.toLowerCase(lineBefore.trim()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Might return {@code null} in some rare cases when PSI element doesn't have an associated module.
|
||||
// For instance, an empty IDEA project with a Python scratch file.
|
||||
@Nullable
|
||||
public static Module getModuleForElement(@NotNull PsiElement element) {
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(element.getContainingFile());
|
||||
if (module != null) {
|
||||
return module;
|
||||
}
|
||||
|
||||
return ArrayUtil.getFirstElement(ModuleManager.getInstance(element.getProject()).getModules());
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,11 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.ast.*;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
|
||||
import com.jetbrains.python.debugger.PySignature;
|
||||
import com.jetbrains.python.debugger.PySignatureCacheManager;
|
||||
@@ -43,7 +46,7 @@ public final class PyDocstringGenerator {
|
||||
private final List<DocstringParam> myRemovedParams = new ArrayList<>();
|
||||
private final String myDocStringText;
|
||||
// Updated after buildAndInsert()
|
||||
@Nullable private final PyDocStringOwner myDocStringOwner;
|
||||
@Nullable private final PyAstDocStringOwner myDocStringOwner;
|
||||
private final String myDocStringIndent;
|
||||
private final DocStringFormat myDocStringFormat;
|
||||
private final PsiElement mySettingsAnchor;
|
||||
@@ -54,7 +57,7 @@ public final class PyDocstringGenerator {
|
||||
private boolean myParametersPrepared = false;
|
||||
private String myQuotes = TRIPLE_DOUBLE_QUOTES;
|
||||
|
||||
private PyDocstringGenerator(@Nullable PyDocStringOwner docStringOwner,
|
||||
private PyDocstringGenerator(@Nullable PyAstDocStringOwner docStringOwner,
|
||||
@Nullable String docStringText,
|
||||
@NotNull DocStringFormat format,
|
||||
@NotNull String indentation,
|
||||
@@ -68,13 +71,13 @@ public final class PyDocstringGenerator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PyDocstringGenerator forDocStringOwner(@NotNull PyDocStringOwner owner) {
|
||||
public static PyDocstringGenerator forDocStringOwner(@NotNull PyAstDocStringOwner owner) {
|
||||
String indentation = "";
|
||||
if (owner instanceof PyStatementListContainer) {
|
||||
indentation = PyIndentUtil.getElementIndent(((PyStatementListContainer)owner).getStatementList());
|
||||
if (owner instanceof PyAstStatementListContainer) {
|
||||
indentation = PyIndentUtil.getElementIndent(((PyAstStatementListContainer)owner).getStatementList());
|
||||
}
|
||||
final String docStringText = owner.getDocStringExpression() == null ? null : owner.getDocStringExpression().getText();
|
||||
return new PyDocstringGenerator(owner, docStringText, DocStringUtil.getConfiguredDocStringFormatOrPlain(owner), indentation, owner);
|
||||
return new PyDocstringGenerator(owner, docStringText, DocStringParser.getConfiguredDocStringFormatOrPlain(owner), indentation, owner);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,10 +91,10 @@ public final class PyDocstringGenerator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PyDocstringGenerator update(@NotNull PyStringLiteralExpression docString) {
|
||||
return new PyDocstringGenerator(PsiTreeUtil.getParentOfType(docString, PyDocStringOwner.class),
|
||||
public static PyDocstringGenerator update(@NotNull PyAstStringLiteralExpression docString) {
|
||||
return new PyDocstringGenerator(PsiTreeUtil.getParentOfType(docString, PyAstDocStringOwner.class),
|
||||
docString.getText(),
|
||||
DocStringUtil.getConfiguredDocStringFormatOrPlain(docString),
|
||||
DocStringParser.getConfiguredDocStringFormatOrPlain(docString),
|
||||
PyIndentUtil.getElementIndent(docString),
|
||||
docString);
|
||||
}
|
||||
@@ -114,7 +117,7 @@ public final class PyDocstringGenerator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PyDocstringGenerator withParam(@NotNull PyNamedParameter param) {
|
||||
public PyDocstringGenerator withParam(@NotNull PyAstNamedParameter param) {
|
||||
return withParam(getPreferredParameterName(param));
|
||||
}
|
||||
|
||||
@@ -125,7 +128,7 @@ public final class PyDocstringGenerator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PyDocstringGenerator withParamTypedByName(@NotNull PyNamedParameter name, @Nullable String type) {
|
||||
public PyDocstringGenerator withParamTypedByName(@NotNull PyAstNamedParameter name, @Nullable String type) {
|
||||
return withParamTypedByName(getPreferredParameterName(name), type);
|
||||
}
|
||||
|
||||
@@ -174,8 +177,8 @@ public final class PyDocstringGenerator {
|
||||
*/
|
||||
@NotNull
|
||||
public PyDocstringGenerator withInferredParameters(boolean addReturn) {
|
||||
if (myDocStringOwner instanceof PyFunction) {
|
||||
for (PyParameter param : ((PyFunction)myDocStringOwner).getParameterList().getParameters()) {
|
||||
if (myDocStringOwner instanceof PyAstFunction) {
|
||||
for (PyAstParameter param : ((PyAstFunction)myDocStringOwner).getParameterList().getParameters()) {
|
||||
if (param.getAsNamed() == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -184,12 +187,12 @@ public final class PyDocstringGenerator {
|
||||
if (StringUtil.isEmpty(paramName) || param.isSelf() || docString != null && docString.getParameters().contains(paramName)) {
|
||||
continue;
|
||||
}
|
||||
withParam((PyNamedParameter)param);
|
||||
withParam((PyAstNamedParameter)param);
|
||||
}
|
||||
final RaiseVisitor visitor = new RaiseVisitor();
|
||||
final PyStatementList statementList = ((PyFunction)myDocStringOwner).getStatementList();
|
||||
final PyAstStatementList statementList = ((PyAstFunction)myDocStringOwner).getStatementList();
|
||||
statementList.accept(visitor);
|
||||
if (!PyUtil.isInitOrNewMethod(myDocStringOwner) && (visitor.myHasReturn || addReturn)) {
|
||||
if (!PyUtilCore.isInitOrNewMethod(myDocStringOwner) && (visitor.myHasReturn || addReturn)) {
|
||||
// will add :return: placeholder in Sphinx/Epydoc docstrings
|
||||
withReturnValue(null);
|
||||
}
|
||||
@@ -233,8 +236,8 @@ public final class PyDocstringGenerator {
|
||||
|
||||
// Sanitize parameters
|
||||
PySignature signature = null;
|
||||
if (myDocStringOwner instanceof PyFunction && myUseTypesFromDebuggerSignature) {
|
||||
signature = PySignatureCacheManager.getInstance(myDocStringOwner.getProject()).findSignature((PyFunction)myDocStringOwner);
|
||||
if (myDocStringOwner instanceof PyAstFunction && myUseTypesFromDebuggerSignature) {
|
||||
signature = PySignatureCacheManager.getInstance(myDocStringOwner.getProject()).findSignature((PyAstFunction)myDocStringOwner);
|
||||
}
|
||||
final DocStringFormat format = myDocStringFormat;
|
||||
final ArrayList<DocstringParam> filtered = new ArrayList<>();
|
||||
@@ -288,18 +291,18 @@ public final class PyDocstringGenerator {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyStringLiteralExpression getDocStringExpression() {
|
||||
public PyAstStringLiteralExpression getDocStringExpression() {
|
||||
Preconditions.checkNotNull(myDocStringOwner, "For this action docstring owner must be supplied");
|
||||
return myDocStringOwner.getDocStringExpression();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private StructuredDocString getStructuredDocString() {
|
||||
return myDocStringText == null ? null : DocStringUtil.parseDocString(myDocStringFormat, myDocStringText);
|
||||
return myDocStringText == null ? null : DocStringParser.parseDocString(myDocStringFormat, myDocStringText);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPreferredParameterName(@NotNull PyNamedParameter parameter) {
|
||||
public String getPreferredParameterName(@NotNull PyAstNamedParameter parameter) {
|
||||
if (getDocStringFormat() == DocStringFormat.GOOGLE) {
|
||||
return parameter.getAsNamed().getRepr(false);
|
||||
}
|
||||
@@ -448,26 +451,26 @@ public final class PyDocstringGenerator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PyDocStringOwner buildAndInsert(@NotNull String replacementText) {
|
||||
public PyAstDocStringOwner buildAndInsert(@NotNull String replacementText) {
|
||||
Preconditions.checkNotNull(myDocStringOwner, "For this action docstring owner must be supplied");
|
||||
|
||||
final Project project = myDocStringOwner.getProject();
|
||||
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
final PyExpressionStatement replacement = elementGenerator.createDocstring(replacementText);
|
||||
PyAstElementGenerator elementGenerator = PyAstElementGenerator.getInstance(project);
|
||||
final PyAstExpressionStatement replacement = elementGenerator.createDocstring(replacementText);
|
||||
|
||||
final PyStringLiteralExpression docStringExpression = getDocStringExpression();
|
||||
final PyAstStringLiteralExpression docStringExpression = getDocStringExpression();
|
||||
if (docStringExpression != null) {
|
||||
docStringExpression.replace(replacement.getExpression());
|
||||
}
|
||||
else {
|
||||
PyStatementListContainer container = PyUtil.as(myDocStringOwner, PyStatementListContainer.class);
|
||||
PyAstStatementListContainer container = ObjectUtils.tryCast(myDocStringOwner, PyAstStatementListContainer.class);
|
||||
if (container == null) {
|
||||
throw new IllegalStateException("Should be a function or class");
|
||||
}
|
||||
final PyStatementList statements = container.getStatementList();
|
||||
final PyAstStatementList statements = container.getStatementList();
|
||||
final String indentation = PyIndentUtil.getElementIndent(statements);
|
||||
|
||||
PyUtil.updateDocumentUnblockedAndCommitted(myDocStringOwner, document -> {
|
||||
PyUtilCore.updateDocumentUnblockedAndCommitted(myDocStringOwner, document -> {
|
||||
final PsiElement beforeStatements = statements.getPrevSibling();
|
||||
String replacementWithLineBreaks = "\n" + indentation + replacementText;
|
||||
if (statements.getStatements().length > 0) {
|
||||
@@ -490,7 +493,7 @@ public final class PyDocstringGenerator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PyDocStringOwner buildAndInsert() {
|
||||
public PyAstDocStringOwner buildAndInsert() {
|
||||
Preconditions.checkNotNull(myDocStringOwner, "For this action docstring owner must be supplied");
|
||||
return buildAndInsert(buildDocString());
|
||||
}
|
||||
@@ -550,22 +553,22 @@ public final class PyDocstringGenerator {
|
||||
}
|
||||
|
||||
}
|
||||
private static class RaiseVisitor extends PyRecursiveElementVisitor {
|
||||
private static class RaiseVisitor extends PyAstRecursiveElementVisitor {
|
||||
|
||||
private boolean myHasRaise = false;
|
||||
private boolean myHasReturn = false;
|
||||
@Nullable private PyExpression myRaiseTarget = null;
|
||||
@Nullable private PyAstExpression myRaiseTarget = null;
|
||||
@Override
|
||||
public void visitPyRaiseStatement(@NotNull PyRaiseStatement node) {
|
||||
public void visitPyRaiseStatement(@NotNull PyAstRaiseStatement node) {
|
||||
myHasRaise = true;
|
||||
final PyExpression[] expressions = node.getExpressions();
|
||||
final PyAstExpression[] expressions = node.getExpressions();
|
||||
if (expressions.length > 0) {
|
||||
myRaiseTarget = expressions[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyReturnStatement(@NotNull PyReturnStatement node) {
|
||||
public void visitPyReturnStatement(@NotNull PyAstReturnStatement node) {
|
||||
myHasReturn = true;
|
||||
}
|
||||
|
||||
@@ -573,8 +576,8 @@ public final class PyDocstringGenerator {
|
||||
public String getRaiseTargetText() {
|
||||
if (myRaiseTarget != null) {
|
||||
String raiseTarget = myRaiseTarget.getText();
|
||||
if (myRaiseTarget instanceof PyCallExpression) {
|
||||
final PyExpression callee = ((PyCallExpression)myRaiseTarget).getCallee();
|
||||
if (myRaiseTarget instanceof PyAstCallExpression) {
|
||||
final PyAstExpression callee = ((PyAstCallExpression)myRaiseTarget).getCallee();
|
||||
if (callee != null) {
|
||||
raiseTarget = callee.getText();
|
||||
}
|
||||
@@ -587,7 +590,7 @@ public final class PyDocstringGenerator {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyDocStringOwner getDocStringOwner() {
|
||||
public PyAstDocStringOwner getDocStringOwner() {
|
||||
return myDocStringOwner;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.jetbrains.python.editor;
|
||||
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.jetbrains.python.ast.*;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
public final class PyEditorHandlerConfig {
|
||||
private PyEditorHandlerConfig() {
|
||||
}
|
||||
|
||||
public static final Class[] IMPLICIT_WRAP_CLASSES = new Class[] {
|
||||
PyAstListLiteralExpression.class,
|
||||
PyAstSetLiteralExpression.class,
|
||||
PyAstDictLiteralExpression.class,
|
||||
PyAstDictLiteralExpression.class,
|
||||
PyAstParenthesizedExpression.class,
|
||||
PyAstArgumentList.class,
|
||||
PyAstParameterList.class,
|
||||
PyAstGroupPattern.class,
|
||||
PyAstSequencePattern.class,
|
||||
PyAstMappingPattern.class,
|
||||
PyAstPatternArgumentList.class,
|
||||
PyAstTypeParameterList.class,
|
||||
};
|
||||
public static final Class[] WRAPPABLE_CLASSES = new Class[]{
|
||||
PsiComment.class,
|
||||
PyAstParenthesizedExpression.class,
|
||||
PyAstListCompExpression.class,
|
||||
PyAstDictCompExpression.class,
|
||||
PyAstSetCompExpression.class,
|
||||
PyAstDictLiteralExpression.class,
|
||||
PyAstSetLiteralExpression.class,
|
||||
PyAstListLiteralExpression.class,
|
||||
PyAstArgumentList.class,
|
||||
PyAstParameterList.class,
|
||||
PyAstDecoratorList.class,
|
||||
PyAstSliceExpression.class,
|
||||
PyAstSubscriptionExpression.class,
|
||||
PyAstGeneratorExpression.class,
|
||||
PyAstGroupPattern.class,
|
||||
PyAstMappingPattern.class,
|
||||
PyAstPatternArgumentList.class,
|
||||
PyAstTypeParameterList.class,
|
||||
};
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static final Class[] CLASSES_TO_PARENTHESISE_ON_ENTER = new Class[]{
|
||||
PyAstBinaryExpression.class,
|
||||
PyAstCallExpression.class,
|
||||
PyAstFromImportStatement.class,
|
||||
PyAstTupleExpression.class,
|
||||
PyAstWithStatement.class,
|
||||
PyAstSequencePattern.class,
|
||||
PyAstReferenceExpression.class,
|
||||
};
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import com.intellij.formatting.WrapType;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PySyntaxCoreBundle;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -13,9 +13,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class PyCodeStyleSettings extends CustomCodeStyleSettings {
|
||||
|
||||
public enum DictAlignment {
|
||||
NONE(PyPsiBundle.message("formatter.panel.dict.alignment.do.not.align")),
|
||||
ON_VALUE(PyPsiBundle.message("formatter.panel.dict.alignment.align.on.value")),
|
||||
ON_COLON(PyPsiBundle.message("formatter.panel.dict.alignment.align.on.colon"));
|
||||
NONE(PySyntaxCoreBundle.message("formatter.panel.dict.alignment.do.not.align")),
|
||||
ON_VALUE(PySyntaxCoreBundle.message("formatter.panel.dict.alignment.align.on.value")),
|
||||
ON_COLON(PySyntaxCoreBundle.message("formatter.panel.dict.alignment.align.on.colon"));
|
||||
|
||||
String description;
|
||||
|
||||
@@ -9,9 +9,9 @@ import com.intellij.psi.formatter.StaticSymbolWhiteSpaceDefinitionStrategy;
|
||||
import com.intellij.psi.impl.source.tree.TreeUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.ast.*;
|
||||
import com.jetbrains.python.ast.impl.PyPsiUtilsCore;
|
||||
import com.jetbrains.python.editor.PyEditorHandlerConfig;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntIterator;
|
||||
@@ -146,7 +146,7 @@ public class PyWhiteSpaceFormattingStrategy extends StaticSymbolWhiteSpaceDefini
|
||||
}
|
||||
|
||||
private static boolean needInsertBackslash(ASTNode nodeAtCaret, boolean autoWrapInProgress) {
|
||||
if (PsiTreeUtil.getParentOfType(nodeAtCaret.getPsi(), PyFStringFragment.class) != null) {
|
||||
if (PsiTreeUtil.getParentOfType(nodeAtCaret.getPsi(), PyAstFStringFragment.class) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ public class PyWhiteSpaceFormattingStrategy extends StaticSymbolWhiteSpaceDefini
|
||||
return false;
|
||||
}
|
||||
if (wrappableAfter == null) {
|
||||
return !(wrappableBefore instanceof PyDecoratorList);
|
||||
return !(wrappableBefore instanceof PyAstDecoratorList);
|
||||
}
|
||||
return wrappableBefore != wrappableAfter;
|
||||
}
|
||||
@@ -210,8 +210,8 @@ public class PyWhiteSpaceFormattingStrategy extends StaticSymbolWhiteSpaceDefini
|
||||
: findAfterCaret(nodeAtCaret, PyEditorHandlerConfig.WRAPPABLE_CLASSES);
|
||||
if (wrappable == null) {
|
||||
PsiElement emptyTuple = before
|
||||
? findBeforeCaret(nodeAtCaret, PyTupleExpression.class)
|
||||
: findAfterCaret(nodeAtCaret, PyTupleExpression.class);
|
||||
? findBeforeCaret(nodeAtCaret, PyAstTupleExpression.class)
|
||||
: findAfterCaret(nodeAtCaret, PyAstTupleExpression.class);
|
||||
if (emptyTuple != null && emptyTuple.getNode().getFirstChildNode().getElementType() == PyTokenTypes.LPAR) {
|
||||
wrappable = emptyTuple;
|
||||
}
|
||||
@@ -221,12 +221,12 @@ public class PyWhiteSpaceFormattingStrategy extends StaticSymbolWhiteSpaceDefini
|
||||
|
||||
@Nullable
|
||||
private static PsiElement findStatementBeforeCaret(ASTNode node) {
|
||||
return findBeforeCaret(node, PyStatement.class, PyStatementPart.class);
|
||||
return findBeforeCaret(node, PyAstStatement.class, PyAstStatementPart.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement findStatementAfterCaret(ASTNode node) {
|
||||
return findAfterCaret(node, PyStatement.class, PyStatementPart.class);
|
||||
return findAfterCaret(node, PyAstStatement.class, PyAstStatementPart.class);
|
||||
}
|
||||
|
||||
private static PsiElement findBeforeCaret(ASTNode atCaret, Class<? extends PsiElement>... classes) {
|
||||
@@ -256,7 +256,7 @@ public class PyWhiteSpaceFormattingStrategy extends StaticSymbolWhiteSpaceDefini
|
||||
for (Class<? extends T> aClass : classes) {
|
||||
if (aClass.isInstance(run)) return (T)run;
|
||||
}
|
||||
if (run instanceof PsiFile || run instanceof PyStatementList) break;
|
||||
if (run instanceof PsiFile || run instanceof PyAstStatementList) break;
|
||||
run = run.getParent();
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ public class PyWhiteSpaceFormattingStrategy extends StaticSymbolWhiteSpaceDefini
|
||||
}
|
||||
|
||||
private static boolean inFromImportParentheses(PsiElement statement, int offset) {
|
||||
if (!(statement instanceof PyFromImportStatement fromImportStatement)) {
|
||||
if (!(statement instanceof PyAstFromImportStatement fromImportStatement)) {
|
||||
return false;
|
||||
}
|
||||
PsiElement leftParen = fromImportStatement.getLeftParen();
|
||||
@@ -275,24 +275,24 @@ public class PyWhiteSpaceFormattingStrategy extends StaticSymbolWhiteSpaceDefini
|
||||
}
|
||||
|
||||
private static boolean inWithItemsParentheses(@NotNull PsiElement statement, int offset) {
|
||||
if (!(statement instanceof PyWithStatement)) {
|
||||
if (!(statement instanceof PyAstWithStatement)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiElement leftParen = PyPsiUtils.getFirstChildOfType(statement, PyTokenTypes.LPAR);
|
||||
final PsiElement leftParen = PyPsiUtilsCore.getFirstChildOfType(statement, PyTokenTypes.LPAR);
|
||||
return leftParen != null && offset >= leftParen.getTextRange().getEndOffset();
|
||||
}
|
||||
|
||||
private static boolean inCaseClauseParentheses(@NotNull PsiElement statement, int offset) {
|
||||
if (!(statement instanceof PyCaseClause caseClause)) {
|
||||
if (!(statement instanceof PyAstCaseClause caseClause)) {
|
||||
return false;
|
||||
}
|
||||
final PyPattern pattern = caseClause.getPattern();
|
||||
final PyAstPattern pattern = caseClause.getPattern();
|
||||
if (pattern == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiElement leftParen = PyPsiUtils.getChildByFilter(pattern, PyTokenTypes.OPEN_BRACES, 0);
|
||||
final PsiElement leftParen = PyPsiUtilsCore.getChildByFilter(pattern, PyTokenTypes.OPEN_BRACES, 0);
|
||||
return leftParen != null && offset >= leftParen.getTextRange().getEndOffset();
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,10 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PythonCodeStyleService;
|
||||
import com.jetbrains.python.ast.PyAstStatementList;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -33,8 +35,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.jetbrains.python.psi.PyUtil.as;
|
||||
|
||||
/**
|
||||
* Contains various methods for manipulation on indentation found in arbitrary text and individual lines:
|
||||
* <ul>
|
||||
@@ -89,7 +89,7 @@ public final class PyIndentUtil {
|
||||
if (anchor instanceof PsiFile) {
|
||||
return "";
|
||||
}
|
||||
final PyStatementList statementList = getAnchorStatementList(anchor);
|
||||
final PyAstStatementList statementList = getAnchorStatementList(anchor);
|
||||
if (statementList == null) {
|
||||
return "";
|
||||
}
|
||||
@@ -105,9 +105,9 @@ public final class PyIndentUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getExpectedBlockIndent(@NotNull PyStatementList anchor) {
|
||||
private static String getExpectedBlockIndent(@NotNull PyAstStatementList anchor) {
|
||||
final String indentStep = getIndentFromSettings(anchor.getContainingFile());
|
||||
final PyStatementList parentBlock = PsiTreeUtil.getParentOfType(anchor, PyStatementList.class, true);
|
||||
final PyAstStatementList parentBlock = PsiTreeUtil.getParentOfType(anchor, PyAstStatementList.class, true);
|
||||
if (parentBlock != null) {
|
||||
return getElementIndent(parentBlock) + indentStep;
|
||||
}
|
||||
@@ -115,14 +115,14 @@ public final class PyIndentUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyStatementList getAnchorStatementList(@NotNull PsiElement element) {
|
||||
PyStatementList statementList = null;
|
||||
private static PyAstStatementList getAnchorStatementList(@NotNull PsiElement element) {
|
||||
PyAstStatementList statementList = null;
|
||||
// First whitespace right before the statement list (right after ":")
|
||||
if (element instanceof PsiWhiteSpace) {
|
||||
statementList = as(element.getNextSibling(), PyStatementList.class);
|
||||
statementList = ObjectUtils.tryCast(element.getNextSibling(), PyAstStatementList.class);
|
||||
}
|
||||
if (statementList == null) {
|
||||
statementList = PsiTreeUtil.getParentOfType(element, PyStatementList.class, false);
|
||||
statementList = PsiTreeUtil.getParentOfType(element, PyAstStatementList.class, false);
|
||||
}
|
||||
return statementList;
|
||||
}
|
||||
22
python/python-syntax/intellij.python.syntax.iml
Normal file
22
python/python-syntax/intellij.python.syntax.iml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="intellij.platform.analysis" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core" />
|
||||
<orderEntry type="module" module-name="intellij.python.parser" />
|
||||
<orderEntry type="module" module-name="intellij.platform.editor" />
|
||||
<orderEntry type="module" module-name="intellij.python.syntax.core" />
|
||||
<orderEntry type="module" module-name="intellij.python.ast" />
|
||||
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
||||
<orderEntry type="module" module-name="intellij.platform.codeStyle.impl" />
|
||||
<orderEntry type="library" name="fastutil-min" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
5
python/python-syntax/resources/META-INF/PythonSyntax.xml
Normal file
5
python/python-syntax/resources/META-INF/PythonSyntax.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<enterHandlerDelegate implementation="com.jetbrains.python.editor.PythonEnterHandler"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -25,6 +25,8 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.ast.*;
|
||||
import com.jetbrains.python.ast.docstring.DocStringUtilCore;
|
||||
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
|
||||
import com.jetbrains.python.documentation.docstrings.*;
|
||||
import com.jetbrains.python.formatter.PyWhiteSpaceFormattingStrategy;
|
||||
@@ -51,7 +53,7 @@ public final class PythonEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
editor = InjectedLanguageUtil.getTopLevelEditor(editor);
|
||||
offset = editor.getCaretModel().getOffset();
|
||||
}
|
||||
if (!(file instanceof PyFile)) {
|
||||
if (!(file instanceof PyAstFile)) {
|
||||
return Result.Continue;
|
||||
}
|
||||
final Boolean isSplitLine = DataManager.getInstance().loadFromDataContext(dataContext, SplitLineAction.SPLIT_LINE_KEY);
|
||||
@@ -86,9 +88,9 @@ public final class PythonEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
PsiElement elementParent = element.getParent();
|
||||
final IElementType nodeType = node.getElementType();
|
||||
if (nodeType == PyTokenTypes.LPAR) elementParent = elementParent.getParent();
|
||||
if (elementParent instanceof PyParenthesizedExpression || elementParent instanceof PyGeneratorExpression) return Result.Continue;
|
||||
if (elementParent instanceof PyAstParenthesizedExpression || elementParent instanceof PyAstGeneratorExpression) return Result.Continue;
|
||||
|
||||
final PyStringElement stringElement = PsiTreeUtil.getParentOfType(element, PyStringElement.class, false);
|
||||
final PyAstStringElement stringElement = PsiTreeUtil.getParentOfType(element, PyAstStringElement.class, false);
|
||||
if (stringElement == null && prevElement == element) {
|
||||
return Result.Continue;
|
||||
}
|
||||
@@ -191,10 +193,10 @@ public final class PythonEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
|
||||
private static void parenthesise(@NotNull PsiElement wrappable, @NotNull Document doc) {
|
||||
TextRange rangeToParenthesise;
|
||||
if (wrappable instanceof PyFromImportStatement fromImportStatement) {
|
||||
if (wrappable instanceof PyAstFromImportStatement fromImportStatement) {
|
||||
rangeToParenthesise = getRangeForPsiElementArray(fromImportStatement.getImportElements());
|
||||
}
|
||||
else if (wrappable instanceof PyWithStatement withStatement) {
|
||||
else if (wrappable instanceof PyAstWithStatement withStatement) {
|
||||
rangeToParenthesise = getRangeForPsiElementArray(withStatement.getWithItems());
|
||||
}
|
||||
else {
|
||||
@@ -219,7 +221,7 @@ public final class PythonEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
}
|
||||
|
||||
private static void insertDocStringStub(Editor editor, PsiElement element, DocstringState state) {
|
||||
PyDocStringOwner docOwner = PsiTreeUtil.getParentOfType(element, PyDocStringOwner.class);
|
||||
PyAstDocStringOwner docOwner = PsiTreeUtil.getParentOfType(element, PyAstDocStringOwner.class);
|
||||
if (docOwner != null) {
|
||||
final int caretOffset = editor.getCaretModel().getOffset();
|
||||
final Document document = editor.getDocument();
|
||||
@@ -242,7 +244,7 @@ public final class PythonEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
public Result postProcessEnter(@NotNull PsiFile file,
|
||||
@NotNull Editor editor,
|
||||
@NotNull DataContext dataContext) {
|
||||
if (!(file instanceof PyFile)) {
|
||||
if (!(file instanceof PyAstFile)) {
|
||||
return Result.Continue;
|
||||
}
|
||||
if (myPostprocessShift > 0) {
|
||||
@@ -260,10 +262,10 @@ public final class PythonEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
final PsiElement element = file.findElementAt(offset);
|
||||
if (element != null) {
|
||||
// Insert additional indentation after section header in Google code style docstrings
|
||||
final PyStringLiteralExpression pyString = DocStringUtil.getParentDefinitionDocString(element);
|
||||
final PyAstStringLiteralExpression pyString = DocStringUtilCore.getParentDefinitionDocString(element);
|
||||
if (pyString != null) {
|
||||
final String docStringText = pyString.getText();
|
||||
final DocStringFormat format = DocStringUtil.guessDocStringFormat(docStringText, pyString);
|
||||
final DocStringFormat format = DocStringParser.guessDocStringFormat(docStringText, pyString);
|
||||
if (format == DocStringFormat.GOOGLE && offset + 1 < document.getTextLength()) {
|
||||
final int lineNum = document.getLineNumber(offset);
|
||||
final TextRange lineRange = TextRange.create(document.getLineStartOffset(lineNum - 1), document.getLineEndOffset(lineNum - 1));
|
||||
@@ -292,7 +294,7 @@ public final class PythonEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
if (!quotes.equals("\"\"\"") && !quotes.equals("'''")) {
|
||||
return DocstringState.NONE;
|
||||
}
|
||||
final PyStringLiteralExpression pyString = DocStringUtil.getParentDefinitionDocString(element);
|
||||
final PyAstStringLiteralExpression pyString = DocStringUtilCore.getParentDefinitionDocString(element);
|
||||
if (pyString != null) {
|
||||
|
||||
String nodeText = element.getText();
|
||||
@@ -20,10 +20,7 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringFormat;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
|
||||
import com.jetbrains.python.documentation.docstrings.GoogleCodeStyleDocStringBuilder;
|
||||
import com.jetbrains.python.documentation.docstrings.SectionBasedDocString;
|
||||
import com.jetbrains.python.documentation.docstrings.*;
|
||||
import com.jetbrains.python.psi.PyIndentUtil;
|
||||
import com.jetbrains.python.psi.PyStringLiteralExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -39,7 +36,7 @@ public class GoogleDocStringSectionFixer extends PyFixer<PyStringLiteralExpressi
|
||||
@Override
|
||||
protected boolean isApplicable(@NotNull Editor editor, @NotNull PyStringLiteralExpression pyString) {
|
||||
return DocStringUtil.getParentDefinitionDocString(pyString) == pyString &&
|
||||
DocStringUtil.guessDocStringFormat(pyString.getText(), pyString) == DocStringFormat.GOOGLE;
|
||||
DocStringParser.guessDocStringFormat(pyString.getText(), pyString) == DocStringFormat.GOOGLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,9 +12,11 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.platform.DirectoryProjectConfigurator;
|
||||
import com.jetbrains.python.PythonModuleTypeBase;
|
||||
import com.jetbrains.python.ReSTService;
|
||||
import com.jetbrains.python.defaultProjectAwareService.PyDefaultProjectAwareModuleConfiguratorImpl;
|
||||
import com.jetbrains.python.defaultProjectAwareService.PyDefaultProjectAwareService;
|
||||
import com.jetbrains.python.defaultProjectAwareService.PyDefaultProjectAwareServiceModuleConfigurator;
|
||||
import com.jetbrains.python.documentation.PyDocumentationSettings;
|
||||
import com.jetbrains.python.documentation.PyDocumentationSettingsDetector;
|
||||
import com.jetbrains.python.packaging.PyPackageRequirementsSettings;
|
||||
import com.jetbrains.python.testing.TestRunnerService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -45,11 +47,13 @@ final class PyDefaultProjectAwareServiceConfigurator implements DirectoryProject
|
||||
private static void updateServices(@NotNull Module module, boolean newProject) {
|
||||
List<PyDefaultProjectAwareServiceModuleConfigurator> configurators = Arrays.asList(
|
||||
TestRunnerService.getConfigurator(),
|
||||
PyDocumentationSettings.getConfigurator(),
|
||||
new PyDefaultProjectAwareModuleConfiguratorImpl<>(PyDocumentationSettings.SERVICE_CLASSES, PY_DOCUMENTATION_SETTINGS_DETECTOR),
|
||||
ReSTService.getConfigurator(),
|
||||
PyPackageRequirementsSettings.getConfigurator());
|
||||
for (PyDefaultProjectAwareServiceModuleConfigurator configurator : configurators) {
|
||||
configurator.configureModule(module, newProject);
|
||||
}
|
||||
}
|
||||
|
||||
private static final PyDocumentationSettingsDetector PY_DOCUMENTATION_SETTINGS_DETECTOR = new PyDocumentationSettingsDetector();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import com.intellij.lang.annotation.AnnotationBuilder;
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.ExternalAnnotator;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.modcommand.ModCommandAction;
|
||||
import com.intellij.openapi.application.ApplicationInfo;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
@@ -37,7 +36,7 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.*;
|
||||
import com.jetbrains.python.codeInsight.imports.OptimizeImportsQuickFix;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringParser;
|
||||
import com.jetbrains.python.formatter.PyCodeStyleSettings;
|
||||
import com.jetbrains.python.inspections.PyPep8Inspection;
|
||||
import com.jetbrains.python.inspections.flake8.Flake8InspectionSuppressor;
|
||||
@@ -155,7 +154,7 @@ public final class Pep8ExternalAnnotator extends ExternalAnnotator<Pep8ExternalA
|
||||
if (vFile == null || !FileTypeRegistry.getInstance().isFileOfType(vFile, PythonFileType.INSTANCE)) {
|
||||
return null;
|
||||
}
|
||||
Sdk sdk = PythonSdkType.findLocalCPython(DocStringUtil.getModuleForElement(file));
|
||||
Sdk sdk = PythonSdkType.findLocalCPython(DocStringParser.getModuleForElement(file));
|
||||
if (sdk == null) {
|
||||
if (!myReportedMissingInterpreter) {
|
||||
myReportedMissingInterpreter = true;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<xi:include href="/META-INF/PythonPsi.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="/META-INF/PythonPsiImpl.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="/META-INF/PythonSdk.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="/META-INF/PythonSyntax.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
@@ -96,7 +97,6 @@
|
||||
<annotator language="Python" implementationClass="com.jetbrains.python.inspections.PyCompatibilityInspectionAdvertiser"/>
|
||||
|
||||
<quoteHandler fileType="Python" className="com.jetbrains.python.editor.PythonQuoteHandler"/>
|
||||
<enterHandlerDelegate implementation="com.jetbrains.python.editor.PythonEnterHandler"/>
|
||||
<enterHandlerDelegate implementation="com.jetbrains.python.editor.PyEnterAtIndentHandler" order="first"/>
|
||||
<enterBetweenBracesDelegate language="Python"
|
||||
implementationClass="com.intellij.codeInsight.editorActions.enter.EnterBetweenBracesAndBracketsDelegate"/>
|
||||
@@ -469,8 +469,6 @@
|
||||
<!-- Code-insight IDE bridge -->
|
||||
<applicationService serviceInterface="com.jetbrains.python.PythonRuntimeService"
|
||||
serviceImplementation="com.jetbrains.python.PythonRuntimeServiceImpl"/>
|
||||
<applicationService serviceInterface="com.jetbrains.python.PythonCodeStyleService"
|
||||
serviceImplementation="com.jetbrains.python.PythonCodeStyleServiceImpl"/>
|
||||
<applicationService serviceInterface="com.jetbrains.python.PythonUiService"
|
||||
serviceImplementation="com.jetbrains.python.PythonUiServiceImpl"/>
|
||||
<applicationService serviceInterface="com.jetbrains.python.codeInsight.imports.PyImportCollectorFactory"
|
||||
|
||||
@@ -300,7 +300,7 @@ public class PySectionBasedDocStringTest extends PyTestCase {
|
||||
|
||||
// PY-16766
|
||||
public void testGoogleDocStringContentDetection() {
|
||||
assertTrue(DocStringUtil.isLikeGoogleDocString(
|
||||
assertTrue(DocStringParser.isLikeGoogleDocString(
|
||||
"""
|
||||
|
||||
My Section:
|
||||
@@ -399,7 +399,7 @@ public class PySectionBasedDocStringTest extends PyTestCase {
|
||||
|
||||
// PY-17657, PY-16303
|
||||
public void testNotGoogleFormatIfDocstringContainTags() {
|
||||
assertEquals(DocStringFormat.REST, DocStringUtil.guessDocStringFormat("""
|
||||
assertEquals(DocStringFormat.REST, DocStringParser.guessDocStringFormat("""
|
||||
""\"
|
||||
:type sub_field: FieldDescriptor | () -> FieldDescriptor
|
||||
:param sub_field: The type of field in this collection
|
||||
@@ -408,7 +408,7 @@ public class PySectionBasedDocStringTest extends PyTestCase {
|
||||
addresses = field.Collection(AddressObject)
|
||||
""\""""));
|
||||
|
||||
assertEquals(DocStringFormat.REST, DocStringUtil.guessDocStringFormat("""
|
||||
assertEquals(DocStringFormat.REST, DocStringParser.guessDocStringFormat("""
|
||||
""\"
|
||||
Args:
|
||||
:param Tuple[int, int] name: Some description
|
||||
|
||||
Reference in New Issue
Block a user