diff --git a/python/resources/inspectionDescriptions/PyMissingTypeHintsInspection.html b/python/resources/inspectionDescriptions/PyMissingTypeHintsInspection.html
new file mode 100644
index 000000000000..7d88ef248c2c
--- /dev/null
+++ b/python/resources/inspectionDescriptions/PyMissingTypeHintsInspection.html
@@ -0,0 +1,7 @@
+
+
+
+This inspection detects lack of type hints for function declaration in
+ one of the two formats: parameter annotations or a type comment
+
+
\ No newline at end of file
diff --git a/python/src/META-INF/python-core-common.xml b/python/src/META-INF/python-core-common.xml
index 911f5041744a..c8a11791611d 100644
--- a/python/src/META-INF/python-core-common.xml
+++ b/python/src/META-INF/python-core-common.xml
@@ -380,6 +380,8 @@
+
+
diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PyAnnotateTypesIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PyAnnotateTypesIntention.java
index dd2b90d0256d..72eadd1fad2f 100644
--- a/python/src/com/jetbrains/python/codeInsight/intentions/PyAnnotateTypesIntention.java
+++ b/python/src/com/jetbrains/python/codeInsight/intentions/PyAnnotateTypesIntention.java
@@ -82,17 +82,21 @@ public class PyAnnotateTypesIntention implements IntentionAction {
final PsiElement elementAt = PyUtil.findNonWhitespaceAtOffset(file, editor.getCaretModel().getOffset());
final PyCallable callable = getCallable(elementAt);
- if (isPy3k(file)) {
- generatePy3kTypeAnnotations(project, editor, elementAt, callable);
+ annotateTypes(editor, callable);
+ }
+
+ public static void annotateTypes(Editor editor, PyCallable callable) {
+ if (isPy3k(callable.getContainingFile())) {
+ generatePy3kTypeAnnotations(callable.getProject(), editor, callable);
}
else {
if (callable instanceof PyFunction) {
- generateTypeCommentAnnotations(project, editor, elementAt, (PyFunction)callable);
+ generateTypeCommentAnnotations(callable.getProject(), (PyFunction)callable);
}
}
}
- private static void generateTypeCommentAnnotations(Project project, Editor editor, PsiElement at, PyFunction function) {
+ private static void generateTypeCommentAnnotations(Project project, PyFunction function) {
StringBuilder replacementTextBuilder = new StringBuilder("# type: (");
@@ -181,13 +185,15 @@ public class PyAnnotateTypesIntention implements IntentionAction {
return LanguageLevel.forElement(file).isPy3K();
}
- private static void generatePy3kTypeAnnotations(@NotNull Project project, Editor editor, PsiElement elementAt, PyCallable callable) {
+ private static void generatePy3kTypeAnnotations(@NotNull Project project, Editor editor, PyCallable callable) {
final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(callable);
- PyExpression returnType = annotateReturnType(project, editor.getDocument(), elementAt, false);
+ if (callable instanceof PyFunction) {
+ PyExpression returnType = annotateReturnType(project, (PyFunction) callable, false);
- if (returnType != null) {
- builder.replaceElement(returnType, returnType.getText());
+ if (returnType != null) {
+ builder.replaceElement(returnType, returnType.getText());
+ }
}
if (callable instanceof PyFunction) {
diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInPy3AnnotationsIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInPy3AnnotationsIntention.java
index 180a2165d9c4..f9b41ab1c7b7 100644
--- a/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInPy3AnnotationsIntention.java
+++ b/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInPy3AnnotationsIntention.java
@@ -76,14 +76,17 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
annotateParameter(project, editor, parameter, true);
}
else {
- annotateReturnType(project, editor.getDocument(), elementAt, true);
+ PyCallable callable = getCallable(elementAt);
+ if (callable instanceof PyFunction) {
+ annotateReturnType(project, (PyFunction)callable, true);
+ }
}
}
static PyNamedParameter annotateParameter(Project project,
- Editor editor,
- @NotNull PyNamedParameter parameter,
- boolean createTemplate) {
+ Editor editor,
+ @NotNull PyNamedParameter parameter,
+ boolean createTemplate) {
final PyExpression defaultParamValue = parameter.getDefaultValue();
final String paramName = StringUtil.notNullize(parameter.getName());
@@ -93,7 +96,6 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
String paramType = parameterType(parameter);
-
final PyNamedParameter namedParameter = elementGenerator.createParameter(paramName, defaultParamText, paramType,
LanguageLevel.forElement(parameter));
@@ -119,7 +121,7 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
static String parameterType(PyParameter parameter) {
String paramType = PyNames.OBJECT;
-
+
PyFunction function = PsiTreeUtil.getParentOfType(parameter, PyFunction.class);
if (function != null) {
final PySignature signature = PySignatureCacheManager.getInstance(parameter.getProject()).findSignature(
@@ -143,65 +145,57 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention {
return returnType;
}
- public static PyExpression annotateReturnType(Project project, Document document, PsiElement resolved, boolean createTemplate) {
- PyCallable callable = getCallable(resolved);
+ public static PyExpression annotateReturnType(Project project, PyFunction function, boolean createTemplate) {
+ String returnType = returnType(function);
- if (callable instanceof PyFunction) {
- PyFunction function = (PyFunction)callable;
+ final String annotationText = " -> " + returnType;
- String returnType = returnType(function);
+ final PsiElement prevElem = PyPsiUtils.getPrevNonCommentSibling(function.getStatementList(), true);
+ assert prevElem != null;
- final String annotationText = " -> " + returnType;
-
- final PsiElement prevElem = PyPsiUtils.getPrevNonCommentSibling(((PyFunction)callable).getStatementList(), true);
- assert prevElem != null;
-
- final PsiDocumentManager manager = PsiDocumentManager.getInstance(project);
- Document documentWithCallable = manager.getDocument(callable.getContainingFile());
- if (documentWithCallable != null) {
- try {
- final TextRange range = prevElem.getTextRange();
- manager.doPostponedOperationsAndUnblockDocument(documentWithCallable);
- if (prevElem.getNode().getElementType() == PyTokenTypes.COLON) {
- documentWithCallable.insertString(range.getStartOffset(), annotationText);
- }
- else {
- documentWithCallable.insertString(range.getEndOffset(), annotationText + ":");
- }
+ final PsiDocumentManager manager = PsiDocumentManager.getInstance(project);
+ Document documentWithCallable = manager.getDocument(function.getContainingFile());
+ if (documentWithCallable != null) {
+ try {
+ final TextRange range = prevElem.getTextRange();
+ manager.doPostponedOperationsAndUnblockDocument(documentWithCallable);
+ if (prevElem.getNode().getElementType() == PyTokenTypes.COLON) {
+ documentWithCallable.insertString(range.getStartOffset(), annotationText);
}
- finally {
- manager.commitDocument(documentWithCallable);
+ else {
+ documentWithCallable.insertString(range.getEndOffset(), annotationText + ":");
}
}
-
-
- callable = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(callable);
- final PyAnnotation annotation = ((PyFunction)callable).getAnnotation();
- assert annotation != null;
- final PyExpression annotationValue = annotation.getValue();
- assert annotationValue != null : "Generated function must have annotation";
-
- if (createTemplate) {
- final int offset = annotationValue.getTextOffset();
-
- final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(annotationValue);
- builder.replaceRange(TextRange.create(0, returnType.length()), returnType);
- final Template template = ((TemplateBuilderImpl)builder).buildInlineTemplate();
- final OpenFileDescriptor descriptor = new OpenFileDescriptor(
- project,
- callable.getContainingFile().getVirtualFile(),
- offset
- );
- final Editor targetEditor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
- if (targetEditor != null) {
- targetEditor.getCaretModel().moveToOffset(offset);
- TemplateManager.getInstance(project).startTemplate(targetEditor, template);
- }
+ finally {
+ manager.commitDocument(documentWithCallable);
}
- return annotationValue;
}
- return null;
+
+ function = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(function);
+ final PyAnnotation annotation = function.getAnnotation();
+ assert annotation != null;
+ final PyExpression annotationValue = annotation.getValue();
+ assert annotationValue != null : "Generated function must have annotation";
+
+ if (createTemplate) {
+ final int offset = annotationValue.getTextOffset();
+
+ final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(annotationValue);
+ builder.replaceRange(TextRange.create(0, returnType.length()), returnType);
+ final Template template = ((TemplateBuilderImpl)builder).buildInlineTemplate();
+ final OpenFileDescriptor descriptor = new OpenFileDescriptor(
+ project,
+ function.getContainingFile().getVirtualFile(),
+ offset
+ );
+ final Editor targetEditor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
+ if (targetEditor != null) {
+ targetEditor.getCaretModel().moveToOffset(offset);
+ TemplateManager.getInstance(project).startTemplate(targetEditor, template);
+ }
+ }
+ return annotationValue;
}
@Override
diff --git a/python/src/com/jetbrains/python/inspections/PyMissingTypeHintsInspection.java b/python/src/com/jetbrains/python/inspections/PyMissingTypeHintsInspection.java
new file mode 100644
index 000000000000..6a3ce7e60eaa
--- /dev/null
+++ b/python/src/com/jetbrains/python/inspections/PyMissingTypeHintsInspection.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2000-2015 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.inspections;
+
+import com.intellij.codeInspection.LocalInspectionToolSession;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElementVisitor;
+import com.jetbrains.python.PyTokenTypes;
+import com.jetbrains.python.codeInsight.intentions.PyAnnotateTypesIntention;
+import com.jetbrains.python.inspections.quickfix.PyQuickFixUtil;
+import com.jetbrains.python.psi.PyElementVisitor;
+import com.jetbrains.python.psi.PyFunction;
+import com.jetbrains.python.psi.PyNamedParameter;
+import com.jetbrains.python.psi.PyParameter;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author traff
+ */
+public class PyMissingTypeHintsInspection extends PyInspection{
+ @NotNull
+ @Override
+ public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly, @NotNull LocalInspectionToolSession session) {
+ return new PyElementVisitor() {
+ @Override
+ public void visitPyFunction(PyFunction function) {
+ if (!(typeCommentExists(function) || typeAnnotationsExist(function))) {
+ ASTNode nameNode = function.getNameNode();
+ if (nameNode != null) {
+ holder.registerProblem(nameNode.getPsi(), "Type hinting is missing for function definition", new AddTypeHintsQuickFix(function));
+ }
+ }
+ }
+ };
+ }
+
+ private static boolean typeCommentExists(PyFunction function) {
+ ASTNode node = function.getStatementList().getNode().getFirstChildNode();
+
+ while (node != null && node.getElementType() != PyTokenTypes.END_OF_LINE_COMMENT) {
+ node = node.getTreeNext();
+ }
+ if (node != null) {
+ return isTypeComment(node);
+ }
+
+ node = function.getStatementList().getPrevSibling().getNode();
+
+ while (node != null && node.getElementType() != PyTokenTypes.COLON && node.getElementType() != PyTokenTypes.END_OF_LINE_COMMENT) {
+ node = node.getTreePrev();
+ }
+
+ if (node != null && node.getElementType() == PyTokenTypes.END_OF_LINE_COMMENT) {
+ return isTypeComment(node);
+ }
+
+ return false;
+ }
+
+ private static boolean isTypeComment(ASTNode node) {
+ String commentText = node.getText();
+ int startInd = commentText.indexOf('#');
+ if (startInd != -1) {
+ commentText = commentText.substring(startInd+1).trim();
+ if (commentText.startsWith("type:")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean typeAnnotationsExist(PyFunction function) {
+ for (PyParameter param: function.getParameterList().getParameters()) {
+ PyNamedParameter namedParameter = param.getAsNamed();
+ if (namedParameter != null) {
+ if (namedParameter.getAnnotation() != null) {
+ return true;
+ }
+ }
+ }
+ if (function.getAnnotation() != null) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static class AddTypeHintsQuickFix implements LocalQuickFix {
+ private PyFunction myFunction;
+
+ public AddTypeHintsQuickFix(@NotNull PyFunction function) {
+ myFunction = function;
+ }
+
+ @Nls
+ @NotNull
+ @Override
+ public String getName() {
+ return "Add type hinting for '" + myFunction.getName() + "'";
+ }
+
+ @Nls
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "Add type hinting";
+ }
+
+ @Override
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ PyAnnotateTypesIntention.annotateTypes(PyQuickFixUtil.getEditor(myFunction), myFunction);
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java
index 0622727ebc1b..a42ddfdc7cca 100644
--- a/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java
+++ b/python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java
@@ -17,12 +17,7 @@ package com.jetbrains.python.inspections.quickfix;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiElement;
import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.SmartPsiElementPointer;
import com.intellij.psi.util.PsiTreeUtil;
@@ -73,20 +68,6 @@ public class DocstringQuickFix implements LocalQuickFix {
return "Fix docstring";
}
- @Nullable
- private static Editor getEditor(@NotNull PsiElement element) {
- Document document = PsiDocumentManager.getInstance(element.getProject()).getDocument(element.getContainingFile());
- if (document != null) {
- final EditorFactory instance = EditorFactory.getInstance();
- if (instance == null) return null;
- Editor[] editors = instance.getEditors(document);
- if (editors.length > 0) {
- return editors[0];
- }
- }
- return null;
- }
-
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PyDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PyDocStringOwner.class);
if (docStringOwner == null) return;
@@ -113,7 +94,7 @@ public class DocstringQuickFix implements LocalQuickFix {
private static void addEmptyDocstring(@NotNull PyDocStringOwner docStringOwner) {
if (docStringOwner instanceof PyFunction ||
docStringOwner instanceof PyClass && ((PyClass)docStringOwner).findInitOrNew(false, null) != null) {
- PyGenerateDocstringIntention.generateDocstring(docStringOwner, getEditor(docStringOwner));
+ PyGenerateDocstringIntention.generateDocstring(docStringOwner, PyQuickFixUtil.getEditor(docStringOwner));
}
}
}
diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyImplementMethodsQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyImplementMethodsQuickFix.java
index 282bca97dbb5..d480f4e203e3 100644
--- a/python/src/com/jetbrains/python/inspections/quickfix/PyImplementMethodsQuickFix.java
+++ b/python/src/com/jetbrains/python/inspections/quickfix/PyImplementMethodsQuickFix.java
@@ -17,11 +17,8 @@ package com.jetbrains.python.inspections.quickfix;
import com.intellij.codeInspection.LocalQuickFixOnPsiElement;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.PyBundle;
@@ -31,7 +28,6 @@ import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Set;
@@ -62,7 +58,7 @@ public class PyImplementMethodsQuickFix extends LocalQuickFixOnPsiElement {
@Override
public void invoke(@NotNull Project project, @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) {
- final Editor editor = getEditor(project, file);
+ final Editor editor = PyQuickFixUtil.getEditor(file);
if (editor != null && startElement instanceof PyClass) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
@@ -81,18 +77,4 @@ public class PyImplementMethodsQuickFix extends LocalQuickFixOnPsiElement {
}
}
}
-
- @Nullable
- private static Editor getEditor(Project project, PsiFile file) {
- Document document = PsiDocumentManager.getInstance(project).getDocument(file);
- if (document != null) {
- final EditorFactory instance = EditorFactory.getInstance();
- if (instance == null) return null;
- Editor[] editors = instance.getEditors(document);
- if (editors.length > 0) {
- return editors[0];
- }
- }
- return null;
- }
}
diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyQuickFixUtil.java b/python/src/com/jetbrains/python/inspections/quickfix/PyQuickFixUtil.java
new file mode 100644
index 000000000000..3ad435445642
--- /dev/null
+++ b/python/src/com/jetbrains/python/inspections/quickfix/PyQuickFixUtil.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.inspections.quickfix;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author traff
+ */
+public class PyQuickFixUtil {
+ @Nullable
+ public static Editor getEditor(@NotNull PsiElement element) {
+ Document document = PsiDocumentManager.getInstance(element.getProject()).getDocument(element.getContainingFile());
+ if (document != null) {
+ final EditorFactory instance = EditorFactory.getInstance();
+ if (instance == null) return null;
+ Editor[] editors = instance.getEditors(document);
+ if (editors.length > 0) {
+ return editors[0];
+ }
+ }
+ return null;
+ }
+}
diff --git a/python/testData/inspections/PyMissingTypeHintsInspection/noAnnotations.py b/python/testData/inspections/PyMissingTypeHintsInspection/noAnnotations.py
new file mode 100644
index 000000000000..73bdd73dbc82
--- /dev/null
+++ b/python/testData/inspections/PyMissingTypeHintsInspection/noAnnotations.py
@@ -0,0 +1,2 @@
+def foo(x, y):
+ pass
\ No newline at end of file
diff --git a/python/testData/inspections/PyMissingTypeHintsInspection/py3kAnnotations.py b/python/testData/inspections/PyMissingTypeHintsInspection/py3kAnnotations.py
new file mode 100644
index 000000000000..caefec0ac1f7
--- /dev/null
+++ b/python/testData/inspections/PyMissingTypeHintsInspection/py3kAnnotations.py
@@ -0,0 +1,2 @@
+def foo(x: int, y: int) -> str:
+ pass
\ No newline at end of file
diff --git a/python/testData/inspections/PyMissingTypeHintsInspection/typeComment.py b/python/testData/inspections/PyMissingTypeHintsInspection/typeComment.py
new file mode 100644
index 000000000000..38efd7e111c2
--- /dev/null
+++ b/python/testData/inspections/PyMissingTypeHintsInspection/typeComment.py
@@ -0,0 +1,3 @@
+def foo(x):
+ # type: (int) -> int
+ pass
\ No newline at end of file
diff --git a/python/testData/inspections/PyMissingTypeHintsInspection/typeCommentOnTheSameLine.py b/python/testData/inspections/PyMissingTypeHintsInspection/typeCommentOnTheSameLine.py
new file mode 100644
index 000000000000..2b42a1884977
--- /dev/null
+++ b/python/testData/inspections/PyMissingTypeHintsInspection/typeCommentOnTheSameLine.py
@@ -0,0 +1,2 @@
+def foo(x): # type: (int) -> int
+ pass
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyMissingTypeHintsInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyMissingTypeHintsInspectionTest.java
new file mode 100644
index 000000000000..fd6ca83100bc
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/inspections/PyMissingTypeHintsInspectionTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.inspections;
+
+import com.jetbrains.python.fixtures.PyTestCase;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher;
+
+/**
+ * @author traff
+ */
+public class PyMissingTypeHintsInspectionTest extends PyTestCase {
+ public void testPy3kAnnotations() {
+ doTest(LanguageLevel.PYTHON35);
+ }
+
+ public void testNoAnnotations() {
+ doTest(LanguageLevel.PYTHON35);
+ }
+
+ public void testTypeComment() {
+ doTest(LanguageLevel.PYTHON27);
+ }
+
+ public void testTypeCommentOnTheSameLine() {
+ doTest(LanguageLevel.PYTHON27);
+ }
+
+ private void doTest(LanguageLevel languageLevel) {
+ PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), languageLevel);
+ try {
+ myFixture.configureByFile("inspections/PyMissingTypeHintsInspection/" + getTestName(true) + ".py");
+ myFixture.enableInspections(PyMissingTypeHintsInspection.class);
+ myFixture.checkHighlighting(false, false, true);
+ }
+ finally {
+ PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), null);
+ }
+ }
+}