mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 04:51:24 +07:00
[python] extract python parser to a separate module
Merge-request: IJ-MR-116296 Merged-by: Vladimir Koshelev <Vladimir.Koshelev@jetbrains.com> GitOrigin-RevId: e7559fb3215d757e6273543e4aa27d52df755e63
This commit is contained in:
committed by
intellij-monorepo-bot
parent
609391377b
commit
29f0eb6c77
@@ -13,5 +13,6 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.util.ui" />
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.analysis" />
|
||||
<orderEntry type="module" module-name="intellij.python.parser" exported="" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -49,13 +49,6 @@
|
||||
dynamic="true"/>
|
||||
</extensionPoints>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<fileType name="Python"
|
||||
language="Python"
|
||||
extensions="py;pyw"
|
||||
hashBangs="python"
|
||||
implementationClass="com.jetbrains.python.PythonFileType"
|
||||
fieldName="INSTANCE"/>
|
||||
<iconMapper mappingFile="PythonPsiApiIconMappings.json"/>
|
||||
<projectService serviceInterface="com.jetbrains.python.psi.types.TypeEvalContextCache"
|
||||
serviceImplementation="com.jetbrains.python.psi.types.TypeEvalContextCacheImpl"/>
|
||||
</extensions>
|
||||
|
||||
@@ -1,679 +0,0 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@NonNls
|
||||
public final class PyNames {
|
||||
public static final String SITE_PACKAGES = "site-packages";
|
||||
public static final String DIST_PACKAGES = "dist-packages";
|
||||
/**
|
||||
* int type
|
||||
*/
|
||||
public static final String TYPE_INT = "int";
|
||||
public static final String TYPE_LONG = "long";
|
||||
/**
|
||||
* unicode string type (see {@link #TYPE_STRING_TYPES}
|
||||
*/
|
||||
public static final String TYPE_UNICODE = "unicode";
|
||||
/**
|
||||
* string type (see {@link #TYPE_STRING_TYPES}
|
||||
*/
|
||||
public static final String TYPE_STR = "str";
|
||||
/**
|
||||
* Any string type
|
||||
*/
|
||||
public static final List<String> TYPE_STRING_TYPES = List.of(TYPE_UNICODE, TYPE_STR);
|
||||
/**
|
||||
* date type
|
||||
*/
|
||||
public static final String TYPE_DATE = "datetime.date";
|
||||
/**
|
||||
* datetime type
|
||||
*/
|
||||
public static final String TYPE_DATE_TIME = "datetime.datetime";
|
||||
/**
|
||||
* time type
|
||||
*/
|
||||
public static final String TYPE_TIME = "datetime.time";
|
||||
|
||||
public static final String TYPE_BYTES = "bytes";
|
||||
|
||||
public static final String TYPE_BYTEARRAY = "bytearray";
|
||||
|
||||
public static final String TYPE_ENUM = "enum.Enum";
|
||||
|
||||
public static final String PYTHON_SDK_ID_NAME = "Python SDK";
|
||||
public static final String VERBOSE_REG_EXP_LANGUAGE_ID = "PythonVerboseRegExp";
|
||||
@NonNls public static final String PYTHON_MODULE_ID = "PYTHON_MODULE";
|
||||
public static final String TESTCASE_SETUP_NAME = "setUp";
|
||||
public static final String PY_DOCSTRING_ID = "Doctest";
|
||||
public static final String END_WILDCARD = ".*";
|
||||
|
||||
private PyNames() {
|
||||
}
|
||||
|
||||
public static final String INIT = "__init__";
|
||||
public static final String DUNDER_DICT = "__dict__";
|
||||
public static final String DOT_PY = ".py";
|
||||
public static final String DOT_PYI = ".pyi";
|
||||
public static final String INIT_DOT_PY = INIT + DOT_PY;
|
||||
public static final String INIT_DOT_PYI = INIT + DOT_PYI;
|
||||
|
||||
public static final String SETUP_DOT_PY = "setup" + DOT_PY;
|
||||
|
||||
public static final String NEW = "__new__";
|
||||
public static final String GETATTR = "__getattr__";
|
||||
public static final String GETATTRIBUTE = "__getattribute__";
|
||||
public static final String GET = "__get__";
|
||||
public static final String __CLASS__ = "__class__";
|
||||
public static final String DUNDER_METACLASS = "__metaclass__";
|
||||
public static final @NlsSafe String METACLASS = "metaclass";
|
||||
public static final String TYPE = "type";
|
||||
|
||||
public static final String SUPER = "super";
|
||||
|
||||
public static final String OBJECT = "object";
|
||||
public static final String NONE = "None";
|
||||
public static final String TRUE = "True";
|
||||
public static final String FALSE = "False";
|
||||
public static final String ELLIPSIS = "...";
|
||||
public static final String FUNCTION = "function";
|
||||
|
||||
public static final String TYPES_FUNCTION_TYPE = "types.FunctionType";
|
||||
public static final String TYPES_METHOD_TYPE = "types.UnboundMethodType";
|
||||
|
||||
public static final String FUTURE_MODULE = "__future__";
|
||||
public static final String UNICODE_LITERALS = "unicode_literals";
|
||||
|
||||
public static final String CLASSMETHOD = "classmethod";
|
||||
public static final String STATICMETHOD = "staticmethod";
|
||||
public static final String OVERLOAD = "overload";
|
||||
|
||||
public static final String PROPERTY = "property";
|
||||
public static final String SETTER = "setter";
|
||||
public static final String DELETER = "deleter";
|
||||
public static final String GETTER = "getter";
|
||||
|
||||
public static final String ALL = "__all__";
|
||||
public static final String SLOTS = "__slots__";
|
||||
public static final String DEBUG = "__debug__";
|
||||
|
||||
public static final String ISINSTANCE = "isinstance";
|
||||
public static final String ASSERT_IS_INSTANCE = "assertIsInstance";
|
||||
public static final String HAS_ATTR = "hasattr";
|
||||
public static final String ISSUBCLASS = "issubclass";
|
||||
|
||||
public static final String DOC = "__doc__";
|
||||
public static final String DOCFORMAT = "__docformat__";
|
||||
|
||||
public static final String DIRNAME = "dirname";
|
||||
public static final String ABSPATH = "abspath";
|
||||
public static final String NORMPATH = "normpath";
|
||||
public static final String REALPATH = "realpath";
|
||||
public static final String JOIN = "join";
|
||||
public static final String REPLACE = "replace";
|
||||
public static final String FILE = "__file__";
|
||||
public static final String PARDIR = "pardir";
|
||||
public static final String CURDIR = "curdir";
|
||||
|
||||
public static final String WARN = "warn";
|
||||
public static final String DEPRECATION_WARNING = "DeprecationWarning";
|
||||
public static final String PENDING_DEPRECATION_WARNING = "PendingDeprecationWarning";
|
||||
|
||||
public static final String CONTAINER = "Container";
|
||||
public static final String HASHABLE = "Hashable";
|
||||
public static final String ITERABLE = "Iterable";
|
||||
public static final String ITERATOR = "Iterator";
|
||||
public static final String SIZED = "Sized";
|
||||
public static final String CALLABLE = "Callable";
|
||||
public static final String SEQUENCE = "Sequence";
|
||||
public static final String MAPPING = "Mapping";
|
||||
public static final String MUTABLE_MAPPING = "MutableMapping";
|
||||
public static final String ABC_SET = "Set";
|
||||
public static final String ABC_MUTABLE_SET = "MutableSet";
|
||||
|
||||
public static final String AWAITABLE = "Awaitable";
|
||||
public static final String ASYNC_ITERABLE = "AsyncIterable";
|
||||
|
||||
public static final String ABC_NUMBER = "Number";
|
||||
public static final String ABC_COMPLEX = "Complex";
|
||||
public static final String ABC_REAL = "Real";
|
||||
public static final String ABC_RATIONAL = "Rational";
|
||||
public static final String ABC_INTEGRAL = "Integral";
|
||||
|
||||
public static final String CONTAINS = "__contains__";
|
||||
public static final String HASH = "__hash__";
|
||||
public static final String ITER = "__iter__";
|
||||
public static final String NEXT = "next";
|
||||
public static final String DUNDER_NEXT = "__next__";
|
||||
public static final String LEN = "__len__";
|
||||
public static final String CALL = "__call__";
|
||||
public static final String GETITEM = "__getitem__";
|
||||
public static final String SETITEM = "__setitem__";
|
||||
public static final String DELITEM = "__delitem__";
|
||||
public static final String POS = "__pos__";
|
||||
public static final String NEG = "__neg__";
|
||||
public static final String DIV = "__div__";
|
||||
public static final String TRUEDIV = "__truediv__";
|
||||
public static final String AITER = "__aiter__";
|
||||
public static final String ANEXT = "__anext__";
|
||||
public static final String AENTER = "__aenter__";
|
||||
public static final String AEXIT = "__aexit__";
|
||||
public static final String DUNDER_AWAIT = "__await__";
|
||||
public static final String SIZEOF = "__sizeof__";
|
||||
public static final String INIT_SUBCLASS = "__init_subclass__";
|
||||
public static final String COMPLEX = "__complex__";
|
||||
public static final String FLOAT = "__float__";
|
||||
public static final String INT = "__int__";
|
||||
public static final String BYTES = "__bytes__";
|
||||
public static final String ABS = "__abs__";
|
||||
public static final String ROUND = "__round__";
|
||||
public static final String CLASS_GETITEM = "__class_getitem__";
|
||||
public static final String PREPARE = "__prepare__";
|
||||
|
||||
public static final String NAME = "__name__";
|
||||
public static final String ENTER = "__enter__";
|
||||
public static final String EXIT = "__exit__";
|
||||
|
||||
public static final String CALLABLE_BUILTIN = "callable";
|
||||
public static final String NAMEDTUPLE = "namedtuple";
|
||||
public static final String COLLECTIONS = "collections";
|
||||
public static final String COLLECTIONS_NAMEDTUPLE_PY2 = COLLECTIONS + "." + NAMEDTUPLE;
|
||||
public static final String COLLECTIONS_NAMEDTUPLE_PY3 = COLLECTIONS + "." + INIT + "." + NAMEDTUPLE;
|
||||
|
||||
public static final String FORMAT = "format";
|
||||
|
||||
public static final String ABSTRACTMETHOD = "abstractmethod";
|
||||
public static final String ABSTRACTPROPERTY = "abstractproperty";
|
||||
public static final String ABC_META_CLASS = "ABCMeta";
|
||||
public static final String ABC = "abc.ABC";
|
||||
public static final String ABC_META = "abc.ABCMeta";
|
||||
|
||||
public static final String TUPLE = "tuple";
|
||||
public static final String SET = "set";
|
||||
public static final String SLICE = "slice";
|
||||
public static final String DICT = "dict";
|
||||
|
||||
public static final String KEYS = "keys";
|
||||
public static final String APPEND = "append";
|
||||
public static final String EXTEND = "extend";
|
||||
public static final String UPDATE = "update";
|
||||
public static final String CLEAR = "clear";
|
||||
public static final String POP = "pop";
|
||||
public static final String POPITEM = "popitem";
|
||||
public static final String SETDEFAULT = "setdefault";
|
||||
|
||||
public static final String PASS = "pass";
|
||||
|
||||
public static final String TEST_CASE = "TestCase";
|
||||
|
||||
public static final String PYCACHE = "__pycache__";
|
||||
|
||||
public static final String NOT_IMPLEMENTED_ERROR = "NotImplementedError";
|
||||
|
||||
public static final @NlsSafe String UNKNOWN_TYPE = "Any";
|
||||
|
||||
public static final @NlsSafe String UNNAMED_ELEMENT = "<unnamed>";
|
||||
|
||||
public static final String UNDERSCORE = "_";
|
||||
|
||||
/**
|
||||
* Contains all known predefined names of "__foo__" form.
|
||||
*/
|
||||
public static final Set<String> UNDERSCORED_ATTRIBUTES = Set.of(
|
||||
"__all__",
|
||||
"__annotations__",
|
||||
"__author__",
|
||||
"__bases__",
|
||||
"__closure__",
|
||||
"__code__",
|
||||
"__defaults__",
|
||||
"__dict__",
|
||||
"__dir__",
|
||||
"__doc__",
|
||||
"__docformat__",
|
||||
"__file__",
|
||||
"__func__",
|
||||
"__globals__",
|
||||
"__kwdefaults__",
|
||||
"__members__",
|
||||
"__metaclass__",
|
||||
"__mod__",
|
||||
"__module__",
|
||||
"__mro__",
|
||||
"__name__",
|
||||
"__path__",
|
||||
"__qualname__",
|
||||
"__self__",
|
||||
"__slots__",
|
||||
"__version__"
|
||||
);
|
||||
|
||||
public static final Set<String> COMPARISON_OPERATORS = Set.of(
|
||||
"__eq__",
|
||||
"__ne__",
|
||||
"__lt__",
|
||||
"__le__",
|
||||
"__gt__",
|
||||
"__ge__",
|
||||
"__cmp__",
|
||||
"__contains__"
|
||||
);
|
||||
|
||||
public static final Set<String> SUBSCRIPTION_OPERATORS = Set.of(
|
||||
GETITEM,
|
||||
SETITEM,
|
||||
DELITEM
|
||||
);
|
||||
|
||||
public static class BuiltinDescription {
|
||||
private final String mySignature;
|
||||
|
||||
public BuiltinDescription(String signature) {
|
||||
mySignature = signature;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return mySignature;
|
||||
}
|
||||
|
||||
// TODO: doc string, too
|
||||
}
|
||||
|
||||
private static final BuiltinDescription _only_self_descr = new BuiltinDescription("(self)");
|
||||
private static final BuiltinDescription _self_other_descr = new BuiltinDescription("(self, other)");
|
||||
private static final BuiltinDescription _self_item_descr = new BuiltinDescription("(self, item)");
|
||||
private static final BuiltinDescription _self_key_descr = new BuiltinDescription("(self, key)");
|
||||
private static final BuiltinDescription _exit_descr = new BuiltinDescription("(self, exc_type, exc_val, exc_tb)");
|
||||
|
||||
@SuppressWarnings("JavacQuirks")
|
||||
private static final Map<String, BuiltinDescription> BuiltinMethods = Map.ofEntries(
|
||||
Map.entry(ABS, _only_self_descr),
|
||||
Map.entry("__add__", _self_other_descr),
|
||||
Map.entry("__and__", _self_other_descr),
|
||||
//_BuiltinMethodsMap.entry("__all__", _only_self_descr);
|
||||
//_BuiltinMethodsMap.entry("__author__", _only_self_descr);
|
||||
//_BuiltinMethodsMap.entry("__bases__", _only_self_descr);
|
||||
Map.entry("__call__", new BuiltinDescription("(self, *args, **kwargs)")),
|
||||
Map.entry("__ceil__", _only_self_descr),
|
||||
//_BuiltinMethodsMap.entry("__class__", _only_self_descr);
|
||||
Map.entry("__cmp__", _self_other_descr),
|
||||
Map.entry("__coerce__", _self_other_descr),
|
||||
Map.entry(COMPLEX, _only_self_descr),
|
||||
Map.entry("__contains__", _self_item_descr),
|
||||
Map.entry("__copy__", _only_self_descr),
|
||||
//_BuiltinMethodsMap.entry("__debug__", _only_self_descr);
|
||||
Map.entry("__deepcopy__", new BuiltinDescription("(self, memodict={})")),
|
||||
Map.entry("__del__", _only_self_descr),
|
||||
Map.entry("__delete__", new BuiltinDescription("(self, instance)")),
|
||||
Map.entry("__delattr__", _self_item_descr),
|
||||
Map.entry("__delitem__", _self_key_descr),
|
||||
Map.entry("__delslice__", new BuiltinDescription("(self, i, j)")),
|
||||
//_BuiltinMethodsMap.entry("__dict__", _only_self_descr);
|
||||
Map.entry("__divmod__", _self_other_descr),
|
||||
//_BuiltinMethodsMap.entry("__doc__", _only_self_descr);
|
||||
//_BuiltinMethodsMap.entry("__docformat__", _only_self_descr);
|
||||
Map.entry("__enter__", _only_self_descr),
|
||||
Map.entry("__exit__", _exit_descr),
|
||||
Map.entry("__eq__", _self_other_descr),
|
||||
//_BuiltinMethodsMap.entry("__file__", _only_self_descr);
|
||||
Map.entry(FLOAT, _only_self_descr),
|
||||
Map.entry("__floor__", _only_self_descr),
|
||||
Map.entry("__floordiv__", _self_other_descr),
|
||||
//_BuiltinMethodsMap.entry("__future__", _only_self_descr);
|
||||
Map.entry("__ge__", _self_other_descr),
|
||||
Map.entry("__get__", new BuiltinDescription("(self, instance, owner)")),
|
||||
Map.entry("__getattr__", _self_item_descr),
|
||||
Map.entry("__getattribute__", _self_item_descr),
|
||||
Map.entry("__getinitargs__", _only_self_descr),
|
||||
Map.entry("__getitem__", _self_item_descr),
|
||||
Map.entry("__getnewargs__", _only_self_descr),
|
||||
//_BuiltinMethodsMap.entry("__getslice__", new BuiltinDescription("(self, i, j)"));
|
||||
Map.entry("__getstate__", _only_self_descr),
|
||||
Map.entry("__gt__", _self_other_descr),
|
||||
Map.entry("__hash__", _only_self_descr),
|
||||
Map.entry("__hex__", _only_self_descr),
|
||||
Map.entry("__iadd__", _self_other_descr),
|
||||
Map.entry("__iand__", _self_other_descr),
|
||||
Map.entry("__idiv__", _self_other_descr),
|
||||
Map.entry("__ifloordiv__", _self_other_descr),
|
||||
//_BuiltinMethodsMap.entry("__import__", _only_self_descr);
|
||||
Map.entry("__ilshift__", _self_other_descr),
|
||||
Map.entry("__imod__", _self_other_descr),
|
||||
Map.entry("__imul__", _self_other_descr),
|
||||
Map.entry("__index__", _only_self_descr),
|
||||
Map.entry(INIT, _only_self_descr),
|
||||
Map.entry(INT, _only_self_descr),
|
||||
Map.entry("__invert__", _only_self_descr),
|
||||
Map.entry("__ior__", _self_other_descr),
|
||||
Map.entry("__ipow__", _self_other_descr),
|
||||
Map.entry("__irshift__", _self_other_descr),
|
||||
Map.entry("__isub__", _self_other_descr),
|
||||
Map.entry("__iter__", _only_self_descr),
|
||||
Map.entry("__itruediv__", _self_other_descr),
|
||||
Map.entry("__ixor__", _self_other_descr),
|
||||
Map.entry("__le__", _self_other_descr),
|
||||
Map.entry("__len__", _only_self_descr),
|
||||
Map.entry("__long__", _only_self_descr),
|
||||
Map.entry("__lshift__", _self_other_descr),
|
||||
Map.entry("__lt__", _self_other_descr),
|
||||
//_BuiltinMethodsMap.entry("__members__", _only_self_descr);
|
||||
//_BuiltinMethodsMap.entry("__metaclass__", _only_self_descr);
|
||||
Map.entry("__missing__", _self_key_descr),
|
||||
Map.entry("__mod__", _self_other_descr),
|
||||
//_BuiltinMethodsMap.entry("__mro__", _only_self_descr);
|
||||
Map.entry("__mul__", _self_other_descr),
|
||||
//_BuiltinMethodsMap.entry("__name__", _only_self_descr);
|
||||
Map.entry("__ne__", _self_other_descr),
|
||||
Map.entry("__neg__", _only_self_descr),
|
||||
Map.entry(NEW, new BuiltinDescription("(cls, *args, **kwargs)")),
|
||||
Map.entry("__oct__", _only_self_descr),
|
||||
Map.entry("__or__", _self_other_descr),
|
||||
//_BuiltinMethodsMap.entry("__path__", _only_self_descr);
|
||||
Map.entry("__pos__", _only_self_descr),
|
||||
Map.entry("__pow__", new BuiltinDescription("(self, power, modulo=None)")),
|
||||
Map.entry("__radd__", _self_other_descr),
|
||||
Map.entry("__rand__", _self_other_descr),
|
||||
Map.entry("__rdiv__", _self_other_descr),
|
||||
Map.entry("__rdivmod__", _self_other_descr),
|
||||
Map.entry("__reduce__", _only_self_descr),
|
||||
Map.entry("__reduce_ex__", new BuiltinDescription("(self, protocol)")),
|
||||
Map.entry("__repr__", _only_self_descr),
|
||||
Map.entry("__reversed__", _only_self_descr),
|
||||
Map.entry("__rfloordiv__", _self_other_descr),
|
||||
Map.entry("__rlshift__", _self_other_descr),
|
||||
Map.entry("__rmod__", _self_other_descr),
|
||||
Map.entry("__rmul__", _self_other_descr),
|
||||
Map.entry("__ror__", _self_other_descr),
|
||||
Map.entry("__rpow__", _self_other_descr),
|
||||
Map.entry("__rrshift__", _self_other_descr),
|
||||
Map.entry("__rshift__", _self_other_descr),
|
||||
Map.entry("__rsub__", _self_other_descr),
|
||||
Map.entry("__rtruediv__", _self_other_descr),
|
||||
Map.entry("__rxor__", _self_other_descr),
|
||||
Map.entry("__set__", new BuiltinDescription("(self, instance, value)")),
|
||||
Map.entry("__setattr__", new BuiltinDescription("(self, key, value)")),
|
||||
Map.entry("__setitem__", new BuiltinDescription("(self, key, value)")),
|
||||
Map.entry("__setslice__", new BuiltinDescription("(self, i, j, sequence)")),
|
||||
Map.entry("__setstate__", new BuiltinDescription("(self, state)")),
|
||||
Map.entry(SIZEOF, _only_self_descr),
|
||||
//_BuiltinMethodsMap.entry("__self__", _only_self_descr);
|
||||
//_BuiltinMethodsMap.entry("__slots__", _only_self_descr);
|
||||
Map.entry("__str__", _only_self_descr),
|
||||
Map.entry("__sub__", _self_other_descr),
|
||||
Map.entry("__truediv__", _self_other_descr),
|
||||
Map.entry("__trunc__", _only_self_descr),
|
||||
Map.entry("__unicode__", _only_self_descr),
|
||||
//_BuiltinMethodsMap.entry("__version__", _only_self_descr);
|
||||
Map.entry("__xor__", _self_other_descr));
|
||||
|
||||
private static final Map<String, BuiltinDescription> PY2_BUILTIN_METHODS = concat(
|
||||
BuiltinMethods,
|
||||
Map.entry("__nonzero__", _only_self_descr),
|
||||
Map.entry("__div__", _self_other_descr),
|
||||
Map.entry(NEXT, _only_self_descr));
|
||||
|
||||
private static final Map<String, BuiltinDescription> PY3_BUILTIN_METHODS = concat(
|
||||
BuiltinMethods,
|
||||
Map.entry("__bool__", _only_self_descr),
|
||||
Map.entry(BYTES, _only_self_descr),
|
||||
Map.entry("__format__", new BuiltinDescription("(self, format_spec)")),
|
||||
Map.entry("__instancecheck__", new BuiltinDescription("(self, instance)")),
|
||||
Map.entry(PREPARE, new BuiltinDescription("(metacls, name, bases)")),
|
||||
Map.entry(ROUND, new BuiltinDescription("(self, n=None)")),
|
||||
Map.entry("__subclasscheck__", new BuiltinDescription("(self, subclass)")),
|
||||
Map.entry(DUNDER_NEXT, _only_self_descr));
|
||||
|
||||
private static final Map<String, BuiltinDescription> PY35_BUILTIN_METHODS = concat(
|
||||
PY3_BUILTIN_METHODS,
|
||||
Map.entry("__imatmul__", _self_other_descr),
|
||||
Map.entry("__matmul__", _self_other_descr),
|
||||
Map.entry("__rmatmul__", _self_other_descr),
|
||||
Map.entry(DUNDER_AWAIT, _only_self_descr),
|
||||
Map.entry(AENTER, _only_self_descr),
|
||||
Map.entry(AEXIT, _exit_descr),
|
||||
Map.entry(AITER, _only_self_descr),
|
||||
Map.entry(ANEXT, _only_self_descr));
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getBuiltinMethods(LanguageLevel)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static final ImmutableMap<String, BuiltinDescription> PY36_BUILTIN_METHODS = ImmutableMap.<String, BuiltinDescription>builder().putAll(concat(
|
||||
PY35_BUILTIN_METHODS,
|
||||
Map.entry(INIT_SUBCLASS, new BuiltinDescription("(cls, **kwargs)")),
|
||||
Map.entry("__set_name__", new BuiltinDescription("(self, owner, name)")),
|
||||
Map.entry("__fspath__", _only_self_descr))).build();
|
||||
|
||||
private static final Map<String, BuiltinDescription> PY37_BUILTIN_METHODS = concat(
|
||||
PY36_BUILTIN_METHODS,
|
||||
Map.entry(CLASS_GETITEM, new BuiltinDescription("(cls, item)")),
|
||||
Map.entry("__mro_entries__", new BuiltinDescription("(self, bases)")));
|
||||
|
||||
@NotNull
|
||||
private static final Map<String, BuiltinDescription> PY37_MODULE_BUILTIN_METHODS = Map.of(
|
||||
"__getattr__", new BuiltinDescription("(name)"),
|
||||
"__dir__", new BuiltinDescription("()"));
|
||||
|
||||
@SafeVarargs
|
||||
private static <K,V> Map<K,V> concat(Map<? extends K, ? extends V> map, Map.Entry<K,V>... additional) {
|
||||
Map<K, V> r = new HashMap<>(map);
|
||||
r.putAll(Map.ofEntries(additional));
|
||||
return Map.copyOf(r);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<String, BuiltinDescription> getBuiltinMethods(@NotNull LanguageLevel level) {
|
||||
if (level.isAtLeast(LanguageLevel.PYTHON37)) {
|
||||
return PY37_BUILTIN_METHODS;
|
||||
}
|
||||
else if (level.isAtLeast(LanguageLevel.PYTHON36)) {
|
||||
return PY36_BUILTIN_METHODS;
|
||||
}
|
||||
else if (level.isAtLeast(LanguageLevel.PYTHON35)) {
|
||||
return PY35_BUILTIN_METHODS;
|
||||
}
|
||||
else if (!level.isPython2()) {
|
||||
return PY3_BUILTIN_METHODS;
|
||||
}
|
||||
else {
|
||||
return PY2_BUILTIN_METHODS;
|
||||
}
|
||||
}
|
||||
|
||||
public static @NotNull Map<String, BuiltinDescription> getModuleBuiltinMethods(@NotNull LanguageLevel level) {
|
||||
if (level.isAtLeast(LanguageLevel.PYTHON37)) {
|
||||
return PY37_MODULE_BUILTIN_METHODS;
|
||||
}
|
||||
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
// canonical names, not forced by interpreter
|
||||
public static final String CANONICAL_SELF = "self";
|
||||
public static final String CANONICAL_CLS = "cls";
|
||||
public static final String BASESTRING = "basestring";
|
||||
|
||||
/*
|
||||
Python keywords
|
||||
*/
|
||||
|
||||
public static final String CLASS = "class";
|
||||
public static final String DEF = "def";
|
||||
public static final String IF = "if";
|
||||
public static final String ELSE = "else";
|
||||
public static final String ELIF = "elif";
|
||||
public static final String TRY = "try";
|
||||
public static final String EXCEPT = "except";
|
||||
public static final String FINALLY = "finally";
|
||||
public static final String WHILE = "while";
|
||||
public static final String FOR = "for";
|
||||
public static final String WITH = "with";
|
||||
public static final String AS = "as";
|
||||
public static final String ASSERT = "assert";
|
||||
public static final String DEL = "del";
|
||||
public static final String EXEC = "exec";
|
||||
public static final String FROM = "from";
|
||||
public static final String IMPORT = "import";
|
||||
public static final String RAISE = "raise";
|
||||
public static final String PRINT = "print";
|
||||
public static final String BREAK = "break";
|
||||
public static final String CONTINUE = "continue";
|
||||
public static final String GLOBAL = "global";
|
||||
public static final String RETURN = "return";
|
||||
public static final String YIELD = "yield";
|
||||
public static final String NONLOCAL = "nonlocal";
|
||||
public static final String AND = "and";
|
||||
public static final String OR = "or";
|
||||
public static final String IS = "is";
|
||||
public static final String IN = "in";
|
||||
public static final String NOT = "not";
|
||||
public static final String LAMBDA = "lambda";
|
||||
public static final String ASYNC = "async";
|
||||
public static final String AWAIT = "await";
|
||||
public static final String MATCH = "match";
|
||||
public static final String CASE = "case";
|
||||
|
||||
/**
|
||||
* Contains keywords as of CPython 2.5.
|
||||
*/
|
||||
public static final Set<String> KEYWORDS = Set.of(
|
||||
AND,
|
||||
DEL,
|
||||
FROM,
|
||||
NOT,
|
||||
WHILE,
|
||||
AS,
|
||||
ELIF,
|
||||
GLOBAL,
|
||||
OR,
|
||||
WITH,
|
||||
ASSERT,
|
||||
ELSE,
|
||||
IF,
|
||||
PASS,
|
||||
YIELD,
|
||||
BREAK,
|
||||
EXCEPT,
|
||||
IMPORT,
|
||||
PRINT,
|
||||
CLASS,
|
||||
EXEC,
|
||||
IN,
|
||||
RAISE,
|
||||
CONTINUE,
|
||||
FINALLY,
|
||||
IS,
|
||||
RETURN,
|
||||
DEF,
|
||||
FOR,
|
||||
LAMBDA,
|
||||
TRY
|
||||
);
|
||||
|
||||
public static final Set<String> BUILTIN_INTERFACES = Set.of(
|
||||
CALLABLE, HASHABLE, ITERABLE, ITERATOR, SIZED, CONTAINER, SEQUENCE, MAPPING, ABC_COMPLEX, ABC_REAL, ABC_RATIONAL, ABC_INTEGRAL,
|
||||
ABC_NUMBER
|
||||
);
|
||||
|
||||
/**
|
||||
* TODO: dependency on language level.
|
||||
*
|
||||
* @param name what to check
|
||||
* @return true iff the name is either a keyword or a reserved name, like None.
|
||||
*/
|
||||
public static boolean isReserved(@Nullable @NonNls String name) {
|
||||
return name != null && KEYWORDS.contains(name) || NONE.equals(name);
|
||||
}
|
||||
|
||||
// NOTE: includes unicode only good for py3k
|
||||
public static final String IDENTIFIER_RE = "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*";
|
||||
private final static Pattern IDENTIFIER_PATTERN = Pattern.compile(IDENTIFIER_RE);
|
||||
|
||||
/**
|
||||
* TODO: dependency on language level.
|
||||
*
|
||||
* @param name what to check
|
||||
* @return true iff name is not reserved and is a well-formed identifier.
|
||||
*/
|
||||
public static boolean isIdentifier(@NotNull @NonNls String name) {
|
||||
return !isReserved(name) && isIdentifierString(name);
|
||||
}
|
||||
|
||||
public static boolean isIdentifierString(@NotNull @NonNls String name) {
|
||||
return IDENTIFIER_PATTERN.matcher(name).matches();
|
||||
}
|
||||
|
||||
public static boolean isRightOperatorName(@Nullable String name) {
|
||||
if ("__rshift__".equals(name)) return false;
|
||||
return name != null && (name.matches("__r[a-z]+__") || CONTAINS.equals(name));
|
||||
}
|
||||
|
||||
public static boolean isRightOperatorName(@Nullable String referencedName, @Nullable String calleeName) {
|
||||
if (isRightOperatorName(calleeName)) return true;
|
||||
|
||||
return referencedName != null && calleeName != null && calleeName.equals(leftToRightComparisonOperatorName(referencedName));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String leftToRightOperatorName(@Nullable String name) {
|
||||
if (name == null) return null;
|
||||
|
||||
final String rightComparisonOperatorName = leftToRightComparisonOperatorName(name);
|
||||
if (rightComparisonOperatorName != null) return rightComparisonOperatorName;
|
||||
|
||||
return name.replaceFirst("__([a-z]+)__", "__r$1__");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String leftToRightComparisonOperatorName(@NotNull String name) {
|
||||
return switch (name) {
|
||||
case "__lt__" -> "__gt__";
|
||||
case "__gt__" -> "__lt__";
|
||||
case "__ge__" -> "__le__";
|
||||
case "__le__" -> "__ge__";
|
||||
case "__eq__", "__ne__" -> name;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Available in Python 3 and Python 2 starting from 2.6.
|
||||
* <p/>
|
||||
* Attributes {@code __doc__}, {@code __dict__} and {@code __module__} should be inherited from object.
|
||||
*/
|
||||
public static final Set<String> FUNCTION_SPECIAL_ATTRIBUTES = Set.of(
|
||||
"__defaults__",
|
||||
"__globals__",
|
||||
"__closure__",
|
||||
"__code__",
|
||||
"__name__"
|
||||
);
|
||||
|
||||
public static final Set<String> LEGACY_FUNCTION_SPECIAL_ATTRIBUTES = Set.of(
|
||||
"func_defaults",
|
||||
"func_globals",
|
||||
"func_closure",
|
||||
"func_code",
|
||||
"func_name",
|
||||
"func_doc",
|
||||
"func_dict"
|
||||
);
|
||||
|
||||
public static final Set<String> PY3_ONLY_FUNCTION_SPECIAL_ATTRIBUTES = Set.of("__annotations__", "__kwdefaults__");
|
||||
|
||||
public static final Set<String> METHOD_SPECIAL_ATTRIBUTES = Set.of("__func__", "__self__", "__name__");
|
||||
|
||||
public static final Set<String> LEGACY_METHOD_SPECIAL_ATTRIBUTES = Set.of("im_func", "im_self", "im_class");
|
||||
|
||||
public static final String MRO = "mro";
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.jetbrains.python.psi.PyElementType;
|
||||
|
||||
public final class PyTokenTypes {
|
||||
private PyTokenTypes() {
|
||||
}
|
||||
|
||||
public static final PyElementType IDENTIFIER = new PyElementType("IDENTIFIER");
|
||||
public static final PyElementType LINE_BREAK = new PyElementType("LINE_BREAK");
|
||||
public static final PyElementType STATEMENT_BREAK = new PyElementType("STATEMENT_BREAK");
|
||||
public static final PyElementType SPACE = new PyElementType("SPACE");
|
||||
public static final PyElementType TAB = new PyElementType("TAB");
|
||||
public static final PyElementType FORMFEED = new PyElementType("FORMFEED");
|
||||
public static final IElementType BAD_CHARACTER = TokenType.BAD_CHARACTER;
|
||||
public static final PyElementType INCONSISTENT_DEDENT = new PyElementType("INCONSISTENT_DEDENT");
|
||||
|
||||
public static final PyElementType END_OF_LINE_COMMENT = new PyElementType("END_OF_LINE_COMMENT");
|
||||
|
||||
public static final PyElementType AND_KEYWORD = new PyElementType("AND_KEYWORD");
|
||||
public static final PyElementType AS_KEYWORD = new PyElementType("AS_KEYWORD");
|
||||
public static final PyElementType ASSERT_KEYWORD = new PyElementType("ASSERT_KEYWORD");
|
||||
public static final PyElementType BREAK_KEYWORD = new PyElementType("BREAK_KEYWORD");
|
||||
public static final PyElementType CASE_KEYWORD = new PyElementType("CASE_KEYWORD");
|
||||
public static final PyElementType CLASS_KEYWORD = new PyElementType("CLASS_KEYWORD");
|
||||
public static final PyElementType CONTINUE_KEYWORD = new PyElementType("CONTINUE_KEYWORD");
|
||||
public static final PyElementType DEF_KEYWORD = new PyElementType("DEF_KEYWORD");
|
||||
public static final PyElementType DEL_KEYWORD = new PyElementType("DEL_KEYWORD");
|
||||
public static final PyElementType ELIF_KEYWORD = new PyElementType("ELIF_KEYWORD");
|
||||
public static final PyElementType ELSE_KEYWORD = new PyElementType("ELSE_KEYWORD");
|
||||
public static final PyElementType EXCEPT_KEYWORD = new PyElementType("EXCEPT_KEYWORD");
|
||||
public static final PyElementType EXEC_KEYWORD = new PyElementType("EXEC_KEYWORD");
|
||||
public static final PyElementType FINALLY_KEYWORD = new PyElementType("FINALLY_KEYWORD");
|
||||
public static final PyElementType FOR_KEYWORD = new PyElementType("FOR_KEYWORD");
|
||||
public static final PyElementType FROM_KEYWORD = new PyElementType("FROM_KEYWORD");
|
||||
public static final PyElementType GLOBAL_KEYWORD = new PyElementType("GLOBAL_KEYWORD");
|
||||
public static final PyElementType IF_KEYWORD = new PyElementType("IF_KEYWORD");
|
||||
public static final PyElementType IMPORT_KEYWORD = new PyElementType("IMPORT_KEYWORD");
|
||||
public static final PyElementType IN_KEYWORD = new PyElementType("IN_KEYWORD", "__contains__");
|
||||
public static final PyElementType IS_KEYWORD = new PyElementType("IS_KEYWORD");
|
||||
public static final PyElementType LAMBDA_KEYWORD = new PyElementType("LAMBDA_KEYWORD");
|
||||
public static final PyElementType MATCH_KEYWORD = new PyElementType("MATCH_KEYWORD");
|
||||
public static final PyElementType TYPE_KEYWORD = new PyElementType("TYPE_KEYWORD");
|
||||
public static final PyElementType NOT_KEYWORD = new PyElementType("NOT_KEYWORD");
|
||||
public static final PyElementType OR_KEYWORD = new PyElementType("OR_KEYWORD");
|
||||
public static final PyElementType PASS_KEYWORD = new PyElementType("PASS_KEYWORD");
|
||||
public static final PyElementType PRINT_KEYWORD = new PyElementType("PRINT_KEYWORD");
|
||||
public static final PyElementType RAISE_KEYWORD = new PyElementType("RAISE_KEYWORD");
|
||||
public static final PyElementType RETURN_KEYWORD = new PyElementType("RETURN_KEYWORD");
|
||||
public static final PyElementType TRY_KEYWORD = new PyElementType("TRY_KEYWORD");
|
||||
public static final PyElementType WITH_KEYWORD = new PyElementType("WITH_KEYWORD");
|
||||
public static final PyElementType WHILE_KEYWORD = new PyElementType("WHILE_KEYWORD");
|
||||
public static final PyElementType YIELD_KEYWORD = new PyElementType("YIELD_KEYWORD");
|
||||
|
||||
// new keywords in Python 3
|
||||
public static final PyElementType NONE_KEYWORD = new PyElementType("NONE_KEYWORD");
|
||||
public static final PyElementType TRUE_KEYWORD = new PyElementType("TRUE_KEYWORD");
|
||||
public static final PyElementType FALSE_KEYWORD = new PyElementType("FALSE_KEYWORD");
|
||||
public static final PyElementType NONLOCAL_KEYWORD = new PyElementType("NONLOCAL_KEYWORD");
|
||||
public static final PyElementType DEBUG_KEYWORD = new PyElementType("DEBUG_KEYWORD");
|
||||
public static final PyElementType ASYNC_KEYWORD = new PyElementType("ASYNC_KEYWORD");
|
||||
public static final PyElementType AWAIT_KEYWORD = new PyElementType("AWAIT_KEYWORD", "__await__");
|
||||
|
||||
public static final PyElementType INTEGER_LITERAL = new PyElementType("INTEGER_LITERAL");
|
||||
public static final PyElementType FLOAT_LITERAL = new PyElementType("FLOAT_LITERAL");
|
||||
public static final PyElementType IMAGINARY_LITERAL = new PyElementType("IMAGINARY_LITERAL");
|
||||
|
||||
public static final PyElementType SINGLE_QUOTED_STRING = new PyElementType("SINGLE_QUOTED_STRING");
|
||||
public static final PyElementType TRIPLE_QUOTED_STRING = new PyElementType("TRIPLE_QUOTED_STRING");
|
||||
public static final PyElementType SINGLE_QUOTED_UNICODE = new PyElementType("SINGLE_QUOTED_UNICODE");
|
||||
public static final PyElementType TRIPLE_QUOTED_UNICODE = new PyElementType("TRIPLE_QUOTED_UNICODE");
|
||||
|
||||
public static final PyElementType DOCSTRING = new PyElementType("DOCSTRING");
|
||||
|
||||
public static final TokenSet UNICODE_NODES = TokenSet.create(TRIPLE_QUOTED_UNICODE, SINGLE_QUOTED_UNICODE);
|
||||
public static final TokenSet TRIPLE_NODES = TokenSet.create(TRIPLE_QUOTED_UNICODE, TRIPLE_QUOTED_STRING);
|
||||
public static final TokenSet STRING_NODES = TokenSet.orSet(UNICODE_NODES, TokenSet.create(SINGLE_QUOTED_STRING,
|
||||
TRIPLE_QUOTED_STRING, DOCSTRING));
|
||||
// Operators
|
||||
public static final PyElementType PLUS = new PyElementType("PLUS", "__add__");// +
|
||||
public static final PyElementType MINUS = new PyElementType("MINUS", "__sub__");// -
|
||||
public static final PyElementType MULT = new PyElementType("MULT", "__mul__");// *
|
||||
public static final PyElementType EXP = new PyElementType("EXP", "__pow__");// **
|
||||
public static final PyElementType DIV = new PyElementType("DIV", "__div__"); // /
|
||||
public static final PyElementType FLOORDIV = new PyElementType("FLOORDIV", "__floordiv__"); // //
|
||||
public static final PyElementType PERC = new PyElementType("PERC", "__mod__");// %
|
||||
public static final PyElementType LTLT = new PyElementType("LTLT", "__lshift__");// <<
|
||||
public static final PyElementType GTGT = new PyElementType("GTGT", "__rshift__");// >>
|
||||
public static final PyElementType AND = new PyElementType("AND", "__and__");// &
|
||||
public static final PyElementType OR = new PyElementType("OR", "__or__");// |
|
||||
public static final PyElementType XOR = new PyElementType("XOR", "__xor__");// ^
|
||||
public static final PyElementType TILDE = new PyElementType("TILDE", "__invert__");// ~
|
||||
public static final PyElementType LT = new PyElementType("LT", "__lt__");// <
|
||||
public static final PyElementType GT = new PyElementType("GT", "__gt__");// >
|
||||
public static final PyElementType LE = new PyElementType("LE", "__le__");// <=
|
||||
public static final PyElementType GE = new PyElementType("GE", "__ge__");// >=
|
||||
public static final PyElementType EQEQ = new PyElementType("EQEQ", "__eq__");// ==
|
||||
public static final PyElementType NE = new PyElementType("NE", "__ne__");// !=
|
||||
public static final PyElementType NE_OLD = new PyElementType("NE_OLD", "__ne__");// <>
|
||||
|
||||
// Delimiters
|
||||
public static final PyElementType LPAR = new PyElementType("LPAR");// (
|
||||
public static final PyElementType RPAR = new PyElementType("RPAR");// )
|
||||
public static final PyElementType LBRACKET = new PyElementType("LBRACKET");// [
|
||||
public static final PyElementType RBRACKET = new PyElementType("RBRACKET");// ]
|
||||
public static final PyElementType LBRACE = new PyElementType("LBRACE");// {
|
||||
public static final PyElementType RBRACE = new PyElementType("RBRACE");// }
|
||||
public static final PyElementType AT = new PyElementType("AT", "__matmul__");// @
|
||||
public static final PyElementType COMMA = new PyElementType("COMMA");// ,
|
||||
public static final PyElementType COLON = new PyElementType("COLON");// :
|
||||
public static final PyElementType DOT = new PyElementType("DOT");// .
|
||||
public static final PyElementType TICK = new PyElementType("TICK");// `
|
||||
public static final PyElementType EQ = new PyElementType("EQ");// =
|
||||
public static final PyElementType SEMICOLON = new PyElementType("SEMICOLON");// ;
|
||||
public static final PyElementType PLUSEQ = new PyElementType("PLUSEQ");// +=
|
||||
public static final PyElementType MINUSEQ = new PyElementType("MINUSEQ");// -=
|
||||
public static final PyElementType MULTEQ = new PyElementType("MULTEQ");// *=
|
||||
public static final PyElementType ATEQ = new PyElementType("ATEQ"); // @=
|
||||
public static final PyElementType DIVEQ = new PyElementType("DIVEQ"); // /=
|
||||
public static final PyElementType FLOORDIVEQ = new PyElementType("FLOORDIVEQ"); // //=
|
||||
public static final PyElementType PERCEQ = new PyElementType("PERCEQ");// %=
|
||||
public static final PyElementType ANDEQ = new PyElementType("ANDEQ");// &=
|
||||
public static final PyElementType OREQ = new PyElementType("OREQ");// |=
|
||||
public static final PyElementType XOREQ = new PyElementType("XOREQ");// ^=
|
||||
public static final PyElementType LTLTEQ = new PyElementType("LTLTEQ");// <<=
|
||||
public static final PyElementType GTGTEQ = new PyElementType("GTGTEQ");// >>=
|
||||
public static final PyElementType EXPEQ = new PyElementType("EXPEQ");// **=
|
||||
public static final PyElementType RARROW = new PyElementType("RARROW");// ->
|
||||
public static final PyElementType COLONEQ = new PyElementType("COLONEQ");// :=
|
||||
|
||||
public static final TokenSet OPERATIONS = TokenSet.create(
|
||||
PLUS, MINUS, MULT, AT, EXP, DIV, FLOORDIV, PERC, LTLT, GTGT, AND, OR,
|
||||
XOR, TILDE, LT, GT, LE, GE, EQEQ, NE, NE_OLD, AT, COLON, TICK, EQ,
|
||||
PLUSEQ, MINUSEQ,
|
||||
MULTEQ, ATEQ, DIVEQ, FLOORDIVEQ, PERCEQ, ANDEQ, OREQ, XOREQ, LTLTEQ, GTGTEQ,
|
||||
EXPEQ, COLONEQ);
|
||||
|
||||
public static final TokenSet COMPARISON_OPERATIONS = TokenSet.create(
|
||||
LT, GT, EQEQ, GE, LE, NE, NE_OLD, IN_KEYWORD, IS_KEYWORD, NOT_KEYWORD);
|
||||
|
||||
public static final TokenSet SHIFT_OPERATIONS = TokenSet.create(LTLT, GTGT);
|
||||
public static final TokenSet ADDITIVE_OPERATIONS = TokenSet.create(PLUS, MINUS);
|
||||
public static final TokenSet MULTIPLICATIVE_OPERATIONS = TokenSet.create(MULT, AT, FLOORDIV, DIV, PERC);
|
||||
public static final TokenSet STAR_OPERATORS = TokenSet.create(MULT, EXP);
|
||||
public static final TokenSet UNARY_OPERATIONS = TokenSet.create(PLUS, MINUS, TILDE);
|
||||
public static final TokenSet BITWISE_OPERATIONS = TokenSet.create(AND, OR, XOR);
|
||||
public static final TokenSet EQUALITY_OPERATIONS = TokenSet.create(EQEQ, NE, NE_OLD);
|
||||
public static final TokenSet RELATIONAL_OPERATIONS = TokenSet.create(LT, GT, LE, GE);
|
||||
public static final TokenSet END_OF_STATEMENT = TokenSet.create(STATEMENT_BREAK, SEMICOLON);
|
||||
public static final TokenSet WHITESPACE = TokenSet.create(SPACE, TAB, FORMFEED);
|
||||
public static final TokenSet WHITESPACE_OR_LINEBREAK = TokenSet.create(SPACE, TAB, FORMFEED, LINE_BREAK);
|
||||
public static final TokenSet OPEN_BRACES = TokenSet.create(LBRACKET, LBRACE, LPAR);
|
||||
public static final TokenSet CLOSE_BRACES = TokenSet.create(RBRACKET, RBRACE, RPAR);
|
||||
public static final TokenSet ALL_BRACES = TokenSet.orSet(OPEN_BRACES, CLOSE_BRACES);
|
||||
|
||||
public static final TokenSet NUMERIC_LITERALS = TokenSet.create(FLOAT_LITERAL, INTEGER_LITERAL, IMAGINARY_LITERAL);
|
||||
public static final TokenSet BOOL_LITERALS = TokenSet.create(TRUE_KEYWORD, FALSE_KEYWORD);
|
||||
public static final TokenSet SCALAR_LITERALS = TokenSet.orSet(BOOL_LITERALS, NUMERIC_LITERALS, TokenSet.create(NONE_KEYWORD));
|
||||
public static final TokenSet EXPRESSION_KEYWORDS = TokenSet.create(TRUE_KEYWORD, FALSE_KEYWORD, NONE_KEYWORD);
|
||||
|
||||
public static final TokenSet AUG_ASSIGN_OPERATIONS = TokenSet.create(PLUSEQ, MINUSEQ, MULTEQ, ATEQ, DIVEQ,
|
||||
PERCEQ, EXPEQ, GTGTEQ, LTLTEQ, ANDEQ, OREQ, XOREQ, FLOORDIVEQ);
|
||||
|
||||
public static final PyElementType BACKSLASH = new PyElementType("BACKSLASH");
|
||||
|
||||
public static final PyElementType INDENT = new PyElementType("INDENT");
|
||||
public static final PyElementType DEDENT = new PyElementType("DEDENT");
|
||||
|
||||
public static final PyElementType FSTRING_TEXT = new PyElementType("FSTRING_TEXT");
|
||||
public static final PyElementType FSTRING_RAW_TEXT = new PyElementType("FSTRING_RAW_TEXT");
|
||||
public static final PyElementType FSTRING_START = new PyElementType("FSTRING_START");
|
||||
public static final PyElementType FSTRING_END = new PyElementType("FSTRING_END");
|
||||
public static final PyElementType FSTRING_FRAGMENT_START = new PyElementType("FSTRING_FRAGMENT_START");
|
||||
public static final PyElementType FSTRING_FRAGMENT_END = new PyElementType("FSTRING_FRAGMENT_END");
|
||||
public static final PyElementType FSTRING_FRAGMENT_FORMAT_START = new PyElementType("FSTRING_FRAGMENT_FORMAT_START");
|
||||
public static final PyElementType FSTRING_FRAGMENT_TYPE_CONVERSION = new PyElementType("FSTRING_FRAGMENT_TYPE_CONVERSION");
|
||||
|
||||
public static final TokenSet FSTRING_TOKENS = TokenSet.create(FSTRING_TEXT,
|
||||
FSTRING_RAW_TEXT,
|
||||
FSTRING_START,
|
||||
FSTRING_END,
|
||||
FSTRING_FRAGMENT_START,
|
||||
FSTRING_FRAGMENT_END,
|
||||
FSTRING_FRAGMENT_FORMAT_START,
|
||||
FSTRING_FRAGMENT_TYPE_CONVERSION);
|
||||
|
||||
public static final TokenSet FSTRING_TEXT_TOKENS = TokenSet.create(FSTRING_TEXT, FSTRING_RAW_TEXT);
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Contributes element types of various kinds specific for a particular Python dialect.
|
||||
*
|
||||
*/
|
||||
public interface PythonDialectsTokenSetContributor {
|
||||
ExtensionPointName<PythonDialectsTokenSetContributor> EP_NAME = ExtensionPointName.create("Pythonid.dialectsTokenSetContributor");
|
||||
|
||||
/**
|
||||
* Returns element types that are subclasses of {@link com.jetbrains.python.psi.PyStatement}.
|
||||
*/
|
||||
@NotNull
|
||||
TokenSet getStatementTokens();
|
||||
|
||||
/**
|
||||
* Returns element types that are subclasses of {@link com.jetbrains.python.psi.PyExpression}.
|
||||
*/
|
||||
@NotNull
|
||||
TokenSet getExpressionTokens();
|
||||
|
||||
/**
|
||||
* Returns element types that are language keywords.
|
||||
*/
|
||||
@NotNull
|
||||
TokenSet getKeywordTokens();
|
||||
|
||||
/**
|
||||
* Returns element types that are subclasses of {@link com.jetbrains.python.psi.PyParameter}.
|
||||
*/
|
||||
@NotNull
|
||||
TokenSet getParameterTokens();
|
||||
|
||||
/**
|
||||
* Returns element types that are subclasses of {@link com.jetbrains.python.psi.PyFunction}.
|
||||
*/
|
||||
@NotNull
|
||||
TokenSet getFunctionDeclarationTokens();
|
||||
|
||||
/**
|
||||
* Returns element types that can be used as unbalanced braces recovery tokens in the lexer.
|
||||
*/
|
||||
@NotNull
|
||||
TokenSet getUnbalancedBracesRecoveryTokens();
|
||||
|
||||
/**
|
||||
* Returns element types that are subclasses of {@link com.jetbrains.python.psi.PyReferenceExpression}.
|
||||
*/
|
||||
@NotNull
|
||||
TokenSet getReferenceExpressionTokens();
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
// Copyright 2000-2021 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;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.text.CharSequenceReader;
|
||||
import icons.PythonPsiApiIcons;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.IllegalCharsetNameException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class PythonFileType extends LanguageFileType {
|
||||
private static final Pattern ENCODING_PATTERN = Pattern.compile("coding[:=]\\s*([-\\w.]+)");
|
||||
public static final int MAX_CHARSET_ENCODING_LINE = 2;
|
||||
|
||||
public static final PythonFileType INSTANCE = new PythonFileType();
|
||||
|
||||
private PythonFileType() {
|
||||
this(PythonLanguage.INSTANCE);
|
||||
}
|
||||
|
||||
protected PythonFileType(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@NonNls
|
||||
public String getName() {
|
||||
return "Python";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@NlsSafe
|
||||
public String getDescription() {
|
||||
return "Python";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDefaultExtension() {
|
||||
return "py";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return PythonPsiApiIcons.PythonFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharset(@NotNull VirtualFile file, byte @NotNull [] content) {
|
||||
if (CharsetToolkit.hasUTF8Bom(content)) {
|
||||
return CharsetToolkit.UTF8;
|
||||
}
|
||||
ByteBuffer bytes = ByteBuffer.wrap(content, 0, Math.min(256, content.length));
|
||||
String decoded = StandardCharsets.UTF_8.decode(bytes).toString();
|
||||
return getCharsetFromEncodingDeclaration(StringUtil.convertLineSeparators(decoded));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Charset extractCharsetFromFileContent(@Nullable Project project, @Nullable VirtualFile file, @NotNull CharSequence content) {
|
||||
final String charsetName = getCharsetFromEncodingDeclaration(content);
|
||||
if (charsetName == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Charset.forName(charsetName);
|
||||
}
|
||||
catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getCharsetFromEncodingDeclaration(@NotNull PsiFile file) {
|
||||
final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
|
||||
final String content;
|
||||
if (document != null && document.getLineCount() > MAX_CHARSET_ENCODING_LINE) {
|
||||
final int offset = document.getLineEndOffset(MAX_CHARSET_ENCODING_LINE);
|
||||
content = document.getText(TextRange.create(0, offset));
|
||||
}
|
||||
else {
|
||||
content = file.getText();
|
||||
}
|
||||
return getCharsetFromEncodingDeclaration(content);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getCharsetFromEncodingDeclaration(@Nullable CharSequence content) {
|
||||
if (content == null || content.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
try (BufferedReader reader = new BufferedReader(new CharSequenceReader(content))) {
|
||||
for (int i = 0; i < MAX_CHARSET_ENCODING_LINE; i++) {
|
||||
final String line = reader.readLine();
|
||||
if (line == null) {
|
||||
return null;
|
||||
}
|
||||
final Matcher matcher = ENCODING_PATTERN.matcher(line);
|
||||
if (matcher.find()) {
|
||||
final String charset = matcher.group(1);
|
||||
return normalizeCharset(charset);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String normalizeCharset(String charset) {
|
||||
if (charset == null) {
|
||||
return null;
|
||||
}
|
||||
charset = StringUtil.toLowerCase(charset);
|
||||
if ("latin-1".equals(charset)) {
|
||||
return "iso-8859-1";
|
||||
}
|
||||
return charset;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2000-2021 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;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
|
||||
|
||||
public class PythonLanguage extends Language {
|
||||
|
||||
public static final PythonLanguage INSTANCE = new PythonLanguage();
|
||||
|
||||
public static PythonLanguage getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
protected PythonLanguage() {
|
||||
super("Python");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCaseSensitive() {
|
||||
return true; // http://jetbrains-feed.appspot.com/message/372001
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Lists interesting features importable from __future__.
|
||||
* {@code .toString()} returns the Python name of the feature.
|
||||
* <br/>
|
||||
*/
|
||||
public enum FutureFeature {
|
||||
DIVISION("division", LanguageLevel.PYTHON24, LanguageLevel.PYTHON30), // actually since 2.2
|
||||
ABSOLUTE_IMPORT("absolute_import", LanguageLevel.PYTHON25, LanguageLevel.PYTHON30),
|
||||
PRINT_FUNCTION("print_function", LanguageLevel.PYTHON26, LanguageLevel.PYTHON30),
|
||||
UNICODE_LITERALS("unicode_literals", LanguageLevel.PYTHON26, LanguageLevel.PYTHON30),
|
||||
ANNOTATIONS("annotations", LanguageLevel.PYTHON37, LanguageLevel.PYTHON312)
|
||||
// NOTE: only add new features to the end unless you want to break existing stubs that rely on ordinal
|
||||
;
|
||||
|
||||
@NotNull
|
||||
private final String myName;
|
||||
|
||||
@NotNull
|
||||
private final LanguageLevel myOptionalVersion;
|
||||
|
||||
@NotNull
|
||||
private final LanguageLevel myRequiredVersion;
|
||||
|
||||
/**
|
||||
* @param name what is imported from __future__
|
||||
* @param proposed version in which the feature has become importable
|
||||
* @param included version in which the feature is included by default
|
||||
*/
|
||||
FutureFeature(@NotNull String name, @NotNull LanguageLevel proposed, @NotNull LanguageLevel included) {
|
||||
myName = name;
|
||||
myOptionalVersion = proposed;
|
||||
myRequiredVersion = included;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the Python importable name of the feature.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true iff the feature can either be imported from __future__ at given level, or is already built-in.
|
||||
*/
|
||||
public boolean availableAt(@NotNull LanguageLevel level) {
|
||||
return level.isAtLeast(myOptionalVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true iff the feature is already present (required) at given level, and there's no need to import it.
|
||||
*/
|
||||
public boolean requiredAt(@NotNull LanguageLevel level) {
|
||||
return level.isAtLeast(myRequiredVersion);
|
||||
}
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
// Copyright 2000-2021 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.psi;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
public enum LanguageLevel {
|
||||
|
||||
/**
|
||||
* @apiNote This level is not supported since 2018.1.
|
||||
*/
|
||||
PYTHON24(204),
|
||||
/**
|
||||
* @apiNote This level is not supported since 2018.1.
|
||||
*/
|
||||
PYTHON25(205),
|
||||
/**
|
||||
* @apiNote This level is not supported since 2019.1.
|
||||
*/
|
||||
PYTHON26(206),
|
||||
PYTHON27(207),
|
||||
/**
|
||||
* @apiNote This level is not supported since 2018.1.
|
||||
* Use it only to distinguish Python 2 and Python 3.
|
||||
* Consider using {@link LanguageLevel#isPython2()}.
|
||||
* Replace {@code level.isOlderThan(PYTHON30)} with {@code level.isPython2()}
|
||||
* and {@code level.isAtLeast(PYTHON30)} with {@code !level.isPython2()}.
|
||||
*/
|
||||
PYTHON30(300),
|
||||
/**
|
||||
* @apiNote This level is not supported since 2018.1.
|
||||
*/
|
||||
PYTHON31(301),
|
||||
/**
|
||||
* @apiNote This level is not supported since 2018.1.
|
||||
*/
|
||||
PYTHON32(302),
|
||||
/**
|
||||
* @apiNote This level is not supported since 2018.1.
|
||||
*/
|
||||
PYTHON33(303),
|
||||
/**
|
||||
* @apiNote This level is not supported since 2019.1.
|
||||
*/
|
||||
PYTHON34(304),
|
||||
/**
|
||||
* @apiNote This level is not supported since 2020.3.
|
||||
*/
|
||||
PYTHON35(305),
|
||||
PYTHON36(306),
|
||||
PYTHON37(307),
|
||||
PYTHON38(308),
|
||||
PYTHON39(309),
|
||||
PYTHON310(310),
|
||||
PYTHON311(311),
|
||||
PYTHON312(312);
|
||||
|
||||
public static final Comparator<LanguageLevel> VERSION_COMPARATOR = (first, second) -> {
|
||||
return first == second ? 0 : first.isOlderThan(second) ? -1 : 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* This value is mostly bound to the compatibility of our debugger and helpers.
|
||||
* You're free to gradually drop support of versions not mentioned here if they present too much hassle to maintain.
|
||||
*/
|
||||
public static final List<LanguageLevel> SUPPORTED_LEVELS =
|
||||
Stream
|
||||
.of(values())
|
||||
.filter(v -> v.isAtLeast(PYTHON36) || v == PYTHON27)
|
||||
.toList();
|
||||
|
||||
private static final LanguageLevel DEFAULT2 = PYTHON27;
|
||||
private static final LanguageLevel DEFAULT3 = PYTHON310;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static LanguageLevel FORCE_LANGUAGE_LEVEL = null;
|
||||
|
||||
@NotNull
|
||||
public static LanguageLevel getDefault() {
|
||||
return getLatest();
|
||||
}
|
||||
|
||||
private final int myVersion;
|
||||
|
||||
LanguageLevel(int version) {
|
||||
myVersion = version;
|
||||
}
|
||||
|
||||
public int getMajorVersion() {
|
||||
return myVersion / 100;
|
||||
}
|
||||
|
||||
public int getMinorVersion() {
|
||||
return myVersion % 100;
|
||||
}
|
||||
|
||||
public boolean hasPrintStatement() {
|
||||
return isPython2();
|
||||
}
|
||||
|
||||
public boolean isPython2() {
|
||||
return getMajorVersion() == 2;
|
||||
}
|
||||
|
||||
public boolean isPy3K() {
|
||||
return getMajorVersion() == 3;
|
||||
}
|
||||
|
||||
public boolean isOlderThan(@NotNull LanguageLevel other) {
|
||||
return myVersion < other.myVersion;
|
||||
}
|
||||
|
||||
public boolean isAtLeast(@NotNull LanguageLevel other) {
|
||||
return myVersion >= other.myVersion;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Contract("null->null;!null->!null")
|
||||
public static LanguageLevel fromPythonVersion(@Nullable String pythonVersion) {
|
||||
if (pythonVersion == null) return null;
|
||||
|
||||
if (pythonVersion.startsWith("2")) {
|
||||
if (pythonVersion.startsWith("2.4")) {
|
||||
return PYTHON24;
|
||||
}
|
||||
if (pythonVersion.startsWith("2.5")) {
|
||||
return PYTHON25;
|
||||
}
|
||||
if (pythonVersion.startsWith("2.6")) {
|
||||
return PYTHON26;
|
||||
}
|
||||
if (pythonVersion.startsWith("2.7")) {
|
||||
return PYTHON27;
|
||||
}
|
||||
return DEFAULT2;
|
||||
}
|
||||
if (pythonVersion.startsWith("3")) {
|
||||
if (pythonVersion.startsWith("3.0")) {
|
||||
return PYTHON30;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.1.") || pythonVersion.equals("3.1")) {
|
||||
return PYTHON31;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.2")) {
|
||||
return PYTHON32;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.3")) {
|
||||
return PYTHON33;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.4")) {
|
||||
return PYTHON34;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.5")) {
|
||||
return PYTHON35;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.6")) {
|
||||
return PYTHON36;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.7")) {
|
||||
return PYTHON37;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.8")) {
|
||||
return PYTHON38;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.9")) {
|
||||
return PYTHON39;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.10")) {
|
||||
return PYTHON310;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.11")) {
|
||||
return PYTHON311;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.12")) {
|
||||
return PYTHON312;
|
||||
}
|
||||
return DEFAULT3;
|
||||
}
|
||||
return getDefault();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String toPythonVersion() {
|
||||
return getMajorVersion() + "." + getMinorVersion();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static LanguageLevel forElement(@NotNull PsiElement element) {
|
||||
return PyPsiFacade.getInstance(element.getProject()).getLanguageLevel(element);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static LanguageLevel getLatest() {
|
||||
return ArrayUtil.getLastElement(values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toPythonVersion();
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class PyElementType extends IElementType {
|
||||
@NotNull private final Function<? super ASTNode, ? extends PsiElement> myPsiCreator;
|
||||
|
||||
private final String mySpecialMethodName;
|
||||
|
||||
public PyElementType(@NotNull @NonNls String debugName) {
|
||||
super(debugName, PythonFileType.INSTANCE.getLanguage());
|
||||
myPsiCreator = node -> { throw new IllegalStateException("Cannot create an element for " + node.getElementType() + " without element class");};
|
||||
mySpecialMethodName = null;
|
||||
}
|
||||
|
||||
public PyElementType(@NotNull @NonNls String debugName, @NotNull Function<? super ASTNode, ? extends PsiElement> creator) {
|
||||
super(debugName, PythonFileType.INSTANCE.getLanguage());
|
||||
myPsiCreator = creator;
|
||||
mySpecialMethodName = null;
|
||||
}
|
||||
|
||||
public PyElementType(@NotNull @NonNls String debugName, @NotNull @NonNls String specialMethodName) {
|
||||
super(debugName, PythonFileType.INSTANCE.getLanguage());
|
||||
myPsiCreator = node -> { throw new IllegalStateException("Cannot create an element for " + node.getElementType() + " without element class");};
|
||||
mySpecialMethodName = specialMethodName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElement createElement(@NotNull ASTNode node) {
|
||||
return myPsiCreator.apply(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return name of special method for operation marked by this token; e.g. "__add__" for "+".
|
||||
*/
|
||||
@Nullable
|
||||
public String getSpecialMethodName() {
|
||||
return mySpecialMethodName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Py:" + super.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.psi;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PyStringLiteralCoreUtil {
|
||||
/**
|
||||
* Valid string prefix characters (lowercased) as defined in Python lexer.
|
||||
*/
|
||||
public static final String PREFIX_CHARACTERS = "ubcrf";
|
||||
|
||||
/**
|
||||
* Maximum length of a string prefix as defined in Python lexer.
|
||||
*/
|
||||
public static final int MAX_PREFIX_LENGTH = 3;
|
||||
|
||||
private static final ImmutableList<String> QUOTES = ImmutableList.of("'''", "\"\"\"", "'", "\"");
|
||||
|
||||
protected PyStringLiteralCoreUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pair where the first element is the prefix combined with the opening quote and the second is the closing quote.
|
||||
* <p>
|
||||
* If the given string literal is not properly quoted, e.g. the closing quote has fewer quotes as opposed to the
|
||||
* opening one, or it's missing altogether this method returns null.
|
||||
* <p>
|
||||
* Examples:
|
||||
* <pre>
|
||||
* ur"foo" -> ("ur, ")
|
||||
* ur'bar -> null
|
||||
* """baz""" -> (""", """)
|
||||
* '''quux' -> null
|
||||
* </pre>
|
||||
*/
|
||||
@Nullable
|
||||
public static Pair<String, String> getQuotes(@NotNull String text) {
|
||||
final String prefix = getPrefix(text);
|
||||
final String mainText = text.substring(prefix.length());
|
||||
for (String quote : QUOTES) {
|
||||
final Pair<String, String> quotes = getQuotes(mainText, prefix, quote);
|
||||
if (quotes != null) {
|
||||
return quotes;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the end offset of the string prefix starting from {@code startOffset} in the given char sequence.
|
||||
* String prefix may contain only up to {@link #MAX_PREFIX_LENGTH} characters from {@link #PREFIX_CHARACTERS}
|
||||
* (case insensitively).
|
||||
*
|
||||
* @return end offset of found string prefix
|
||||
*/
|
||||
public static int getPrefixEndOffset(@NotNull CharSequence text, int startOffset) {
|
||||
int offset;
|
||||
for (offset = startOffset; offset < Math.min(startOffset + MAX_PREFIX_LENGTH, text.length()); offset++) {
|
||||
if (PREFIX_CHARACTERS.indexOf(Character.toLowerCase(text.charAt(offset))) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getPrefix(@NotNull CharSequence text) {
|
||||
return getPrefix(text, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts string prefix from the given char sequence using {@link #getPrefixEndOffset(CharSequence, int)}.
|
||||
*
|
||||
* @return extracted string prefix
|
||||
* @see #getPrefixEndOffset(CharSequence, int)
|
||||
*/
|
||||
@NotNull
|
||||
public static String getPrefix(@NotNull CharSequence text, int startOffset) {
|
||||
return text.subSequence(startOffset, getPrefixEndOffset(text, startOffset)).toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Pair<String, String> getQuotes(@NotNull String text, @NotNull String prefix, @NotNull String quote) {
|
||||
final int length = text.length();
|
||||
final int n = quote.length();
|
||||
if (length >= 2 * n && text.startsWith(quote) && text.endsWith(quote)) {
|
||||
return Pair.create(prefix + text.substring(0, n), text.substring(length - n));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String stripQuotesAroundValue(String text) {
|
||||
Pair<String, String> quotes = getQuotes(text);
|
||||
if (quotes == null) {
|
||||
return text;
|
||||
}
|
||||
|
||||
return text.substring(quotes.first.length(), text.length() - quotes.second.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles unicode and raw strings
|
||||
*
|
||||
* @return false if no quotes found, true otherwise
|
||||
* sdfs -> false
|
||||
* ur'x' -> true
|
||||
* "string" -> true
|
||||
*/
|
||||
|
||||
public static boolean isQuoted(@Nullable String text) {
|
||||
return text != null && getQuotes(text) != null;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -721,6 +722,29 @@ public final class PyPsiUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getStringValue(@Nullable PsiElement o) {
|
||||
if (o == null) {
|
||||
return null;
|
||||
}
|
||||
if (o instanceof PyStringLiteralExpression literalExpression) {
|
||||
return literalExpression.getStringValue();
|
||||
}
|
||||
else {
|
||||
return o.getText();
|
||||
}
|
||||
}
|
||||
|
||||
public static TextRange getStringValueTextRange(PsiElement element) {
|
||||
if (element instanceof PyStringLiteralExpression) {
|
||||
final List<TextRange> ranges = ((PyStringLiteralExpression)element).getStringValueTextRanges();
|
||||
return ranges.get(0);
|
||||
}
|
||||
else {
|
||||
return new TextRange(0, element.getTextLength());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiComment findSameLineComment(@NotNull PsiElement elem) {
|
||||
// If `elem` is a compound multi-line element, stick to its first line nonetheless
|
||||
|
||||
Reference in New Issue
Block a user