;; From tree-sitter-python licensed under MIT License
; Copyright (c) 2016 Max Brunsfeld

; Variables
(identifier) @variable

; Reset highlighting in f-string interpolations
(interpolation) @none

;; Identifier naming conventions
((identifier) @type
 (#lua-match? @type "^[A-Z].*[a-z]"))
((identifier) @constant
 (#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))

((identifier) @constant.builtin
 (#lua-match? @constant.builtin "^__[a-zA-Z0-9_]*__$"))

((identifier) @constant.builtin
 (#any-of? @constant.builtin
           ;; https://docs.python.org/3/library/constants.html
           "Ellipsis"
           "quit"
           "exit"
           "copyright"
           "credits"
           "license"))

((attribute
    attribute: (identifier) @field)
 (#match? @field "^([A-Z])@!.*$"))

; Function calls

(decorator) @function
((decorator (attribute (identifier) @function))
 (#match? @function "^([A-Z])@!.*$"))
(decorator) @function
((decorator (identifier) @function)
 (#match? @function "^([A-Z])@!.*$"))

(call
  function: (identifier) @function.call)

(call
  function: (attribute
              attribute: (identifier) @method.call))

((call
   function: (identifier) @constructor)
 (#lua-match? @constructor "^[A-Z]"))

((call
  function: (attribute
              attribute: (identifier) @constructor))
 (#lua-match? @constructor "^[A-Z]"))

;; Builtin functions
;; $(".sig-object .sig-name span.pre").map((_, v) => `"${v.innerText}"`).toArray().sort().join(" ")

((call
  function: (identifier) @function.builtin)
 (#any-of? @function.builtin
          "_abi_decode" "_abi_encode" "abs" "as_wei_value" "bitwise_and" "bitwise_not" "bitwise_or" "bitwise_xor"
          "blockhash" "ceil" "concat" "convert" "create_copy_of" "create_from_blueprint" "create_minimal_proxy_to"
          "ecadd" "ecmul" "ecrecover" "empty" "extract32" "floor" "isqrt" "keccak256" "len" "max" "max_value"
          "method_id" "min" "min_value" "pow_mod256" "print" "raw_call" "raw_log" "selfdestruct" "send" "sha256" "shift"
          "slice" "sqrt" "uint256_addmod" "uint256_mulmod" "uint2str" "unsafe_add" "unsafe_div" "unsafe_mul"
          "unsafe_sub" "print" "indexed" "public" "constant" "immutable"))

;; Function definitions

(function_definition
  name: (identifier) @function)

(function_definition
  name: (identifier) @constructor
 (#any-of? @constructor "__init__"))

(type (identifier) @type)
(type
  (subscript
    (identifier) @type)) ; type subscript: Tuple[int]

((call
  function: (identifier) @_isinstance
  arguments: (argument_list
    (_)
    (identifier) @type))
 (#eq? @_isinstance "isinstance"))

;; Normal parameters
(parameters
  (identifier) @parameter)
;; Lambda parameters
(lambda_parameters
  (identifier) @parameter)
(lambda_parameters
  (tuple_pattern
    (identifier) @parameter))
; Default parameters
(keyword_argument
  name: (identifier) @parameter)
; Naming parameters on call-site
(default_parameter
  name: (identifier) @parameter)
(typed_parameter
  (identifier) @parameter)
(typed_default_parameter
  (identifier) @parameter)
; Variadic parameters *args, **kwargs
(parameters
  (list_splat_pattern ; *args
    (identifier) @parameter))
(parameters
  (dictionary_splat_pattern ; **kwargs
    (identifier) @parameter))


;; Literals

(none) @constant.builtin
[(true) (false)] @boolean
((identifier) @variable.builtin
 (#eq? @variable.builtin "self"))
((identifier) @variable.builtin
 (#eq? @variable.builtin "cls"))
((identifier) @variable.builtin
 (#eq? @variable.builtin "msg"))
((identifier) @variable.builtin
 (#eq? @variable.builtin "block"))

(integer) @number
(float) @float

(comment) @comment @spell

((module . (comment) @preproc)
  (#match? @preproc "^#!/"))

(string) @string
[
  (escape_sequence)
  "{{"
  "}}"
] @string.escape

; doc-strings
(expression_statement (string) @spell)

; Tokens

[
  "-"
  "-="
  "!="
  "*"
  "**"
  "**="
  "*="
  "/"
  "//"
  "//="
  "/="
  "&"
  "&="
  "%"
  "%="
  "^"
  "^="
  "+"
  "+="
  "<"
  "<<"
  "<<="
  "<="
  "<>"
  "="
  "=="
  ">"
  ">="
  ">>"
  ">>="
  "@"
  "@="
  "|"
  "|="
  "~"
  "->"
] @operator

; Keywords
[
  "and"
  "in"
  "is"
  "not"
  "or"

  "del"
] @keyword.operator

[
  "def"
  "lambda"
] @keyword.function

[
  "assert"
  "pass"
  "as"
  "log"
  "event"
  "struct"
  "interface"
] @keyword

[
  "return"
] @keyword.return

(import_from_statement "from" @include)
"import" @include

(aliased_import "as" @include)

["if" "elif" "else"] @conditional

["for" "while" "break" "continue"] @repeat

[
  "raise"
] @exception

(raise_statement "from" @exception)

["(" ")" "[" "]" "{" "}"] @punctuation.bracket

(interpolation
  "{" @punctuation.special
  "}" @punctuation.special)

["," "." ":" ";" (ellipsis)] @punctuation.delimiter

;; Event definitions

(event_definition
  body: (block
          (function_definition
            name: (identifier) @method)))

((event_definition
  body: (block
          (expression_statement
            (assignment
              left: (identifier) @field))))
 (#match? @field "^([A-Z])@!.*$"))
((event_definition
  body: (block
          (expression_statement
            (assignment
              left: (_
                     (identifier) @field)))))
 (#match? @field "^([A-Z])@!.*$"))

;; Interface definitions

(interface_definition
  body: (interface_sigs
          (interface_sig
            name: (identifier) @method)))

(interface_definition
  body: (interface_sigs
          (interface_sig
            mutability: (identifier) @keyword)))

;; Error
(ERROR) @error
