mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Cleanup in SpecifyTypeIn*Intentions and PyDocstringInspection
Like SpecifyTypeInDocstringIntention SpecifyTypeInPy3AnnotationIntention operates only on named function parameters.
This commit is contained in:
+7
-7
@@ -53,12 +53,12 @@ public class SpecifyTypeInDocstringIntention extends TypeIntention {
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
PsiElement elementAt = PyUtil.findNonWhitespaceAtOffset(file, editor.getCaretModel().getOffset());
|
||||
PyExpression problemElement = getProblemElement(elementAt);
|
||||
PsiReference reference = problemElement == null ? null : problemElement.getReference();
|
||||
final PsiElement elementAt = PyUtil.findNonWhitespaceAtOffset(file, editor.getCaretModel().getOffset());
|
||||
final PyExpression problemElement = getProblemElement(elementAt);
|
||||
final PsiReference reference = problemElement == null ? null : problemElement.getReference();
|
||||
|
||||
final PsiElement resolved = reference != null ? reference.resolve() : null;
|
||||
PyNamedParameter parameter = getParameter(problemElement, resolved);
|
||||
final PyNamedParameter parameter = getParameter(problemElement, resolved);
|
||||
|
||||
final PyCallable callable;
|
||||
if (parameter != null) {
|
||||
@@ -72,7 +72,7 @@ public class SpecifyTypeInDocstringIntention extends TypeIntention {
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateDocstring(@Nullable PyNamedParameter param, PyFunction pyFunction) {
|
||||
private static void generateDocstring(@Nullable PyNamedParameter param, @NotNull PyFunction pyFunction) {
|
||||
if (!DocStringUtil.ensureNotPlainDocstringFormat(pyFunction)) {
|
||||
return;
|
||||
}
|
||||
@@ -101,8 +101,8 @@ public class SpecifyTypeInDocstringIntention extends TypeIntention {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isParamTypeDefined(@NotNull final PyParameter parameter) {
|
||||
PyFunction pyFunction = PsiTreeUtil.getParentOfType(parameter, PyFunction.class);
|
||||
protected boolean isParamTypeDefined(@NotNull PyParameter parameter) {
|
||||
final PyFunction pyFunction = PsiTreeUtil.getParentOfType(parameter, PyFunction.class);
|
||||
if (pyFunction != null) {
|
||||
final StructuredDocString structuredDocString = pyFunction.getStructuredDocString();
|
||||
if (structuredDocString == null) {
|
||||
|
||||
+25
-25
@@ -39,8 +39,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
|
||||
private String myText = PyBundle.message("INTN.specify.type.in.annotation");
|
||||
public SpecifyTypeInPy3AnnotationsIntention() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getText() {
|
||||
@@ -59,12 +57,12 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
PsiElement elementAt = PyUtil.findNonWhitespaceAtOffset(file, editor.getCaretModel().getOffset());
|
||||
PyExpression problemElement = getProblemElement(elementAt);
|
||||
PsiReference reference = problemElement == null? null : problemElement.getReference();
|
||||
final PsiElement elementAt = PyUtil.findNonWhitespaceAtOffset(file, editor.getCaretModel().getOffset());
|
||||
final PyExpression problemElement = getProblemElement(elementAt);
|
||||
final PsiReference reference = problemElement == null ? null : problemElement.getReference();
|
||||
|
||||
final PsiElement resolved = reference != null? reference.resolve() : null;
|
||||
PyParameter parameter = getParameter(problemElement, resolved);
|
||||
final PsiElement resolved = reference != null ? reference.resolve() : null;
|
||||
final PyNamedParameter parameter = getParameter(problemElement, resolved);
|
||||
|
||||
if (parameter != null) {
|
||||
annotateParameter(project, editor, parameter);
|
||||
@@ -74,42 +72,43 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
|
||||
}
|
||||
}
|
||||
|
||||
private static void annotateParameter(Project project, Editor editor, PyParameter parameter) {
|
||||
PyExpression defaultParamValue = parameter instanceof PyNamedParameter? parameter.getDefaultValue() : null;
|
||||
private static void annotateParameter(Project project, Editor editor, @NotNull PyNamedParameter parameter) {
|
||||
final PyExpression defaultParamValue = parameter.getDefaultValue();
|
||||
|
||||
final String name = StringUtil.notNullize(parameter.getName());
|
||||
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
|
||||
String defaultParamText = defaultParamValue == null? null: defaultParamValue.getText();
|
||||
final PyNamedParameter namedParameter = elementGenerator.createParameter(name, defaultParamText, PyNames.OBJECT, LanguageLevel.forElement(parameter));
|
||||
final String defaultParamText = defaultParamValue == null ? null : defaultParamValue.getText();
|
||||
final PyNamedParameter namedParameter = elementGenerator.createParameter(name, defaultParamText, PyNames.OBJECT,
|
||||
LanguageLevel.forElement(parameter));
|
||||
assert namedParameter != null;
|
||||
parameter = (PyParameter)parameter.replace(namedParameter);
|
||||
parameter = (PyNamedParameter)parameter.replace(namedParameter);
|
||||
parameter = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(parameter);
|
||||
editor.getCaretModel().moveToOffset(parameter.getTextOffset());
|
||||
PyAnnotation annotation = parameter instanceof PyNamedParameter? ((PyNamedParameter)parameter).getAnnotation() : null;
|
||||
final PyAnnotation annotation = parameter.getAnnotation();
|
||||
if (annotation != null) {
|
||||
PyExpression annotationValue = annotation.getValue();
|
||||
final PyExpression annotationValue = annotation.getValue();
|
||||
|
||||
final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(parameter);
|
||||
int replacementStart = annotation.getStartOffsetInParent() + annotationValue.getStartOffsetInParent();
|
||||
assert annotationValue != null : "Generated parameter must have annotation";
|
||||
final int replacementStart = annotation.getStartOffsetInParent() + annotationValue.getStartOffsetInParent();
|
||||
builder.replaceRange(TextRange.create(replacementStart,
|
||||
replacementStart + annotationValue.getTextLength()), PyNames.OBJECT);
|
||||
Template template = ((TemplateBuilderImpl)builder).buildInlineTemplate();
|
||||
final Template template = ((TemplateBuilderImpl)builder).buildInlineTemplate();
|
||||
TemplateManager.getInstance(project).startTemplate(editor, template);
|
||||
}
|
||||
}
|
||||
|
||||
private void annotateReturnType(Project project, PsiElement resolved) {
|
||||
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
|
||||
PyCallable callable = getCallable(resolved);
|
||||
|
||||
if (callable instanceof PyFunction) {
|
||||
final String functionSignature = "def " + callable.getName() + callable.getParameterList().getText();
|
||||
String functionText = functionSignature +
|
||||
" -> object:";
|
||||
" -> object:";
|
||||
final PyStatementList statementList = ((PyFunction)callable).getStatementList();
|
||||
assert statementList != null;
|
||||
for (PyStatement st : statementList.getStatements()) {
|
||||
functionText = functionText + "\n\t" + st.getText();
|
||||
}
|
||||
@@ -121,17 +120,18 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
|
||||
final PyAnnotation annotation = ((PyFunction)callable).getAnnotation();
|
||||
assert annotation != null;
|
||||
final PyExpression annotationValue = annotation.getValue();
|
||||
assert annotationValue != null : "Generated function must have annotation";
|
||||
final int offset = annotationValue.getTextOffset();
|
||||
|
||||
final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(annotationValue);
|
||||
builder.replaceRange(TextRange.create(0, PyNames.OBJECT.length()), PyNames.OBJECT);
|
||||
Template template = ((TemplateBuilderImpl)builder).buildInlineTemplate();
|
||||
OpenFileDescriptor descriptor = new OpenFileDescriptor(
|
||||
final Template template = ((TemplateBuilderImpl)builder).buildInlineTemplate();
|
||||
final OpenFileDescriptor descriptor = new OpenFileDescriptor(
|
||||
project,
|
||||
callable.getContainingFile().getVirtualFile(),
|
||||
offset
|
||||
);
|
||||
Editor targetEditor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
|
||||
final Editor targetEditor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
|
||||
if (targetEditor != null) {
|
||||
targetEditor.getCaretModel().moveToOffset(offset);
|
||||
TemplateManager.getInstance(project).startTemplate(targetEditor, template);
|
||||
@@ -144,7 +144,7 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
|
||||
return isDefinedInAnnotation(parameter);
|
||||
}
|
||||
|
||||
private boolean isDefinedInAnnotation(PyParameter parameter) {
|
||||
private static boolean isDefinedInAnnotation(PyParameter parameter) {
|
||||
if (LanguageLevel.forElement(parameter).isOlderThan(LanguageLevel.PYTHON30)) {
|
||||
return false;
|
||||
}
|
||||
@@ -159,6 +159,6 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
|
||||
|
||||
@Override
|
||||
protected void updateText(boolean isReturn) {
|
||||
myText = isReturn? PyBundle.message("INTN.specify.return.type.in.annotation") : PyBundle.message("INTN.specify.type.in.annotation");
|
||||
myText = isReturn ? PyBundle.message("INTN.specify.return.type.in.annotation") : PyBundle.message("INTN.specify.type.in.annotation");
|
||||
}
|
||||
}
|
||||
@@ -123,18 +123,13 @@ public class PyDocstringGenerator {
|
||||
return withParam(getPreferredParameterName(param));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PyDocstringGenerator withoutParam(@NotNull String name) {
|
||||
return withParamTypedByName(name, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PyDocstringGenerator withParamTypedByName(@NotNull String name, @Nullable String type) {
|
||||
myAddedParams.add(new DocstringParam(name, type, false));
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@NotNull
|
||||
public PyDocstringGenerator withParamTypedByName(@NotNull PyNamedParameter name, @Nullable String type) {
|
||||
return withParamTypedByName(getPreferredParameterName(name), type);
|
||||
}
|
||||
@@ -145,6 +140,12 @@ public class PyDocstringGenerator {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PyDocstringGenerator withoutParam(@NotNull String name) {
|
||||
myRemovedParams.add(new DocstringParam(name, null, false));
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PyDocstringGenerator withQuotes(@NotNull String quotes) {
|
||||
myQuotes = quotes;
|
||||
|
||||
@@ -70,12 +70,12 @@ public class PyDocstringInspection extends PyInspection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyFile(PyFile node) {
|
||||
public void visitPyFile(@NotNull PyFile node) {
|
||||
checkDocString(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyFunction(PyFunction node) {
|
||||
public void visitPyFunction(@NotNull PyFunction node) {
|
||||
if (PythonUnitTestUtil.isUnitTestCaseFunction(node)) return;
|
||||
final PyClass containingClass = node.getContainingClass();
|
||||
if (containingClass != null && PythonUnitTestUtil.isUnitTestCaseClass(containingClass)) return;
|
||||
@@ -84,7 +84,7 @@ public class PyDocstringInspection extends PyInspection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyClass(PyClass node) {
|
||||
public void visitPyClass(@NotNull PyClass node) {
|
||||
if (PythonUnitTestUtil.isUnitTestCaseClass(node)) return;
|
||||
final String name = node.getName();
|
||||
if (name == null || name.startsWith("_")) {
|
||||
@@ -98,7 +98,7 @@ public class PyDocstringInspection extends PyInspection {
|
||||
checkDocString(node);
|
||||
}
|
||||
|
||||
private void checkDocString(PyDocStringOwner node) {
|
||||
private void checkDocString(@NotNull PyDocStringOwner node) {
|
||||
final PyStringLiteralExpression docStringExpression = node.getDocStringExpression();
|
||||
if (docStringExpression == null) {
|
||||
PsiElement marker = null;
|
||||
@@ -111,8 +111,8 @@ public class PyDocstringInspection extends PyInspection {
|
||||
if (n != null) marker = n.getPsi();
|
||||
}
|
||||
else if (node instanceof PyFile) {
|
||||
TextRange tr = new TextRange(0, 0);
|
||||
ProblemsHolder holder = getHolder();
|
||||
final TextRange tr = new TextRange(0, 0);
|
||||
final ProblemsHolder holder = getHolder();
|
||||
if (holder != null) {
|
||||
holder.registerProblem(node, tr, PyBundle.message("INSP.no.docstring"));
|
||||
}
|
||||
@@ -127,29 +127,29 @@ public class PyDocstringInspection extends PyInspection {
|
||||
}
|
||||
}
|
||||
else {
|
||||
boolean registered = checkParameters(node, docStringExpression);
|
||||
final boolean registered = checkParameters(node, docStringExpression);
|
||||
if (!registered && StringUtil.isEmptyOrSpaces(docStringExpression.getStringValue())) {
|
||||
registerProblem(docStringExpression, PyBundle.message("INSP.empty.docstring"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkParameters(PyDocStringOwner pyDocStringOwner, PyStringLiteralExpression node) {
|
||||
private boolean checkParameters(@NotNull PyDocStringOwner pyDocStringOwner, @NotNull PyStringLiteralExpression node) {
|
||||
final String text = node.getText();
|
||||
if (text == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StructuredDocString docString = DocStringUtil.parse(text, node);
|
||||
final StructuredDocString docString = DocStringUtil.parse(text, node);
|
||||
|
||||
if (docString instanceof PlainDocString) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pyDocStringOwner instanceof PyFunction) {
|
||||
PyParameter[] realParams = ((PyFunction)pyDocStringOwner).getParameterList().getParameters();
|
||||
final PyParameter[] realParams = ((PyFunction)pyDocStringOwner).getParameterList().getParameters();
|
||||
|
||||
List<PyNamedParameter> missingParams = getMissingParams(docString, realParams);
|
||||
final List<PyNamedParameter> missingParams = getMissingParams(docString, realParams);
|
||||
boolean registered = false;
|
||||
if (!missingParams.isEmpty()) {
|
||||
for (PyNamedParameter param : missingParams) {
|
||||
@@ -157,10 +157,10 @@ public class PyDocstringInspection extends PyInspection {
|
||||
}
|
||||
registered = true;
|
||||
}
|
||||
List<Substring> unexpectedParams = getUnexpectedParams(docString, realParams);
|
||||
final List<Substring> unexpectedParams = getUnexpectedParams(docString, realParams);
|
||||
if (!unexpectedParams.isEmpty()) {
|
||||
for (Substring param : unexpectedParams) {
|
||||
ProblemsHolder holder = getHolder();
|
||||
final ProblemsHolder holder = getHolder();
|
||||
|
||||
if (holder != null) {
|
||||
holder.registerProblem(node, param.getTextRange(),
|
||||
@@ -175,8 +175,9 @@ public class PyDocstringInspection extends PyInspection {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static List<Substring> getUnexpectedParams(StructuredDocString docString, PyParameter[] realParams) {
|
||||
Map<String, Substring> unexpected = Maps.newHashMap();
|
||||
@NotNull
|
||||
private static List<Substring> getUnexpectedParams(@NotNull StructuredDocString docString, @NotNull PyParameter[] realParams) {
|
||||
final Map<String, Substring> unexpected = Maps.newHashMap();
|
||||
|
||||
for (Substring s : docString.getParameterSubstrings()) {
|
||||
unexpected.put(s.toString(), s);
|
||||
@@ -190,14 +191,14 @@ public class PyDocstringInspection extends PyInspection {
|
||||
return Lists.newArrayList(unexpected.values());
|
||||
}
|
||||
|
||||
private static List<PyNamedParameter> getMissingParams(StructuredDocString docString, PyParameter[] realParams) {
|
||||
List<PyNamedParameter> missing = new ArrayList<PyNamedParameter>();
|
||||
@NotNull
|
||||
private static List<PyNamedParameter> getMissingParams(@NotNull StructuredDocString docString, @NotNull PyParameter[] realParams) {
|
||||
final List<PyNamedParameter> missing = new ArrayList<PyNamedParameter>();
|
||||
final List<String> docStringParameters = docString.getParameters();
|
||||
for (PyParameter p : realParams) {
|
||||
if (p.isSelf() || !(p instanceof PyNamedParameter)) {
|
||||
continue;
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
if (!docStringParameters.contains(p.getName())) {
|
||||
missing.add((PyNamedParameter)p);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user