i18n: Extract messages from and annotate several Python inspections

* PyFinalInspection
* PyFromFutureImportInspection
* PyInconsistentIndentationInspection
* PyInterpreterInspection
* PyListCreationInspection
* PyMandatoryEncodingInspection
* PyMissingTypeHintsInspection
* PyNonAsciiCharInspection
* PyOverloadsInspection
* PyPackageRequirementsInspection
* PyPep8NamingInspection
* PyPropertyDefinitionInspection
* PyProtectedMemberInspection
* PyProtocolInspection
* PyShadowingBuiltinsInspection
* PyStatementEffectInspection
* PyStringFormatInspection
* PyTupleAssignmentBalanceInspection

I also replaced some existing message keys that used poorly recognized "$1"
notation or otherwise diverged from the convention in use, and updated
annotations in PythonUiService where needed.

GitOrigin-RevId: 75d73d38104c806ad5065e87f76e274b502e889d
This commit is contained in:
Mikhail Golubev
2020-08-21 10:03:22 +00:00
committed by intellij-monorepo-bot
parent 1b58c59529
commit 0e3afcf3ef
24 changed files with 341 additions and 218 deletions
@@ -133,10 +133,10 @@
<localInspection language="Python" shortName="PyDictDuplicateKeysInspection" suppressId="PyDictDuplicateKeys" bundle="messages.PyPsiBundle" key="INSP.NAME.duplicate.keys" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyDictDuplicateKeysInspection"/>
<localInspection language="Python" shortName="PyDunderSlotsInspection" suppressId="PyDunderSlots" bundle="messages.PyPsiBundle" key="INSP.NAME.dunder.slots" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyDunderSlotsInspection"/>
<localInspection language="Python" shortName="PyExceptClausesOrderInspection" suppressId="PyExceptClausesOrder" bundle="messages.PyPsiBundle" key="INSP.NAME.bad.except.clauses.order" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyExceptClausesOrderInspection"/>
<localInspection language="Python" shortName="PyFinalInspection" suppressId="PyFinal" bundle="messages.PyPsiBundle" key="INSP.final.classes.methods.and.variables" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyFinalInspection"/>
<localInspection language="Python" shortName="PyFinalInspection" suppressId="PyFinal" bundle="messages.PyPsiBundle" key="INSP.NAME.final.classes.methods.and.variables" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyFinalInspection"/>
<localInspection language="Python" shortName="PyFromFutureImportInspection" suppressId="PyFromFutureImport" bundle="messages.PyPsiBundle" key="INSP.NAME.from.future.import" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyFromFutureImportInspection"/>
<localInspection language="Python" shortName="PyGlobalUndefinedInspection" suppressId="PyGlobalUndefined" bundle="messages.PyPsiBundle" key="INSP.global.undefined" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyGlobalUndefinedInspection"/>
<localInspection language="Python" shortName="PyInconsistentIndentationInspection" suppressId="PyInconsistentIndentation" bundle="messages.PyPsiBundle" key="INSP.inconsistent.indentation" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyInconsistentIndentationInspection"/>
<localInspection language="Python" shortName="PyInconsistentIndentationInspection" suppressId="PyInconsistentIndentation" bundle="messages.PyPsiBundle" key="INSP.NAME.inconsistent.indentation" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyInconsistentIndentationInspection"/>
<localInspection language="Python" shortName="PyIncorrectDocstringInspection" suppressId="PyIncorrectDocstring" bundle="messages.PyPsiBundle" key="INSP.NAME.incorrect.docstring" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyIncorrectDocstringInspection"/>
<localInspection language="Python" shortName="PyMissingOrEmptyDocstringInspection" suppressId="PyMissingOrEmptyDocstring" bundle="messages.PyPsiBundle" key="INSP.NAME.missing.or.empty.docstring" groupKey="INSP.GROUP.python" enabledByDefault="false" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyMissingOrEmptyDocstringInspection"/>
<localInspection language="Python" shortName="PyNamedTupleInspection" suppressId="PyNamedTuple" bundle="messages.PyPsiBundle" key="INSP.named.tuple" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyNamedTupleInspection"/>
@@ -150,7 +150,7 @@
<localInspection language="Python" shortName="PyInitNewSignatureInspection" suppressId="PyInitNewSignature" bundle="messages.PyPsiBundle" key="INSP.NAME.new.init.signature" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyInitNewSignatureInspection"/>
<localInspection language="Python" shortName="PyTrailingSemicolonInspection" suppressId="PyTrailingSemicolon" bundle="messages.PyPsiBundle" key="INSP.NAME.trailing.semicolon" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyTrailingSemicolonInspection"/>
<localInspection language="Python" shortName="PyReturnFromInitInspection" suppressId="PyReturnFromInit" bundle="messages.PyPsiBundle" key="INSP.NAME.init.return" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyReturnFromInitInspection"/>
<localInspection language="Python" shortName="PyTupleAssignmentBalanceInspection" suppressId="PyTupleAssignmentBalance" bundle="messages.PyPsiBundle" key="INSP.NAME.incorrect.assignment" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyTupleAssignmentBalanceInspection"/>
<localInspection language="Python" shortName="PyTupleAssignmentBalanceInspection" suppressId="PyTupleAssignmentBalance" bundle="messages.PyPsiBundle" key="INSP.NAME.tuple.assignment.balance" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyTupleAssignmentBalanceInspection"/>
<localInspection language="Python" shortName="PyClassicStyleClassInspection" suppressId="PyClassicStyleClass" bundle="messages.PyPsiBundle" key="INSP.NAME.classic.class.usage" groupKey="INSP.GROUP.python" enabledByDefault="false" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyClassicStyleClassInspection"/>
<localInspection language="Python" shortName="PyExceptionInheritInspection" suppressId="PyExceptionInherit" bundle="messages.PyPsiBundle" key="INSP.NAME.exception.not.inherit" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyExceptionInheritInspection"/>
<localInspection language="Python" shortName="PyUnboundLocalVariableInspection" suppressId="PyUnboundLocalVariable" bundle="messages.PyPsiBundle" key="INSP.NAME.unbound" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyUnboundLocalVariableInspection"/>
@@ -172,22 +172,22 @@
<localInspection language="Python" shortName="PyDecoratorInspection" suppressId="PyDecorator" bundle="messages.PyPsiBundle" key="INSP.NAME.decorator.outside.class" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyDecoratorInspection"/>
<localInspection language="Python" shortName="PyTypeCheckerInspection" suppressId="PyTypeChecker" bundle="messages.PyPsiBundle" key="INSP.type.checker" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyTypeCheckerInspection"/>
<localInspection language="Python" shortName="PyDeprecationInspection" suppressId="PyDeprecation" bundle="messages.PyPsiBundle" key="INSP.NAME.deprecated.function.class.or.module" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyDeprecationInspection"/>
<localInspection language="Python" shortName="PyMandatoryEncodingInspection" suppressId="PyMandatoryEncoding" bundle="messages.PyPsiBundle" key="INSP.mandatory.encoding" groupKey="INSP.GROUP.python" enabledByDefault="false" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyMandatoryEncodingInspection"/>
<localInspection language="Python" shortName="PyMandatoryEncodingInspection" suppressId="PyMandatoryEncoding" bundle="messages.PyPsiBundle" key="INSP.NAME.mandatory.encoding" groupKey="INSP.GROUP.python" enabledByDefault="false" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyMandatoryEncodingInspection"/>
<localInspection language="Python" shortName="PyClassHasNoInitInspection" suppressId="PyClassHasNoInit" bundle="messages.PyPsiBundle" key="INSP.class.has.no.init" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyClassHasNoInitInspection"/>
<localInspection language="Python" shortName="PyNoneFunctionAssignmentInspection" suppressId="PyNoneFunctionAssignment" bundle="messages.PyPsiBundle" key="INSP.assigning.function.call.that.doesnt.return.anything" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyNoneFunctionAssignmentInspection"/>
<localInspection language="Python" shortName="PyProtectedMemberInspection" suppressId="PyProtectedMember" bundle="messages.PyPsiBundle" key="INSP.protected.member" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyProtectedMemberInspection"/>
<localInspection language="Python" shortName="PyProtectedMemberInspection" suppressId="PyProtectedMember" bundle="messages.PyPsiBundle" key="INSP.NAME.protected.member" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyProtectedMemberInspection"/>
<localInspection language="Python" shortName="PyMethodMayBeStaticInspection" suppressId="PyMethodMayBeStatic" bundle="messages.PyPsiBundle" key="INSP.method.may.be.static" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyMethodMayBeStaticInspection"/>
<localInspection language="Python" shortName="PyDocstringTypesInspection" suppressId="PyDocstringTypes" bundle="messages.PyPsiBundle" key="INSP.NAME.docstring.types" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyDocstringTypesInspection"/>
<localInspection language="Python" shortName="PyShadowingNamesInspection" suppressId="PyShadowingNames" bundle="messages.PyPsiBundle" key="INSP.shadowing.names" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyShadowingNamesInspection"/>
<localInspection language="Python" shortName="PyAbstractClassInspection" suppressId="PyAbstractClass" bundle="messages.PyPsiBundle" key="INSP.abstract.class" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyAbstractClassInspection"/>
<localInspection language="Python" shortName="PyMissingTypeHintsInspection" suppressId="PyMissingTypeHints" bundle="messages.PyPsiBundle" key="INSP.missing.type.hints" groupKey="INSP.GROUP.python" enabledByDefault="false" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyMissingTypeHintsInspection"/>
<localInspection language="Python" shortName="PyOverloadsInspection" suppressId="PyOverloads" bundle="messages.PyPsiBundle" key="INSP.overloads.in.regular.python.files" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyOverloadsInspection"/>
<localInspection language="Python" shortName="PyProtocolInspection" suppressId="PyProtocol" bundle="messages.PyPsiBundle" key="INSP.protocol.definition.and.usages" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyProtocolInspection"/>
<localInspection language="Python" shortName="PyMissingTypeHintsInspection" suppressId="PyMissingTypeHints" bundle="messages.PyPsiBundle" key="INSP.NAME.missing.type.hints" groupKey="INSP.GROUP.python" enabledByDefault="false" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyMissingTypeHintsInspection"/>
<localInspection language="Python" shortName="PyOverloadsInspection" suppressId="PyOverloads" bundle="messages.PyPsiBundle" key="INSP.NAME.overloads.in.regular.python.files" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyOverloadsInspection"/>
<localInspection language="Python" shortName="PyProtocolInspection" suppressId="PyProtocol" bundle="messages.PyPsiBundle" key="INSP.NAME.protocol.definition.and.usages" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyProtocolInspection"/>
<localInspection language="Python" shortName="PyTypeHintsInspection" suppressId="PyTypeHints" bundle="messages.PyPsiBundle" key="INSP.type.hints" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyTypeHintsInspection"/>
<localInspection language="Python" shortName="PyTypedDictInspection" suppressId="PyTypedDict" bundle="messages.PyPsiBundle" key="INSP.typed.dict" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyTypedDictInspection"/>
<localInspection language="Python" shortName="PyChainedComparisonsInspection" suppressId="PyChainedComparisons" bundle="messages.PyPsiBundle" key="INSP.NAME.chained.comparisons" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyChainedComparisonsInspection"/>
<localInspection language="Python" shortName="PyPep8NamingInspection" suppressId="PyPep8Naming" bundle="messages.PyPsiBundle" key="INSP.pep8.naming" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyPep8NamingInspection"/>
<localInspection language="Python" shortName="PyShadowingBuiltinsInspection" suppressId="PyShadowingBuiltins" bundle="messages.PyPsiBundle" key="INSP.shadowing.builtins" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyShadowingBuiltinsInspection"/>
<localInspection language="Python" shortName="PyPep8NamingInspection" suppressId="PyPep8Naming" bundle="messages.PyPsiBundle" key="INSP.NAME.pep8.naming" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyPep8NamingInspection"/>
<localInspection language="Python" shortName="PyShadowingBuiltinsInspection" suppressId="PyShadowingBuiltins" bundle="messages.PyPsiBundle" key="INSP.NAME.shadowing.builtins" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyShadowingBuiltinsInspection"/>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.PyConvertMethodToPropertyIntention</className>
@@ -119,7 +119,6 @@ can.t.assign.to.await.expression=Can't assign to await expression
for.expected='for' expected
rarrow.expected='->' expected
unexpected.tokens=Unexpected tokens
enable.in.python.3=Enable in Python 3+
PARSE.function.type.annotations.py2=Type annotations are unsupported in Python 2
PARSE.function.return.type.annotations.py2=Return type annotations are unsupported in Python 2
@@ -438,13 +437,7 @@ INSP.GROUP.python=Python
INSP.abstract.class.set.as.metaclass=Set ''{0}'' as metaclass
INSP.abstract.class.add.to.superclasses=Add ''{0}'' to superclasses
INSP.pep8.naming=PEP 8 naming convention violation
INSP.pep8.naming.excluded.base.classes=Excluded base classes
INSP.pep8.naming.ignored.errors=Ignored errors
INSP.shadowing.builtins=Shadowing built-ins
INSP.final.classes.methods.and.variables=Final classes, methods and variables
INSP.global.undefined=Global variable is undefined at the module level
INSP.inconsistent.indentation=Inconsistent indentation
INSP.named.tuple=Namedtuple definition
INSP.shadows.name.from.outer.scope=Shadows name ''{0}'' from outer scope
INSP.trailing.semicolon=Trailing semicolon in the statement
@@ -457,13 +450,7 @@ INSP.interpreter.configure.python.interpreter=Configure Python interpreter
INSP.interpreter.interpreter.settings=Interpreter settings
INSP.interpreter.use.interpreter=Use {0}
INSP.interpreter.use.suggested.interpreter=Use suggested interpreter
INSP.mandatory.encoding.encoding.comment.format=Encoding comment format:
INSP.mandatory.encoding.select.default.encoding=Select default encoding:
INSP.mandatory.encoding.no.encoding.specified.for.file=No encoding specified for file
INSP.method.parameters.metaclass.method.first.argument.name=Metaclass method first argument name
INSP.missing.type.hints.add.type.hints=Add type hints
INSP.missing.type.hints.add.type.hints.for=Add type hints for ''{0}''
INSP.missing.type.hints.only.when.types.are.known.collected.from.run.time.or.inferred=Only when types are known(collected from run-time or inferred)
INSP.package.requirements.requirements.have.been.ignored=Requirements have been ignored
INSP.package.requirements.requirement.has.been.ignored=''{0}'' has been ignored
@@ -477,21 +464,15 @@ INSP.package.requirements.administrator.privileges.required.button.configure=Con
INSP.package.requirements.administrator.privileges.required.button.install.anyway=Install Anyway
INSP.package.requirements.requirements.file.empty=Requirements file is empty
INSP.package.requirements.quickfix.family.name=Add imported packages to requirements...
INSP.pep8.ignore.base.class=Ignore base class
INSP.pep8.ignore.base.class=Ignore Base Class
INSP.pep8.ignore.method.names.for.descendants.of.class=Ignore method names for descendants of class
INSP.shadowing.builtins.ignore.shadowed.built.in.name=Ignore shadowed built-in name
INSP.stub.packages.compatibility.ignore=Ignore ''{0}'' compatibility
INSP.stub.packages.compatibility.ignored.packages=Ignored stub packages
INSP.stub.packages.compatibility.incompatible.packages.message=''{0}{1}{2}'' is incompatible with ''{3}{4}{5}''. Expected ''{6}'' version: [{7}]
INSP.arguments.not.declared.but.provided.by.decorator=Following arguments are not declared but provided by decorator: {0}
INSP.abstract.class=Class must implement all abstract methods
INSP.assigning.function.call.that.doesnt.return.anything=Assigning function call that doesn't return anything
INSP.mandatory.encoding=No encoding specified for file
INSP.missing.type.hints=Missing type hinting for function definition
INSP.overloads.in.regular.python.files=Overloads in regular Python files
INSP.pep8.coding.style.violation=PEP 8 coding style violation
INSP.protected.member=Access to a protected member of a class or a module
INSP.protocol.definition.and.usages=Protocol definition and usages
INSP.shadowing.names=Shadowing names from outer scopes
INSP.stub.packages.compatibility=Stub packages compatibility inspection
INSP.stub.packages=Stub packages advertiser
@@ -542,6 +523,16 @@ INSP.unused.import.statement=Unused import statement <code>#ref</code>
# PyInterpreterInspection
INSP.NAME.invalid.interpreter=Invalid interpreter configured
INSP.interpreter.pipenv.interpreter.associated.with.another.project=Pipenv interpreter is associated with another project: ''{0}''
INSP.interpreter.pipenv.interpreter.associated.with.another.module=Pipenv interpreter is associated with another module: ''{0}''
INSP.interpreter.pipenv.interpreter.not.associated.with.any.project=Pipenv interpreter is not associated with any project
INSP.interpreter.pipenv.interpreter.not.associated.with.any.module=Pipenv interpreter is not associated with any module
INSP.interpreter.invalid.python.interpreter.selected.for.project=Invalid Python interpreter selected for the project
INSP.interpreter.invalid.python.interpreter.selected.for.module=Invalid Python interpreter selected for the module
INSP.interpreter.python.has.reached.its.end.of.life.and.is.no.longer.supported.in.pycharm=Python {0} has reached its end-of-life date and it is no longer supported in PyCharm
INSP.interpreter.python.has.reached.its.end.life.and.is.no.longer.supported.in.python.plugin=Python {0} has reached its end-of-life date and it is no longer supported in Python plugin
INSP.interpreter.no.python.interpreter.configured.for.project=No Python interpreter configured for the project
INSP.interpreter.no.python.interpreter.configured.for.module=No Python interpreter configured for the module
# ReturnValueFromInitInspection
INSP.NAME.init.return=__init__ method that returns a value
@@ -554,8 +545,8 @@ INSP.unreachable.code=This code is unreachable
# PyStringFormatInspection
INSP.NAME.str.format=Errors in string formatting operations
INSP.format.requires.no.mapping=Format doesn't require a mapping
INSP.key.$0.has.no.arg=Key ''{0}'' has no corresponding argument
INSP.unexpected.type.$0=Unexpected type {0}
INSP.str.format.key.has.no.argument=Key ''{0}'' has no corresponding argument
INSP.str.format.unexpected.argument.type=Unexpected type {0}
INSP.too.few.keys=Too few mapping keys
INSP.no.format.specifier.char=Format specifier character missing
INSP.format.requires.mapping=Format requires a mapping
@@ -566,6 +557,8 @@ INSP.unused.mapping = Mapping key "{0}" is unused
INSP.unsupported.format.character=Unsupported format character ''{0}''
INSP.manual.to.auto.field.numbering=Cannot switch from manual field specification to automatic field numbering
INSP.auto.to.manual.field.numbering=Cannot switch from automatic field numbering to manual field specification
INSP.str.format.unsupported.format.character.b=Unsupported format character 'b'
INSP.str.format.can.not.use.star.in.formats.when.using.mapping=Can't use '*' in formats when using a mapping
# PyMethodOverridingInspection
INSP.NAME.method.over=Method signature does not match signature of overridden method
@@ -589,9 +582,13 @@ INSP.unbound.function.too.large=Function ''{0}'' is too large to analyse
# PyListCreationInspection
INSP.NAME.list.creation=List creation could be rewritten by list literal
INSP.list.creation.this.list.creation.could.be.rewritten.as.list.literal=This list creation could be rewritten as a list literal
# PyTupleAssignmentBalanceInspection
INSP.NAME.incorrect.assignment=Tuple assignment balance is incorrect
INSP.NAME.tuple.assignment.balance=Tuple assignment balance is incorrect
INSP.tuple.assignment.balance.only.one.starred.expression.allowed.in.assignment=Only one starred expression allowed in assignment
INSP.tuple.assignment.balance.need.more.values.to.unpack=Need more values to unpack
INSP.tuple.assignment.balance.too.many.values.to.unpack=Too many values to unpack
# PyClassicStyleClassInspection
INSP.NAME.classic.class.usage=Classic style class usage
@@ -613,7 +610,8 @@ INSP.docstring.types.dynamically.inferred.type.does.not.match.specified.type=Dyn
# PyStatementEffectInspection
INSP.NAME.statement.effect=Statement has no effect
INSP.NAME.statement.message=Statement seems to have no effect
INSP.statement.effect.statement.seems.to.have.no.effect=Statement seems to have no effect
INSP.statement.effect.statement.having.no.effect.can.be.replaced.with.function.call=Statement seems to have no effect and can be replaced with function call to have effect
# PyStringExceptionInspection
INSP.NAME.raising.string.exception=Raising a string exception
@@ -622,11 +620,16 @@ INSP.NAME.raising.string.exception=Raising a string exception
INSP.NAME.wrong.super.arguments=Wrong arguments to call super
INSP.$0.is.not.superclass.of.$1=''{0}'' is not an instance or a subclass of ''{1}''
# PynonAsciiCharInspection
# PyNonAsciiCharInspection
INSP.NAME.non.ascii=File contains non-ASCII character
INSP.non.ascii.char.non.ascii.character.in.file.but.no.encoding.declared=Non-ASCII character ''{0}'' in file, but no encoding declared
# PyMandatoryEncodingInspection
INSP.NAME.mandatory.encoding=No encoding specified for file
INSP.mandatory.encoding.label.encoding.comment.format=Encoding comment format:
INSP.mandatory.encoding.label.select.default.encoding=Select default encoding:
INSP.mandatory.encoding.checkbox.enable.in.python.3=Enable in Python 3+
INSP.mandatory.encoding.no.encoding.specified.for.file=No encoding specified for file
# PyTupleItemAssignmentInspection
INSP.NAME.tuple.item.assignment=Tuple item assignment
@@ -652,8 +655,10 @@ INSP.deleter.signature.advice=Deleter signature should be (self)
INSP.accessor.first.param.is.$0=First parameter of an accessor is usually called ''{0}''
# PyProtectedMemberInspection
INSP.protected.member.$0.access=Access to a protected member {0} of a class
INSP.protected.member.$0.access.module=Access to a protected member {0} of a module
INSP.NAME.protected.member=Access to a protected member of a class or a module
INSP.protected.member.access.to.protected.member.of.class=Access to a protected member {0} of a class
INSP.protected.member.access.to.protected.member.of.module=Access to a protected member {0} of a module
INSP.protected.member.name.not.declared.in.all=''{0}'' is not declared in __all__
# PyOldStyleClassesInspection
INSP.NAME.oldstyle.class=Old-style class contains new-style class features
@@ -739,6 +744,11 @@ INSP.decorators.method.only.decorator.on.method.outside.class=Decorator {0} on m
# PyPackageRequirementsInspection
INSP.NAME.requirements=Package requirements
INSP.requirements.column.name.ignore.packages=Ignore Packages
INSP.requirements.package.requirements.not.satisfied=Package {1,choice,1#requirement|2#requirements} {0} {1,choice,1#is|2#are} not satisfied
INSP.requirements.package.containing.module.not.listed.in.project.requirements=Package containing module ''{0}'' is not listed in project requirements
QFIX.NAME.install.requirements=Install {0,choice,1#requirement|2#requirements}
QFIX.NAME.ignore.requirements=Ignore {0,choice,1#requirement|2#requirements}
# PyClassHasNoInitInspection
INSP.NAME.class.has.no.init=Class has no __init__ method
@@ -796,6 +806,7 @@ INSP.duplicate.keys.dictionary.contains.duplicate.keys=Dictionary contains dupli
# PyFromFutureImportInspection
INSP.NAME.from.future.import=from __future__ import must be the first executable statement
INSP.from.future.import.from.future.imports.must.occur.at.beginning.file=from __future__ imports must occur at the beginning of the file
# PyMethodFirstArgAssignmentInspection
INSP.NAME.first.arg.assign=Reassignment of method's first argument
@@ -907,17 +918,85 @@ INSP.dataclasses.method.should.be.called.on.attrs.types=''{0}'' method should be
# PyHighlightingAnnotator
INSP.python.trailing.suffix.not.support=Python does not support a trailing ''{0}''
# PyInterpreterInspection
python.sdk.no.interpreter.configured.owner=No Python interpreter configured for the {0}
# PyDeprecationInspection
INSP.NAME.deprecated.function.class.or.module=Deprecated function, class or module
INSP.deprecation.abc.decorator.deprecated.use.alternative=''{0}'' is deprecated since Python 3.3. Use ''{1}'' with ''{2}'' instead
# PyDunderSlotsInspection
INSP.NAME.dunder.slots=Definition of __slots__ in a class
INSP.dunder.slots.name.in.slots.conflicts.with.class.variable=''{0}'' in __slots__ conflicts with class variable
INSP.dunder.slots.class.object.attribute.read.only=''{0}'' object attribute ''{1}'' is read-only
# PyFinalInspection
INSP.NAME.final.classes.methods.and.variables=Final classes, methods and variables
INSP.final.super.classes.are.marked.as.final.and.should.not.be.subclassed={0} {1,choice,1#is|2#are} marked as ''@final'' and should not be subclassed
INSP.final.final.should.be.placed.on.first.overload='@final' should be placed on the first overload
INSP.final.method.marked.as.final.should.not.be.overridden=''{0}'' is marked as ''@final'' and should not be overridden
INSP.final.final.should.be.placed.on.implementation='@final' should be placed on the implementation
INSP.final.final.could.not.be.mixed.with.abstract.decorators='Final' could not be mixed with abstract decorators
INSP.final.final.class.could.not.contain.abstract.methods='Final' class could not contain abstract methods
INSP.final.no.need.to.mark.method.in.final.class.as.final=No need to mark method in 'Final' class as '@final'
INSP.final.non.method.function.could.not.be.marked.as.final=Non-method function could not be marked as '@final'
INSP.final.final.could.not.be.used.in.annotations.for.function.parameters='Final' could not be used in annotations for function parameters
INSP.final.final.could.not.be.used.in.annotation.for.function.return.value='Final' could not be used in annotation for function return value
INSP.final.if.assigned.value.omitted.there.should.be.explicit.type.argument.to.final=If assigned value is omitted, there should be an explicit type argument to 'Final'
INSP.final.final.name.should.be.initialized.with.value='Final' name should be initialized with a value
INSP.final.already.declared.name.could.not.be.redefined.as.final=Already declared name could not be redefined as 'Final'
INSP.final.either.instance.attribute.or.class.attribute.could.be.type.hinted.as.final=Either instance attribute or class attribute could be type hinted as 'Final'
INSP.final.final.attribute.could.not.be.overridden=''{0}'' is ''Final'' and could not be overridden
INSP.final.final.attribute.should.be.declared.in.class.body.or.init='Final' attribute should be declared in class body or '__init__'
INSP.final.final.target.could.not.be.reassigned=''{0}'' is ''Final'' and could not be reassigned
INSP.final.final.could.only.be.used.as.outermost.type='Final' could only be used as the outermost type
INSP.final.final.could.not.be.used.inside.loop='Final' could not be used inside a loop
# PyInconsistentIndentationInspection
INSP.NAME.inconsistent.indentation=Inconsistent indentation
INSP.inconsistent.indentation.mix.tabs.spaces=Inconsistent indentation: mix of tabs and spaces
INSP.inconsistent.indentation.previous.line.used.tabs.this.line.uses.spaces=Inconsistent indentation: previous line used tabs, this line uses spaces
INSP.inconsistent.indentation.previous.line.used.spaces.this.line.uses.tabs=Inconsistent indentation: previous line used spaces, this line uses tabs
# PyMissingTypeHintsInspection
INSP.NAME.missing.type.hints=Missing type hinting for function definition
INSP.missing.type.hints.type.hinting.missing.for.function.definition=Type hinting is missing for function definition
INSP.missing.type.hints.add.type.hints=Add type hints
INSP.missing.type.hints.add.type.hints.for=Add type hints for ''{0}''
INSP.missing.type.hints.checkbox.only.when.types.are.known=Only when types are known (collected from run-time or inferred)
# PyOverloadsInspection
INSP.NAME.overloads.in.regular.python.files=Overloads in regular Python files
INSP.overloads.series.overload.decorated.methods.should.always.be.followed.by.implementation=A series of @overload-decorated methods should always be followed by an implementation that is not @overload-ed
INSP.overloads.series.overload.decorated.functions.should.always.be.followed.by.implementation=A series of @overload-decorated functions should always be followed by an implementation that is not @overload-ed
INSP.overloads.this.method.overload.signature.not.compatible.with.implementation=Signature of this @overload-decorated method is not compatible with the implementation
INSP.overloads.this.function.overload.signature.not.compatible.with.implementation=Signature of this @overload-decorated function is not compatible with the implementation
# PyPep8NamingInspection
INSP.NAME.pep8.naming=PEP 8 naming convention violation
INSP.pep8.naming.column.name.excluded.base.classes=Excluded Base Classes
INSP.pep8.naming.column.name.ignored.errors=Ignored Errors
QFIX.NAME.ignore.errors.like.this=Ignore errors like this
INSP.pep8.naming.class.names.should.use.camelcase.convention=Class names should use CamelCase convention
INSP.pep8.naming.function.name.should.be.lowercase=Function name should be lowercase
INSP.pep8.naming.argument.name.should.be.lowercase=Argument name should be lowercase
INSP.pep8.naming.variable.in.function.should.be.lowercase=Variable in function should be lowercase
INSP.pep8.naming.constant.variable.imported.as.non.constant=Constant variable imported as non constant
INSP.pep8.naming.lowercase.variable.imported.as.non.lowercase=Lowercase variable imported as non lowercase
INSP.pep8.naming.camelcase.variable.imported.as.lowercase=CamelCase variable imported as lowercase
INSP.pep8.naming.camelcase.variable.imported.as.constant=CamelCase variable imported as constant
# PyProtocolInspection
INSP.NAME.protocol.definition.and.usages=Protocol definition and usages
INSP.protocol.all.bases.protocol.must.be.protocols=All bases of a protocol must be protocols
INSP.protocol.only.runtime.checkable.protocols.can.be.used.with.instance.class.checks=Only @runtime_checkable protocols can be used with instance and class checks
INSP.protocol.newtype.cannot.be.used.with.protocol.classes=NewType cannot be used with protocol classes
INSP.protocol.element.type.incompatible.with.protocol=Type of ''{0}'' is incompatible with ''{1}''
# PyShadowingBuiltinsInspection
INSP.NAME.shadowing.builtins=Shadowing built-ins
INSP.shadowing.builtins.shadows.built.in.name=Shadows built-in name ''{0}''
INSP.shadowing.builtins.column.name.ignore.built.ins=Ignore Built-Ins
QFIX.FAMILY.NAME.ignore.shadowed.built.in.name=Ignore shadowed built-in name
QFIX.NAME.ignore.shadowed.built.in.name=Ignore shadowed built-in name "{0}"
# PyInspectionsSuppressor
INSP.python.suppressor.suppress.for.function=Suppress for function
INSP.python.suppressor.suppress.for.class=Suppress for class
@@ -10,7 +10,6 @@ import com.intellij.openapi.ui.InputValidator;
import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.util.NlsContexts.Checkbox;
import com.intellij.openapi.util.NlsContexts.Label;
import com.intellij.openapi.util.NlsContexts.*;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
@@ -80,7 +79,7 @@ public class PythonUiService {
return null;
}
public JComponent createSingleCheckboxOptionsPanel(@Label String label, InspectionProfileEntry inspection, String property) {
public JComponent createSingleCheckboxOptionsPanel(@Checkbox String label, InspectionProfileEntry inspection, String property) {
return null;
}
@@ -109,7 +108,7 @@ public class PythonUiService {
return null;
}
public JComponent createListEditForm(String title, List<String> stringList) {
public JComponent createListEditForm(@ColumnName String title, List<String> stringList) {
return null;
}
@@ -4,9 +4,11 @@ package com.jetbrains.python.inspections
import com.intellij.codeInspection.LocalInspectionToolSession
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.util.NlsSafe
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.jetbrains.python.PyNames
import com.jetbrains.python.PyPsiBundle
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil
import com.jetbrains.python.codeInsight.functionTypeComments.psi.PyFunctionTypeAnnotation
@@ -33,8 +35,10 @@ class PyFinalInspection : PyInspection() {
node.getSuperClasses(myTypeEvalContext).filter { isFinal(it) }.let { finalSuperClasses ->
if (finalSuperClasses.isEmpty()) return@let
val postfix = " ${if (finalSuperClasses.size == 1) "is" else "are"} marked as '@final' and should not be subclassed"
registerProblem(node.nameIdentifier, finalSuperClasses.joinToString(postfix = postfix) { "'${it.name}'" })
@NlsSafe val superClassList = finalSuperClasses.joinToString { "'${it.name}'" }
registerProblem(node.nameIdentifier,
PyPsiBundle.message("INSP.final.super.classes.are.marked.as.final.and.should.not.be.subclassed",
superClassList, finalSuperClasses.size))
}
if (PyiUtil.isInsideStub(node)) {
@@ -43,7 +47,7 @@ class PyFinalInspection : PyInspection() {
node.visitMethods(
{ m ->
if (!visitedNames.add(m.name) && isFinal(m)) {
registerProblem(m.nameIdentifier, "'@final' should be placed on the first overload")
registerProblem(m.nameIdentifier, PyPsiBundle.message("INSP.final.final.should.be.placed.on.first.overload"))
}
true
},
@@ -71,13 +75,14 @@ class PyFinalInspection : PyInspection() {
.filterIsInstance<PyFunction>()
.firstOrNull { isFinal(it) }
?.let {
val qualifiedName = it.qualifiedName ?: it.containingClass?.name + "." + it.name
registerProblem(node.nameIdentifier, "'$qualifiedName' is marked as '@final' and should not be overridden")
@NlsSafe val qualifiedName = it.qualifiedName ?: it.containingClass?.name + "." + it.name
registerProblem(node.nameIdentifier,
PyPsiBundle.message("INSP.final.method.marked.as.final.should.not.be.overridden", qualifiedName))
}
if (!PyiUtil.isInsideStub(node)) {
if (isFinal(node) && PyiUtil.isOverload(node, myTypeEvalContext)) {
registerProblem(node.nameIdentifier, "'@final' should be placed on the implementation")
registerProblem(node.nameIdentifier, PyPsiBundle.message("INSP.final.final.should.be.placed.on.implementation"))
}
checkInstanceFinalsOutsideInit(node)
@@ -85,31 +90,34 @@ class PyFinalInspection : PyInspection() {
if (PyKnownDecoratorUtil.hasAbstractDecorator(node, myTypeEvalContext)) {
if (isFinal(node)) {
registerProblem(node.nameIdentifier, "'Final' could not be mixed with abstract decorators")
registerProblem(node.nameIdentifier, PyPsiBundle.message("INSP.final.final.could.not.be.mixed.with.abstract.decorators"))
}
else if (isFinal(cls)) {
val message = "'Final' class could not contain abstract methods"
val message = PyPsiBundle.message("INSP.final.final.class.could.not.contain.abstract.methods")
registerProblem(node.nameIdentifier, message)
registerProblem(cls.nameIdentifier, message)
}
}
else if (isFinal(node) && isFinal(cls)) {
registerProblem(node.nameIdentifier, "No need to mark method in 'Final' class as '@final'", ProblemHighlightType.WEAK_WARNING)
registerProblem(node.nameIdentifier, PyPsiBundle.message("INSP.final.no.need.to.mark.method.in.final.class.as.final"),
ProblemHighlightType.WEAK_WARNING)
}
}
else if (isFinal(node)) {
registerProblem(node.nameIdentifier, "Non-method function could not be marked as '@final'")
registerProblem(node.nameIdentifier, PyPsiBundle.message("INSP.final.non.method.function.could.not.be.marked.as.final"))
}
getFunctionTypeAnnotation(node)?.let { comment ->
if (comment.parameterTypeList.parameterTypes.any { resolvesToFinal(if (it is PySubscriptionExpression) it.operand else it) }) {
registerProblem(node.typeComment, "'Final' could not be used in annotations for function parameters")
registerProblem(node.typeComment,
PyPsiBundle.message("INSP.final.final.could.not.be.used.in.annotations.for.function.parameters"))
}
}
getReturnTypeAnnotation(node, myTypeEvalContext)?.let {
if (resolvesToFinal(if (it is PySubscriptionExpression) it.operand else it)) {
registerProblem(node.typeComment ?: node.annotation, "'Final' could not be used in annotation for function return value")
registerProblem(node.typeComment ?: node.annotation,
PyPsiBundle.message("INSP.final.final.could.not.be.used.in.annotation.for.function.return.value"))
}
}
}
@@ -121,12 +129,13 @@ class PyFinalInspection : PyInspection() {
node.annotation?.value?.let {
if (PyiUtil.isInsideStub(node) || ScopeUtil.getScopeOwner(node) is PyClass) {
if (resolvesToFinal(it)) {
registerProblem(it, "If assigned value is omitted, there should be an explicit type argument to 'Final'")
registerProblem(it,
PyPsiBundle.message("INSP.final.if.assigned.value.omitted.there.should.be.explicit.type.argument.to.final"))
}
}
else {
if (resolvesToFinal(if (it is PySubscriptionExpression) it.operand else it)) {
registerProblem(node, "'Final' name should be initialized with a value")
registerProblem(node, PyPsiBundle.message("INSP.final.final.name.should.be.initialized.with.value"))
}
}
}
@@ -136,7 +145,7 @@ class PyFinalInspection : PyInspection() {
}
if (isFinal(node) && PyUtil.multiResolveTopPriority(node, resolveContext).any { it != node }) {
registerProblem(node, "Already declared name could not be redefined as 'Final'")
registerProblem(node, PyPsiBundle.message("INSP.final.already.declared.name.could.not.be.redefined.as.final"))
}
}
@@ -144,7 +153,8 @@ class PyFinalInspection : PyInspection() {
super.visitPyNamedParameter(node)
if (isFinal(node)) {
registerProblem(node.annotation?.value ?: node.typeComment, "'Final' could not be used in annotations for function parameters")
registerProblem(node.annotation?.value ?: node.typeComment,
PyPsiBundle.message("INSP.final.final.could.not.be.used.in.annotations.for.function.parameters"))
}
}
@@ -209,7 +219,7 @@ class PyFinalInspection : PyInspection() {
initAttributes: Map<String, PyTargetExpression>) {
classLevelFinals.forEach { (name, psi) ->
if (!psi.hasAssignedValue() && name !in initAttributes) {
registerProblem(psi, "'Final' name should be initialized with a value")
registerProblem(psi, PyPsiBundle.message("INSP.final.final.name.should.be.initialized.with.value"))
}
}
}
@@ -221,10 +231,10 @@ class PyFinalInspection : PyInspection() {
if (sameNameClassLevelFinal != null && isFinal(initAttribute)) {
if (sameNameClassLevelFinal.hasAssignedValue()) {
registerProblem(initAttribute, "Already declared name could not be redefined as 'Final'")
registerProblem(initAttribute, PyPsiBundle.message("INSP.final.already.declared.name.could.not.be.redefined.as.final"))
}
else {
val message = "Either instance attribute or class attribute could be type hinted as 'Final'"
val message = PyPsiBundle.message("INSP.final.either.instance.attribute.or.class.attribute.could.be.type.hinted.as.final")
registerProblem(sameNameClassLevelFinal, message)
registerProblem(initAttribute, message)
}
@@ -256,7 +266,8 @@ class PyFinalInspection : PyInspection() {
if (notRegistered.isEmpty()) return
for (commonFinal in newFinals.keys.intersect(inheritedFinals.keys)) {
registerProblem(newFinals[commonFinal], "'$ancestorName.$commonFinal' is 'Final' and could not be overridden")
@NlsSafe val qualifiedName = "$ancestorName.$commonFinal"
registerProblem(newFinals[commonFinal], PyPsiBundle.message("INSP.final.final.attribute.could.not.be.overridden", qualifiedName))
notRegistered.remove(commonFinal)
}
}
@@ -267,7 +278,7 @@ class PyFinalInspection : PyInspection() {
val instanceAttributes = mutableMapOf<String, PyTargetExpression>()
PyClassImpl.collectInstanceAttributes(method, instanceAttributes)
instanceAttributes.values.forEach {
if (isFinal(it)) registerProblem(it, "'Final' attribute should be declared in class body or '__init__'")
if (isFinal(it)) registerProblem(it, PyPsiBundle.message("INSP.final.final.attribute.should.be.declared.in.class.body.or.init"))
}
}
@@ -285,7 +296,7 @@ class PyFinalInspection : PyInspection() {
}
if (resolved.any { it is PyTargetExpression && isFinal(it) }) {
registerProblem(target, "'${target.name}' is 'Final' and could not be reassigned")
registerProblem(target, PyPsiBundle.message("INSP.final.final.target.could.not.be.reassigned", target.name))
return
}
@@ -293,7 +304,7 @@ class PyFinalInspection : PyInspection() {
if (myTypeEvalContext.maySwitchToAST(e) &&
e.parent.let { it is PyNonlocalStatement || it is PyGlobalStatement } &&
PyUtil.multiResolveTopPriority(e, resolveContext).any { it is PyTargetExpression && isFinal(it) }) {
registerProblem(target, "'${target.name}' is 'Final' and could not be reassigned")
registerProblem(target, PyPsiBundle.message("INSP.final.final.target.could.not.be.reassigned", target.name))
return
}
}
@@ -315,13 +326,14 @@ class PyFinalInspection : PyInspection() {
ScopeUtil.getScopeOwner(target).let { it is PyFunction && PyUtil.turnConstructorIntoClass(it) == cls }) {
return
}
registerProblem(target, "'$name' is 'Final' and could not be reassigned")
registerProblem(target, PyPsiBundle.message("INSP.final.final.target.could.not.be.reassigned", name))
}
for (ancestor in cls.getAncestorClasses(myTypeEvalContext)) {
val inheritedClassAttribute = ancestor.findClassAttribute(name, false, myTypeEvalContext)
if (inheritedClassAttribute != null && !inheritedClassAttribute.hasAssignedValue() && isFinal(inheritedClassAttribute)) {
registerProblem(target, "'${ancestor.name}.$name' is 'Final' and could not be reassigned")
@NlsSafe val qualifiedName = "${ancestor.name}.$name"
registerProblem(target, PyPsiBundle.message("INSP.final.final.target.could.not.be.reassigned", qualifiedName))
return
}
}
@@ -332,8 +344,8 @@ class PyFinalInspection : PyInspection() {
val attributesInInit = mutableMapOf<String, PyTargetExpression>()
PyClassImpl.collectInstanceAttributes(init, attributesInInit)
if (attributesInInit[name]?.let { it != target && isFinal(it) } == true) {
val qualifier = if (cls == current) "" else "${current.name}."
registerProblem(target, "'$qualifier$name' is 'Final' and could not be reassigned")
@NlsSafe val qualifiedName = (if (cls == current) "" else "${current.name}.") + name
registerProblem(target, PyPsiBundle.message("INSP.final.final.target.could.not.be.reassigned", qualifiedName))
break
}
}
@@ -347,7 +359,8 @@ class PyFinalInspection : PyInspection() {
val ancestorClassAttribute = ancestor.findClassAttribute(name, false, myTypeEvalContext)
if (ancestorClassAttribute != null && ancestorClassAttribute.hasAssignedValue() && isFinal(ancestorClassAttribute)) {
registerProblem(target, "'${ancestor.name}.$name' is 'Final' and could not be reassigned")
@NlsSafe val qualifiedName = "${ancestor.name}.$name"
registerProblem(target, PyPsiBundle.message("INSP.final.final.target.could.not.be.reassigned", qualifiedName))
break
}
}
@@ -360,7 +373,7 @@ class PyFinalInspection : PyInspection() {
}
if (isInAnnotationOrTypeComment(node) && resolvesToFinal(node)) {
registerProblem(node, "'Final' could only be used as the outermost type")
registerProblem(node, PyPsiBundle.message("INSP.final.final.could.only.be.used.as.outermost.type"))
}
}
@@ -376,7 +389,7 @@ class PyFinalInspection : PyInspection() {
override fun visitPyWhileStatement(node: PyWhileStatement) {}
override fun visitPyTargetExpression(node: PyTargetExpression) {
if (isFinal(node)) registerProblem(node, "'Final' could not be used inside a loop")
if (isFinal(node)) registerProblem(node, PyPsiBundle.message("INSP.final.final.could.not.be.used.inside.loop"))
}
}
)
@@ -20,6 +20,7 @@ import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.inspections.quickfix.MoveFromFutureImportQuickFix;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
@@ -69,7 +70,7 @@ public class PyFromFutureImportInspection extends PyInspection {
continue;
}
}
registerProblem(node, "from __future__ imports must occur at the beginning of the file",
registerProblem(node, PyPsiBundle.message("INSP.from.future.import.from.future.imports.must.occur.at.beginning.file"),
new MoveFromFutureImportQuickFix());
return;
}
@@ -18,15 +18,16 @@ package com.jetbrains.python.inspections;
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.util.InspectionMessage;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IElementType;
import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.inspections.quickfix.ConvertIndentsFix;
import com.jetbrains.python.lexer.PythonIndentingLexer;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -94,7 +95,7 @@ public class PyInconsistentIndentationInspection extends PyInspection {
}
final int problemStart = tokenStart + lastLF + 1;
if (spaces > 0 && tabs > 0) {
reportProblem("Inconsistent indentation: mix of tabs and spaces", problemStart, length);
reportProblem(PyPsiBundle.message("INSP.inconsistent.indentation.mix.tabs.spaces"), problemStart, length);
// don't know which one is correct => don't complain about inconsistent indentation on subsequent lines which use
// either tabs or spaces
myLastSpaces = 0;
@@ -102,10 +103,12 @@ public class PyInconsistentIndentationInspection extends PyInspection {
}
else {
if (spaces > 0 && myLastTabs > 0) {
reportProblem("Inconsistent indentation: previous line used tabs, this line uses spaces", problemStart, length);
reportProblem(PyPsiBundle.message("INSP.inconsistent.indentation.previous.line.used.tabs.this.line.uses.spaces"),
problemStart, length);
}
else if (tabs > 0 && myLastSpaces > 0) {
reportProblem("Inconsistent indentation: previous line used spaces, this line uses tabs", problemStart, length);
reportProblem(PyPsiBundle.message("INSP.inconsistent.indentation.previous.line.used.spaces.this.line.uses.tabs"),
problemStart, length);
}
if (spaces > 0 || tabs > 0) {
myLastTabs = tabs;
@@ -114,7 +117,7 @@ public class PyInconsistentIndentationInspection extends PyInspection {
}
}
private void reportProblem(final String descriptionTemplate, final int problemStart, final int problemLength) {
private void reportProblem(@InspectionMessage String descriptionTemplate, final int problemStart, final int problemLength) {
PsiElement elt = myFile.findElementAt(problemStart);
int startOffset = problemStart - elt.getTextRange().getStartOffset();
int endOffset = startOffset + problemLength;
@@ -19,6 +19,7 @@ import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.inspections.quickfix.ListCreationQuickFix;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
@@ -57,7 +58,7 @@ public class PyListCreationInspection extends PyInspection {
ListCreationQuickFix quickFix = null;
final String message = "This list creation could be rewritten as a list literal";
final String message = PyPsiBundle.message("INSP.list.creation.this.list.creation.could.be.rewritten.as.list.literal");
while (expressionStatement instanceof PyExpressionStatement) {
final PyExpression statement = ((PyExpressionStatement)expressionStatement).getExpression();
if (!(statement instanceof PyCallExpression)) break;
@@ -17,6 +17,7 @@ package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyPsiBundle;
@@ -72,7 +73,7 @@ public class PyMandatoryEncodingInspection extends PyInspection {
}
}
public String myDefaultEncoding = "utf-8";
public @NlsSafe String myDefaultEncoding = "utf-8";
public int myEncodingFormatIndex = 0;
public boolean myAllPythons = false;
@@ -121,7 +122,7 @@ public class PyMandatoryEncodingInspection extends PyInspection {
private JPanel onlyPython2Box() {
final JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JCheckBox checkBox =
PythonUiService.getInstance().createInspectionCheckBox(PyPsiBundle.message("enable.in.python.3"), this, "myAllPythons");
PythonUiService.getInstance().createInspectionCheckBox(PyPsiBundle.message("INSP.mandatory.encoding.checkbox.enable.in.python.3"), this, "myAllPythons");
if (checkBox != null) {
panel.add(checkBox);
}
@@ -131,7 +132,7 @@ public class PyMandatoryEncodingInspection extends PyInspection {
@NotNull
private static JPanel defaultEncodingLabel() {
final JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
panel.add(new JLabel(PyPsiBundle.message("INSP.mandatory.encoding.select.default.encoding")));
panel.add(new JLabel(PyPsiBundle.message("INSP.mandatory.encoding.label.select.default.encoding")));
return panel;
}
@@ -154,7 +155,7 @@ public class PyMandatoryEncodingInspection extends PyInspection {
@NotNull
private static JPanel encodingFormatLabel() {
final JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
panel.add(new JLabel(PyPsiBundle.message("INSP.mandatory.encoding.encoding.comment.format")));
panel.add(new JLabel(PyPsiBundle.message("INSP.mandatory.encoding.label.encoding.comment.format")));
return panel;
}
@@ -43,7 +43,7 @@ public class PyMissingTypeHintsInspection extends PyInspection {
ASTNode nameNode = function.getNameNode();
if (nameNode != null) {
registerProblem(nameNode.getPsi(),
"Type hinting is missing for function definition",
PyPsiBundle.message("INSP.missing.type.hints.type.hinting.missing.for.function.definition"),
new AddTypeHintsQuickFix(function.getName()));
}
}
@@ -92,7 +92,7 @@ public class PyMissingTypeHintsInspection extends PyInspection {
@Override
public JComponent createOptionsPanel() {
return PythonUiService.getInstance().createSingleCheckboxOptionsPanel(
PyPsiBundle.message("INSP.missing.type.hints.only.when.types.are.known.collected.from.run.time.or.inferred"),
PyPsiBundle.message("INSP.missing.type.hints.checkbox.only.when.types.are.known"),
this, "m_onlyWhenTypesAreKnown");
}
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.PythonUiService;
import com.jetbrains.python.inspections.quickfix.AddEncodingQuickFix;
@@ -79,7 +80,7 @@ public class PyNonAsciiCharInspection extends PyInspection {
if (hasNonAscii) {
if (charsetString == null) {
registerProblem(node, "Non-ASCII character " + c + " in file, but no encoding declared",
registerProblem(node, PyPsiBundle.message("INSP.non.ascii.char.non.ascii.character.in.file.but.no.encoding.declared", c),
new AddEncodingQuickFix(myDefaultEncoding, myEncodingFormatIndex));
}
}
@@ -6,6 +6,7 @@ import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.PsiElementVisitor
import com.intellij.util.Processor
import com.intellij.util.containers.SortedList
import com.jetbrains.python.PyPsiBundle
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner
import com.jetbrains.python.psi.PyClass
import com.jetbrains.python.psi.PyFile
@@ -59,33 +60,38 @@ class PyOverloadsInspection : PyInspection() {
functions
.maxBy { it.textOffset }
?.let {
registerProblem(it.nameIdentifier,
"A series of @overload-decorated ${chooseBetweenFunctionsAndMethods(owner)} " +
"should always be followed by an implementation that is not @overload-ed")
registerProblem(it.nameIdentifier, if (owner is PyClass) {
PyPsiBundle.message("INSP.overloads.series.overload.decorated.methods.should.always.be.followed.by.implementation")
}
else {
PyPsiBundle.message("INSP.overloads.series.overload.decorated.functions.should.always.be.followed.by.implementation")
})
}
}
else {
if (implementation != functions.last()) {
registerProblem(functions.last().nameIdentifier,
"A series of @overload-decorated ${chooseBetweenFunctionsAndMethods(owner)} " +
"should always be followed by an implementation that is not @overload-ed")
registerProblem(functions.last().nameIdentifier, if (owner is PyClass) {
PyPsiBundle.message("INSP.overloads.series.overload.decorated.methods.should.always.be.followed.by.implementation")
}
else {
PyPsiBundle.message("INSP.overloads.series.overload.decorated.functions.should.always.be.followed.by.implementation")
})
}
functions
.asSequence()
.filter { isIncompatibleOverload(implementation, it) }
.forEach {
registerProblem(it.nameIdentifier,
"Signature of this @overload-decorated ${chooseBetweenFunctionAndMethod(owner)} " +
"is not compatible with the implementation")
registerProblem(it.nameIdentifier, if (owner is PyClass) {
PyPsiBundle.message("INSP.overloads.this.method.overload.signature.not.compatible.with.implementation")
}
else {
PyPsiBundle.message("INSP.overloads.this.function.overload.signature.not.compatible.with.implementation")
})
}
}
}
private fun chooseBetweenFunctionsAndMethods(owner: ScopeOwner) = if (owner is PyClass) "methods" else "functions"
private fun chooseBetweenFunctionAndMethod(owner: ScopeOwner) = if (owner is PyClass) "method" else "function"
private fun isIncompatibleOverload(implementation: PyFunction, overload: PyFunction): Boolean {
return implementation != overload &&
PyiUtil.isOverload(overload, myTypeEvalContext) &&
@@ -1,7 +1,6 @@
// 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.inspections;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.codeInspection.LocalInspectionToolSession;
@@ -9,6 +8,7 @@ import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.ex.InspectionProfileModifiableModelKt;
import com.intellij.codeInspection.util.InspectionMessage;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
@@ -27,7 +27,6 @@ import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
import com.jetbrains.python.psi.types.PyClassLikeType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,6 +36,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import java.util.regex.Pattern;
/**
@@ -49,16 +49,16 @@ public class PyPep8NamingInspection extends PyInspection {
private static final Pattern UPPERCASE_REGEX = Pattern.compile("[_\\p{javaUpperCase}][_\\p{javaUpperCase}0-9]*");
private static final Pattern MIXEDCASE_REGEX = Pattern.compile("_?_?[\\p{javaUpperCase}][\\p{javaLowerCase}\\p{javaUpperCase}0-9]*");
// See error codes of the tool "pep8-naming"
private static final Map<String, String> ERROR_CODES_DESCRIPTION = ImmutableMap.<String, String>builder()
.put("N801", "Class names should use CamelCase convention")
.put("N802", "Function name should be lowercase")
.put("N803", "Argument name should be lowercase")
.put("N806", "Variable in function should be lowercase")
.put("N811", "Constant variable imported as non constant")
.put("N812", "Lowercase variable imported as non lowercase")
.put("N813", "CamelCase variable imported as lowercase")
.put("N814", "CamelCase variable imported as constant")
.build();
private static final Map<String, Supplier<@InspectionMessage String>> ERROR_CODES_DESCRIPTION = Map.of(
"N801", PyPsiBundle.messagePointer("INSP.pep8.naming.class.names.should.use.camelcase.convention"),
"N802", PyPsiBundle.messagePointer("INSP.pep8.naming.function.name.should.be.lowercase"),
"N803", PyPsiBundle.messagePointer("INSP.pep8.naming.argument.name.should.be.lowercase"),
"N806", PyPsiBundle.messagePointer("INSP.pep8.naming.variable.in.function.should.be.lowercase"),
"N811", PyPsiBundle.messagePointer("INSP.pep8.naming.constant.variable.imported.as.non.constant"),
"N812", PyPsiBundle.messagePointer("INSP.pep8.naming.lowercase.variable.imported.as.non.lowercase"),
"N813", PyPsiBundle.messagePointer("INSP.pep8.naming.camelcase.variable.imported.as.lowercase"),
"N814", PyPsiBundle.messagePointer("INSP.pep8.naming.camelcase.variable.imported.as.constant")
);
public final List<String> ignoredErrors = new ArrayList<>();
public boolean ignoreOverriddenFunctions = true;
public final List<String> ignoredBaseClasses = Lists.newArrayList("unittest.TestCase", "unittest.case.TestCase");
@@ -67,17 +67,17 @@ public class PyPep8NamingInspection extends PyInspection {
@Override
public JComponent createOptionsPanel() {
final JPanel rootPanel = new JPanel(new BorderLayout());
JCheckBox checkBox = PythonUiService.getInstance()
.createInspectionCheckBox(PyPsiBundle.message("ignore.overridden.functions"), this, "ignoreOverriddenFunctions");
PythonUiService uiService = PythonUiService.getInstance();
JCheckBox checkBox = uiService.createInspectionCheckBox(PyPsiBundle.message("ignore.overridden.functions"), this, "ignoreOverriddenFunctions");
if (checkBox != null) {
rootPanel.add(checkBox, BorderLayout.NORTH);
}
JComponent classes = PythonUiService.getInstance().createListEditForm(PyPsiBundle.message("INSP.pep8.naming.excluded.base.classes"), ignoredBaseClasses);
JComponent errors = PythonUiService.getInstance().createListEditForm(PyPsiBundle.message("INSP.pep8.naming.ignored.errors"), ignoredErrors);
JComponent classes = uiService.createListEditForm(PyPsiBundle.message("INSP.pep8.naming.column.name.excluded.base.classes"), ignoredBaseClasses);
JComponent errors = uiService.createListEditForm(PyPsiBundle.message("INSP.pep8.naming.column.name.ignored.errors"), ignoredErrors);
if (classes != null && errors != null) {
JComponent splitter = PythonUiService.getInstance().onePixelSplitter(false, classes, errors);
JComponent splitter = uiService.onePixelSplitter(false, classes, errors);
if (splitter != null) {
rootPanel.add(splitter, BorderLayout.CENTER);
@@ -161,17 +161,15 @@ public class PyPep8NamingInspection extends PyInspection {
protected static class IgnoreErrorFix implements LocalQuickFix {
private final String myCode;
private static final String myText = "Ignore errors like this";
IgnoreErrorFix(String code) {
myCode = code;
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return myText;
return PyPsiBundle.message("QFIX.NAME.ignore.errors.like.this");
}
@Override
@@ -233,10 +231,10 @@ public class PyPep8NamingInspection extends PyInspection {
protected void registerAndAddRenameAndIgnoreErrorQuickFixes(@Nullable final PsiElement node, @NotNull final String errorCode) {
if (getHolder() != null && getHolder().isOnTheFly()) {
registerProblem(node, ERROR_CODES_DESCRIPTION.get(errorCode), createRenameAndIngoreErrorQuickFixes(node, errorCode));
registerProblem(node, ERROR_CODES_DESCRIPTION.get(errorCode).get(), createRenameAndIngoreErrorQuickFixes(node, errorCode));
}
else {
registerProblem(node, ERROR_CODES_DESCRIPTION.get(errorCode), new IgnoreErrorFix(errorCode));
registerProblem(node, ERROR_CODES_DESCRIPTION.get(errorCode).get(), new IgnoreErrorFix(errorCode));
}
}
@@ -257,7 +255,7 @@ public class PyPep8NamingInspection extends PyInspection {
final String errorCode = "N802";
if (!ignoredErrors.contains(errorCode)) {
quickFixes.add(new IgnoreErrorFix(errorCode));
registerProblem(nameNode.getPsi(), ERROR_CODES_DESCRIPTION.get(errorCode),
registerProblem(nameNode.getPsi(), ERROR_CODES_DESCRIPTION.get(errorCode).get(),
quickFixes.toArray(LocalQuickFix.EMPTY_ARRAY));
}
}
@@ -6,6 +6,7 @@ import com.intellij.codeInsight.controlflow.ControlFlowUtil;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.util.InspectionMessage;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
@@ -20,42 +21,17 @@ import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
import com.jetbrains.python.inspections.quickfix.PyUpdatePropertySignatureQuickFix;
import com.jetbrains.python.inspections.quickfix.RenameParameterQuickFix;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyArgumentList;
import com.jetbrains.python.psi.PyCallExpression;
import com.jetbrains.python.psi.PyCallable;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyDecorator;
import com.jetbrains.python.psi.PyDecoratorList;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyKnownDecoratorUtil;
import com.jetbrains.python.psi.PyLambdaExpression;
import com.jetbrains.python.psi.PyNoneLiteralExpression;
import com.jetbrains.python.psi.PyParameter;
import com.jetbrains.python.psi.PyParameterList;
import com.jetbrains.python.psi.PyRaiseStatement;
import com.jetbrains.python.psi.PyReferenceExpression;
import com.jetbrains.python.psi.PyReturnStatement;
import com.jetbrains.python.psi.PySubscriptionExpression;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.PyTypedElement;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.PyYieldExpression;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.types.PyCallableParameter;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyNoneType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.PyTypeChecker;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Checks that arguments to property() and @property and friends are ok.
@@ -302,7 +278,7 @@ public class PyPropertyDefinitionInspection extends PyInspection {
private void checkReturnValueAllowed(@NotNull PyCallable callable,
@NotNull PsiElement beingChecked,
boolean allowed,
@NotNull String message) {
@NotNull @InspectionMessage String message) {
if (callable instanceof PyFunction) {
final PyFunction function = (PyFunction)callable;
@@ -6,6 +6,7 @@ import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.codeInspection.util.InspectionMessage;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.psi.*;
@@ -161,9 +162,10 @@ public class PyProtectedMemberInspection extends PyInspection {
}
}
final PyType type = myTypeEvalContext.getType(qualifier);
final String bundleKey = type instanceof PyModuleType ? "INSP.protected.member.$0.access.module" : "INSP.protected.member.$0.access";
registerProblem(node, PyPsiBundle.message(bundleKey, name), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, null, quickFixes.toArray(
LocalQuickFix.EMPTY_ARRAY));
final @InspectionMessage String message = type instanceof PyModuleType
? PyPsiBundle.message("INSP.protected.member.access.to.protected.member.of.module", name)
: PyPsiBundle.message("INSP.protected.member.access.to.protected.member.of.class", name);
registerProblem(node, message, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, null, quickFixes.toArray(LocalQuickFix.EMPTY_ARRAY));
}
}
@@ -200,7 +202,7 @@ public class PyProtectedMemberInspection extends PyInspection {
)
.forEach(
referenceExpression -> {
final String message = "'" + referenceExpression.getName() + "' is not declared in __all__";
final String message = PyPsiBundle.message("INSP.protected.member.name.not.declared.in.all", referenceExpression.getName());
registerProblem(referenceExpression, message, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
);
@@ -8,6 +8,7 @@ import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.util.containers.isNullOrEmpty
import com.jetbrains.python.PyNames
import com.jetbrains.python.PyPsiBundle
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider
import com.jetbrains.python.codeInsight.typing.inspectProtocolSubclass
import com.jetbrains.python.codeInsight.typing.isProtocol
@@ -78,7 +79,7 @@ class PyProtocolInspection : PyInspection() {
}
if (!superClassTypes.all(correctBase)) {
registerProblem(type.pyClass.nameIdentifier, "All bases of a protocol must be protocols")
registerProblem(type.pyClass.nameIdentifier, PyPsiBundle.message("INSP.protocol.all.bases.protocol.must.be.protocols"))
}
}
@@ -89,7 +90,9 @@ class PyProtocolInspection : PyInspection() {
if (base is PyReferenceExpression) {
val qNames = PyResolveUtil.resolveImportedElementQNameLocally(base).asSequence().map { it.toString() }
if (qNames.any { it == PyTypingTypeProvider.PROTOCOL || it == PyTypingTypeProvider.PROTOCOL_EXT }) {
registerProblem(base, "Only @runtime_checkable protocols can be used with instance and class checks", GENERIC_ERROR)
registerProblem(base,
PyPsiBundle.message("INSP.protocol.only.runtime.checkable.protocols.can.be.used.with.instance.class.checks"),
GENERIC_ERROR)
return
}
}
@@ -102,7 +105,9 @@ class PyProtocolInspection : PyInspection() {
it == TYPING_RUNTIME_CHECKABLE || it == TYPING_RUNTIME_CHECKABLE_EXT || it == TYPING_RUNTIME || it == TYPING_RUNTIME_EXT
}
) {
registerProblem(base, "Only @runtime_checkable protocols can be used with instance and class checks", GENERIC_ERROR)
registerProblem(base,
PyPsiBundle.message("INSP.protocol.only.runtime.checkable.protocols.can.be.used.with.instance.class.checks"),
GENERIC_ERROR)
}
}
}
@@ -118,7 +123,7 @@ class PyProtocolInspection : PyInspection() {
if (base != null) {
val type = myTypeEvalContext.getType(base)
if (type is PyClassLikeType && isProtocol(type, myTypeEvalContext)) {
registerProblem(base, "NewType cannot be used with protocol classes")
registerProblem(base, PyPsiBundle.message("INSP.protocol.newtype.cannot.be.used.with.protocol.classes"))
}
}
}
@@ -138,7 +143,7 @@ class PyProtocolInspection : PyInspection() {
.filterNot { PyTypeChecker.match(expectedMemberType, myTypeEvalContext.getType(it), myTypeEvalContext) }
.forEach {
val place = if (it is PsiNameIdentifierOwner) it.nameIdentifier else it
registerProblem(place, "Type of '${it.name}' is incompatible with '${protocol.name}'")
registerProblem(place, PyPsiBundle.message("INSP.protocol.element.type.incompatible.with.protocol", it.name, protocol.name))
}
}
}
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.InspectionProfileModifiableModelKt;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiNameIdentifierOwner;
@@ -61,7 +62,7 @@ public class PyShadowingBuiltinsInspection extends PyInspection {
@Override
public JComponent createOptionsPanel() {
return PythonUiService.getInstance().createListEditForm("Ignore built-ins", ignoredNames);
return PythonUiService.getInstance().createListEditForm(PyPsiBundle.message("INSP.shadowing.builtins.column.name.ignore.built.ins"), ignoredNames);
}
@NotNull
@@ -73,7 +74,7 @@ public class PyShadowingBuiltinsInspection extends PyInspection {
}
private static final class PyIgnoreBuiltinQuickFix implements LocalQuickFix, LowPriorityAction {
@NotNull private final String myName;
@NotNull private final @NlsSafe String myName;
private PyIgnoreBuiltinQuickFix(@NotNull String name) {
myName = name;
@@ -82,7 +83,7 @@ public class PyShadowingBuiltinsInspection extends PyInspection {
@NotNull
@Override
public String getName() {
return getFamilyName() + " \"" + myName + "\"";
return PyPsiBundle.message("QFIX.NAME.ignore.shadowed.built.in.name", myName);
}
@Override
@@ -93,7 +94,7 @@ public class PyShadowingBuiltinsInspection extends PyInspection {
@NotNull
@Override
public String getFamilyName() {
return PyPsiBundle.message("INSP.shadowing.builtins.ignore.shadowed.built.in.name");
return PyPsiBundle.message("QFIX.FAMILY.NAME.ignore.shadowed.built.in.name");
}
@Override
@@ -155,7 +156,7 @@ public class PyShadowingBuiltinsInspection extends PyInspection {
if (builtin != null && !PyUtil.inSameFile(builtin, element)) {
final PsiElement identifier = element.getNameIdentifier();
final PsiElement problemElement = identifier != null ? identifier : element;
registerProblem(problemElement, String.format("Shadows built-in name '%s'", name),
registerProblem(problemElement, PyPsiBundle.message("INSP.shadowing.builtins.shadows.built.in.name", name),
ProblemHighlightType.WEAK_WARNING, null, createQuickFixes(name, problemElement));
}
}
@@ -76,10 +76,11 @@ public class PyStatementEffectInspection extends PyInspection {
}
}
if (expression instanceof PyReferenceExpression && !((PyReferenceExpression)expression).isQualified()) {
registerProblem(expression, PyPsiBundle.message("INSP.NAME.statement.message"));
registerProblem(expression, PyPsiBundle.message("INSP.statement.effect.statement.seems.to.have.no.effect"));
}
else {
registerProblem(expression, PyPsiBundle.message("INSP.NAME.statement.message"), new StatementEffectIntroduceVariableQuickFix());
registerProblem(expression, PyPsiBundle.message("INSP.statement.effect.statement.seems.to.have.no.effect"),
new StatementEffectIntroduceVariableQuickFix());
}
}
@@ -138,7 +139,9 @@ public class PyStatementEffectInspection extends PyInspection {
ResolveResult[] results = referenceExpression.getReference(getResolveContext()).multiResolve(true);
for (ResolveResult res : results) {
if (res.getElement() instanceof PyFunction) {
registerProblem(expression, "Statement seems to have no effect and can be replaced with function call to have effect", new StatementEffectFunctionCallQuickFix());
registerProblem(expression,
PyPsiBundle.message("INSP.statement.effect.statement.having.no.effect.can.be.replaced.with.function.call"),
new StatementEffectFunctionCallQuickFix());
return true;
}
}
@@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableMap;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.util.InspectionMessage;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
@@ -298,7 +299,7 @@ public class PyStringFormatInspection extends PyInspection {
if (!myUsedMappingKeys.get(key).booleanValue()) {
unresolved++;
if (unresolved > referenceKeyNumber) {
registerProblem(problemTarget, PyPsiBundle.message("INSP.key.$0.has.no.arg", key));
registerProblem(problemTarget, PyPsiBundle.message("INSP.str.format.key.has.no.argument", key));
break;
}
}
@@ -316,12 +317,14 @@ public class PyStringFormatInspection extends PyInspection {
}
}
private void registerProblem(@NotNull PsiElement problemTarget, @NotNull final String message, @NotNull LocalQuickFix quickFix) {
private void registerProblem(@NotNull PsiElement problemTarget,
@NotNull @InspectionMessage String message,
@NotNull LocalQuickFix quickFix) {
myProblemRegister = true;
myVisitor.registerProblem(problemTarget, message, quickFix);
}
private void registerProblem(@NotNull PsiElement problemTarget, @NotNull final String message) {
private void registerProblem(@NotNull PsiElement problemTarget, @NotNull @InspectionMessage String message) {
myProblemRegister = true;
myVisitor.registerProblem(problemTarget, message);
}
@@ -343,7 +346,7 @@ public class PyStringFormatInspection extends PyInspection {
return;
}
if (actual != null && !PyTypeChecker.match(expected, actual, myTypeEvalContext)) {
registerProblem(problemTarget, PyPsiBundle.message("INSP.unexpected.type.$0", actual.getName()));
registerProblem(problemTarget, PyPsiBundle.message("INSP.str.format.unexpected.argument.type", actual.getName()));
}
}
@@ -381,7 +384,7 @@ public class PyStringFormatInspection extends PyInspection {
if (conversionType == 'b') {
final LanguageLevel languageLevel = LanguageLevel.forElement(formatExpression);
if (languageLevel.isOlderThan(LanguageLevel.PYTHON35) || !isBytesLiteral(formatExpression, myTypeEvalContext)) {
registerProblem(formatExpression, "Unsupported format character 'b'");
registerProblem(formatExpression, PyPsiBundle.message("INSP.str.format.unsupported.format.character.b"));
return;
}
}
@@ -408,7 +411,7 @@ public class PyStringFormatInspection extends PyInspection {
if ("*".equals(width)) {
++myExpectedArguments;
if (myUsedMappingKeys.size() > 0) {
registerProblem(formatExpression, "Can't use '*' in formats when using a mapping");
registerProblem(formatExpression, PyPsiBundle.message("INSP.str.format.can.not.use.star.in.formats.when.using.mapping"));
}
}
}
@@ -559,7 +562,7 @@ public class PyStringFormatInspection extends PyInspection {
if (chunkMapping != null) {
registerProblem(myFormatExpression, hasElementIndex ?
PyPsiBundle.message("INSP.too.few.args.for.fmt.string") :
PyPsiBundle.message("INSP.key.$0.has.no.arg", chunkMapping));
PyPsiBundle.message("INSP.str.format.key.has.no.argument", chunkMapping));
}
else {
registerProblem(myFormatExpression, PyPsiBundle.message("INSP.too.few.args.for.fmt.string"));
@@ -570,7 +573,7 @@ public class PyStringFormatInspection extends PyInspection {
}
}
private void registerProblem(@NotNull PsiElement problemTarget, @NotNull final String message) {
private void registerProblem(@NotNull PsiElement problemTarget, @NotNull @InspectionMessage String message) {
myProblemRegister = true;
myVisitor.registerProblem(problemTarget, message);
}
@@ -585,7 +588,7 @@ public class PyStringFormatInspection extends PyInspection {
if (expected != null && actual != null
&& CHECKED_TYPES.contains(actual.getName())
&& !PyTypeChecker.match(expected, actual, myTypeEvalContext)) {
registerProblem(typedElement, PyPsiBundle.message("INSP.unexpected.type.$0", actual.getName()));
registerProblem(typedElement, PyPsiBundle.message("INSP.str.format.unexpected.argument.type", actual.getName()));
}
}
}
@@ -19,6 +19,7 @@ import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.util.ArrayUtil;
import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.types.PyNoneType;
@@ -59,7 +60,8 @@ public class PyTupleAssignmentBalanceInspection extends PyInspection {
final int starExpressions = countStarExpressions(targets);
if (starExpressions > 1) {
registerProblem(lhsExpression, "Only one starred expression allowed in assignment");
registerProblem(lhsExpression,
PyPsiBundle.message("INSP.tuple.assignment.balance.only.one.starred.expression.allowed.in.assignment"));
return;
}
@@ -67,10 +69,10 @@ public class PyTupleAssignmentBalanceInspection extends PyInspection {
if (valuesLength == -1) return;
if (targetsLength > valuesLength + starExpressions) {
registerProblem(assignedValue, "Need more values to unpack");
registerProblem(assignedValue, PyPsiBundle.message("INSP.tuple.assignment.balance.need.more.values.to.unpack"));
}
else if (starExpressions == 0 && targetsLength < valuesLength) {
registerProblem(assignedValue, "Too many values to unpack");
registerProblem(assignedValue, PyPsiBundle.message("INSP.tuple.assignment.balance.too.many.values.to.unpack"));
}
}
@@ -153,7 +153,7 @@ public final class PythonUiServiceImpl extends PythonUiService {
}
@Override
public JComponent createSingleCheckboxOptionsPanel(String label, InspectionProfileEntry inspection, String property) {
public JComponent createSingleCheckboxOptionsPanel(@NlsContexts.Checkbox String label, InspectionProfileEntry inspection, String property) {
return new SingleCheckboxOptionsPanel(label, inspection, property);
}
@@ -228,7 +228,7 @@ public final class PythonUiServiceImpl extends PythonUiService {
}
@Override
public JCheckBox createInspectionCheckBox(String message, InspectionProfileEntry inspection, String property) {
public JCheckBox createInspectionCheckBox(@NlsContexts.Checkbox String message, InspectionProfileEntry inspection, String property) {
return new CheckBox(message, inspection, property);
}
@@ -243,7 +243,7 @@ public final class PythonUiServiceImpl extends PythonUiService {
}
@Override
public JComponent createListEditForm(String title, List<String> stringList) {
public JComponent createListEditForm(@NlsContexts.ColumnName String title, List<String> stringList) {
final ListEditForm form = new ListEditForm(title, stringList);
return form.getContentPanel();
}
@@ -5,6 +5,7 @@ import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.util.InspectionMessage;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtilCore;
@@ -19,6 +20,7 @@ import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
@@ -75,7 +77,6 @@ public final class PyInterpreterInspection extends PyInspection {
final boolean pyCharm = PythonIdeLanguageCustomization.isMainlyPythonIde();
final String interpreterOwner = pyCharm ? "project" : "module";
final List<LocalQuickFix> fixes = new ArrayList<>();
// TODO: Introduce an inspection extension
if (UsePipEnvQuickFix.Companion.isApplicable(module)) {
@@ -94,33 +95,62 @@ public final class PyInterpreterInspection extends PyInspection {
fixes.add(new InterpreterSettingsQuickFix(module));
}
final String product = pyCharm ? "PyCharm" : "Python plugin";
if (sdk == null) {
registerProblem(node, PyPsiBundle.message("python.sdk.no.interpreter.configured.owner", interpreterOwner), fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
final @InspectionMessage String message;
if (pyCharm) {
message = PyPsiBundle.message("INSP.interpreter.no.python.interpreter.configured.for.project");
}
else {
message = PyPsiBundle.message("INSP.interpreter.no.python.interpreter.configured.for.module");
}
registerProblem(node, message, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
}
else {
// TODO: Introduce an inspection extension
final String associatedModulePath = PySdkExtKt.getAssociatedModulePath(sdk);
final @NlsSafe String associatedModulePath = PySdkExtKt.getAssociatedModulePath(sdk);
if (PipenvKt.isPipEnv(sdk) && (associatedModulePath == null || PySdkExtKt.isAssociatedWithAnotherModule(sdk, module))) {
final String message = associatedModulePath != null ?
"Pipenv interpreter is associated with another " + interpreterOwner + ": '" + associatedModulePath + "'" :
"Pipenv interpreter is not associated with any " + interpreterOwner;
final @InspectionMessage String message;
if (associatedModulePath != null) {
if (pyCharm) {
message = PyPsiBundle.message("INSP.interpreter.pipenv.interpreter.associated.with.another.project", associatedModulePath);
}
else {
message = PyPsiBundle.message("INSP.interpreter.pipenv.interpreter.associated.with.another.module", associatedModulePath);
}
}
else {
if (pyCharm) {
message = PyPsiBundle.message("INSP.interpreter.pipenv.interpreter.not.associated.with.any.project");
}
else {
message = PyPsiBundle.message("INSP.interpreter.pipenv.interpreter.not.associated.with.any.module");
}
}
registerProblem(node, message, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
}
else if (PythonSdkUtil.isInvalid(sdk)) {
registerProblem(node,
"Invalid Python interpreter selected for the " + interpreterOwner,
fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
final @InspectionMessage String message;
if (pyCharm) {
message = PyPsiBundle.message("INSP.interpreter.invalid.python.interpreter.selected.for.project");
}
else {
message = PyPsiBundle.message("INSP.interpreter.invalid.python.interpreter.selected.for.module");
}
registerProblem(node, message, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
}
else {
final LanguageLevel languageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);
if (!LanguageLevel.SUPPORTED_LEVELS.contains(languageLevel)) {
registerProblem(
node,
"Python " + languageLevel + " has reached its end-of-life date and it is no longer supported in " + product + ".",
fixes.toArray(LocalQuickFix.EMPTY_ARRAY)
);
final @InspectionMessage String message;
if (pyCharm) {
message = PyPsiBundle.message("INSP.interpreter.python.has.reached.its.end.of.life.and.is.no.longer.supported.in.pycharm",
languageLevel);
}
else {
message = PyPsiBundle.message("INSP.interpreter.python.has.reached.its.end.life.and.is.no.longer.supported.in.python.plugin",
languageLevel);
}
registerProblem(node, message, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
}
}
}
@@ -6,6 +6,8 @@ import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.EditInspectionToolsSettingsAction;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.codeInspection.ui.ListEditForm;
import com.intellij.codeInspection.util.InspectionMessage;
import com.intellij.codeInspection.util.IntentionFamilyName;
import com.intellij.core.CoreBundle;
import com.intellij.execution.ExecutionException;
import com.intellij.idea.ActionsBundle;
@@ -18,6 +20,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -60,7 +63,7 @@ public class PyPackageRequirementsInspection extends PyInspection {
@Override
public JComponent createOptionsPanel() {
final ListEditForm form = new ListEditForm("Ignore packages", ignoredPackages);
final ListEditForm form = new ListEditForm(PyPsiBundle.message("INSP.requirements.column.name.ignore.packages"), ignoredPackages);
return form.getContentPanel();
}
@@ -122,11 +125,9 @@ public class PyPackageRequirementsInspection extends PyInspection {
if (sdk != null) {
final List<PyRequirement> unsatisfied = findUnsatisfiedRequirements(module, sdk, myIgnoredPackages);
if (unsatisfied != null && !unsatisfied.isEmpty()) {
final boolean plural = unsatisfied.size() > 1;
String msg = String.format("Package requirement%s %s %s not satisfied",
plural ? "s" : "",
PyPackageUtil.requirementsToString(unsatisfied),
plural ? "are" : "is");
@NlsSafe String requirementsList = PyPackageUtil.requirementsToString(unsatisfied);
@InspectionMessage String msg = PyPsiBundle.message("INSP.requirements.package.requirements.not.satisfied",
requirementsList, unsatisfied.size());
final List<LocalQuickFix> quickFixes = new ArrayList<>();
// TODO: Introduce an inspection extension
if (PipenvKt.isPipEnv(sdk)) {
@@ -235,7 +236,7 @@ public class PyPackageRequirementsInspection extends PyInspection {
new IgnoreRequirementFix(Collections.singleton(packageName))};
registerProblem(packageReferenceExpression,
String.format("Package containing module '%s' is not listed in project requirements", packageName),
PyPsiBundle.message("INSP.requirements.package.containing.module.not.listed.in.project.requirements", packageName),
ProblemHighlightType.WEAK_WARNING,
null,
fixes);
@@ -372,27 +373,26 @@ public class PyPackageRequirementsInspection extends PyInspection {
}
public static class PyInstallRequirementsFix implements LocalQuickFix {
@NotNull private final String myName;
@NotNull private final @IntentionFamilyName String myName;
@NotNull private final Module myModule;
@NotNull private final Sdk mySdk;
@NotNull private final List<PyRequirement> myUnsatisfied;
@NotNull private final List<String> myExtraArgs;
@Nullable private final PyPackageManagerUI.Listener myListener;
public PyInstallRequirementsFix(@Nullable @Nls(capitalization = Nls.Capitalization.Sentence) String name,
public PyInstallRequirementsFix(@Nullable @IntentionFamilyName String name,
@NotNull Module module, @NotNull Sdk sdk,
@NotNull List<PyRequirement> unsatisfied) {
this(name, module, sdk, unsatisfied, Collections.emptyList(), null);
}
public PyInstallRequirementsFix(@Nullable @Nls(capitalization = Nls.Capitalization.Sentence) String name,
public PyInstallRequirementsFix(@Nullable @IntentionFamilyName String name,
@NotNull Module module,
@NotNull Sdk sdk,
@NotNull List<PyRequirement> unsatisfied,
@NotNull List<String> extraArgs,
@Nullable PyPackageManagerUI.Listener listener) {
final boolean plural = unsatisfied.size() > 1;
myName = name != null ? name : String.format("Install requirement%s", plural ? "s" : "");
myName = name != null ? name : PyPsiBundle.message("QFIX.NAME.install.requirements", unsatisfied.size());
myModule = module;
mySdk = sdk;
myUnsatisfied = unsatisfied;
@@ -604,8 +604,7 @@ public class PyPackageRequirementsInspection extends PyInspection {
@NotNull
@Override
public String getFamilyName() {
final boolean plural = myPackageNames.size() > 1;
return String.format("Ignore requirement%s", plural ? "s" : "");
return PyPsiBundle.message("QFIX.NAME.ignore.requirements", myPackageNames.size());
}
@Override
@@ -1,5 +1,5 @@
<weak_warning descr="Missing docstring"></weak_warning><warning descr="No encoding specified for file"></warning>def <weak_warning descr="Missing docstring">f</weak_warning>(x):
<warning descr="Non-ASCII character М in file, but no encoding declared"># type: (b'Моноцикл') -> None</warning>
<warning descr="Non-ASCII character 'М' in file, but no encoding declared"># type: (b'Моноцикл') -> None</warning>
pass
@@ -1,4 +1,4 @@
g = 2
i = 2
<warning descr="Non-ASCII character ɡ in file, but no encoding declared">ɡ</warning> = 1
<warning descr="Non-ASCII character 'ɡ' in file, but no encoding declared">ɡ</warning> = 1
a = g + i