Skip to content

Commit

Permalink
[Python] Add support for generics (#3799)
Browse files Browse the repository at this point in the history
Resolves #3793

This commit adds support for PEP 695 and 698.
  • Loading branch information
deathaxe authored Aug 14, 2023
1 parent 5df0b69 commit 26ce896
Show file tree
Hide file tree
Showing 2 changed files with 339 additions and 9 deletions.
144 changes: 135 additions & 9 deletions Python/Python.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,14 @@ variables:
# | buffer | file
)\b
typing_functions: |-
(?x:
assert_type | assert_never | clear_overloads | dataclass_transform | final
| get_args | get_origin | get_overloads | get_type_hints | is_typeddict
| no_type_check | no_type_check_decorator | overload | override | reveal_type
| runtime_checkable
)\b
typing_types: |-
(?x:
# Super-special typing primitives.
Expand Down Expand Up @@ -255,6 +263,8 @@ variables:
| bases | prepare | slots | metaclass | mro
# Python 2
| members | methods
# Python 3.12 (PEP 698)
| override
)__\b )
##############################################################################
Expand All @@ -271,6 +281,7 @@ contexts:
- include: block-statements
- include: class-definitions
- include: function-definitions
- include: type-definitions
- include: statement-terminators
- include: expression-as-a-statement

Expand Down Expand Up @@ -738,24 +749,28 @@ contexts:

class-definitions:
- match: ^\s*(class)\b
scope: meta.class.python
captures:
1: keyword.declaration.class.python
push: class-definition-name
push:
- class-definition-base-list
- type-parameter-list
- class-definition-name

class-definition-name:
- meta_scope: meta.class.python
- match: (?=\()
set: class-definition-base-list
- include: illegal-names
- include: illegal-name
- match: '{{identifier}}'
scope: entity.name.class.python
pop: 1
- include: class-definition-end

class-definition-base-list:
- meta_include_prototype: false
- meta_content_scope: meta.class.python
- match: \(
scope: punctuation.section.inheritance.begin.python
set: class-definition-base-list-body
- include: class-definition-end

class-definition-base-list-body:
- meta_scope: meta.class.inheritance.python
Expand Down Expand Up @@ -805,25 +820,30 @@ contexts:
captures:
1: keyword.declaration.async.python
2: keyword.declaration.function.python
push: function-definition-name
push:
- function-parameter-list
- type-parameter-list
- function-definition-name

function-definition-name:
- meta_content_scope: meta.function.python
- include: function-parameter-list
- include: illegal-names
- include: illegal-name
- match: '{{magic_functions}}'
scope: entity.name.function.python support.function.magic.python
pop: 1
- match: '{{identifier}}'
scope: entity.name.function.python
pop: 1
- include: function-definition-end

function-parameter-list:
- meta_include_prototype: false
- meta_content_scope: meta.function.python
- match: \(
scope: meta.function.parameters.python punctuation.section.parameters.begin.python
set:
- function-parameter-list-body
- function-parameter-allow-unpack-operators
- include: function-definition-end

function-parameter-list-body:
- meta_content_scope: meta.function.parameters.python
Expand Down Expand Up @@ -1006,6 +1026,110 @@ contexts:
- include: line-continuation-or-pop
- include: illegal-assignment-expressions

###[ TYPE DEFINITIONS ]#######################################################

type-definitions:
- match: ^\s*(type)\b
captures:
1: keyword.declaration.class.python
push:
- type-definition-meta
- type-definition-value-assignment
- type-parameter-list
- type-definition-name

type-definition-meta:
- meta_include_prototype: false
- meta_scope: meta.type-alias.python
- include: immediately-pop

type-definition-name:
- include: illegal-name
- match: '{{identifier}}'
scope: entity.name.type.alias.python
pop: 1
- include: line-continuation-or-pop

type-definition-value-assignment:
- match: =
scope: keyword.operator.assignment.python
set: variable-annotation
- include: line-continuation-or-pop

###[ TYPE PARAMETERS ]########################################################

type-parameter-lists:
- match: \[
scope: meta.generic.python punctuation.definition.generic.begin.python
push:
- type-parameter-list-body
- allow-unpack-operators

type-parameter-list:
- match: \[
scope: meta.generic.python punctuation.definition.generic.begin.python
set:
- type-parameter-list-body
- allow-unpack-operators
- include: line-continuation-or-pop
- include: else-pop

type-parameter-list-body:
- meta_content_scope: meta.generic.python
- match: \]
scope: meta.generic.python punctuation.section.parameters.end.python
pop: 1
- match: ','
scope: punctuation.separator.parameters.python
push: allow-unpack-operators
- match: '{{colon}}'
scope: meta.generic.python punctuation.separator.bound.python
set: type-parameter-bound
- include: comments
- include: illegal-names
- match: '{{identifier}}'
scope: variable.parameter.type.python
- include: line-continuations

type-parameter-bound:
- meta_include_prototype: false
- meta_content_scope: meta.generic.bound.python
- include: line-continuations
- match: (?=\S)
set: type-parameter-bound-body

type-parameter-bound-body:
- meta_scope: meta.generic.bound.python
- meta_content_scope: meta.type.python
- match: \s*(?=[],=])
set: type-parameter-list-body
# Scope newline `meta.type` only, if type continues on next line.
# Note: This is required to workaround ST's line blindness.
- match: (?=\s*\n)
branch_point: type-parameter-bound-end
branch:
- type-parameter-bound-continue
- type-parameter-bound-end
- include: type-parameter-bound-content

type-parameter-bound-content:
# Note: maybe type-hint expressions
- include: type-constants
- include: expression-in-a-group

type-parameter-bound-continue:
- meta_include_prototype: false
- match: \s*(?=[],=])
fail: type-parameter-bound-end
- include: comments
- include: else-pop

type-parameter-bound-end:
- meta_include_prototype: false
- match: ''
pop: 2
push: type-parameter-list-body

###[ ASSIGNMENT STATEMENTS ]##################################################

assignment-statements:
Expand Down Expand Up @@ -2190,6 +2314,8 @@ contexts:
builtin-functions:
- match: '{{builtin_functions}}'
scope: support.function.builtin.python
- match: '{{typing_functions}}'
scope: support.function.typing.python

builtin-types:
- match: '{{builtin_types}}'
Expand Down
Loading

0 comments on commit 26ce896

Please sign in to comment.