Skip to content

Commit

Permalink
Finish opaque type declatation.
Browse files Browse the repository at this point in the history
  • Loading branch information
HairyRabbit committed Dec 25, 2017
1 parent e83eab8 commit 6431b70
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 30 deletions.
90 changes: 70 additions & 20 deletions js2-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -5349,6 +5349,49 @@ For a simple name, the kids list has exactly one node, a `js2-name-node'."
(js2-print-ast bindings 0)
(insert ";")))

(cl-defstruct (js2-opaque-type-alias-node
(:include js2-node)
(:constructor make-js2-opaque-type-alias-node (&key (type js2-INTERFACE)
(pos js2-ts-cursor)
name
len bindings
type-params
subtyping)))
"AST node for an opaque-type-alias declaration."
name ; opaque-type-alias name (a `js2-node-name', or nil if anonymous)
type-params ; exnteds expr wrap a parens
bindings
subtyping)

(js2--struct-put 'js2-opaque-type-alias-node 'js2-visitor 'js2-visit-opaque-type-alias-node)
(js2--struct-put 'js2-opaque-type-alias-node 'js2-printer 'js2-print-opaque-type-alias-node)

(defun js2-visit-opaque-type-alias-node (n v)
(js2-visit-ast (js2-opaque-type-alias-node-name n) v)
(js2-visit-ast (js2-opaque-type-alias-node-extends n) v)
(dolist (e (js2-opaque-type-alias-node-bindings n))
(js2-visit-ast e v)))

(defun js2-print-opaque-type-alias-node (n i)
(let* ((pad (js2-make-pad i))
(name (js2-opaque-type-alias-node-name n))
(bindings (js2-opaque-type-alias-node-bindings n))
(tp (js2-opaque-type-alias-node-type-params n))
(subtyping (js2-opaque-type-alias-node-subtyping n)))
(insert pad "opaque type")
(when name
(insert " ")
(js2-print-ast name 0))
(when tp
(when (not name)
(insert " "))
(js2-print-ast tp 0))
(when subtyping
(js2-print-ast subtyping 0))
(insert " = ")
(js2-print-ast bindings 0)
(insert ";")))

;;; Node utilities

(defsubst js2-node-line (n)
Expand Down Expand Up @@ -9388,6 +9431,7 @@ node are given relative start positions and correct lengths."
(aset parsers js2-YIELD #'js2-parse-ret-yield)
(aset parsers js2-INTERFACE #'js2-parse-interface)
(aset parsers js2-TYPE #'js2-parse-type-alias)
(aset parsers js2-OPAQUE #'js2-parse-opaque-type-alias)
parsers)
"A vector mapping token types to parser functions.")

Expand Down Expand Up @@ -12596,7 +12640,7 @@ And, if CHECK-ACTIVATION-P is non-nil, use the value of TOKEN."
(setq optional t)))
(let ((next-tt (js2-get-token)))
(cond
((= next-tt js2-LP) ; match a(
((= next-tt js2-LP) ; match a(
(setq value (js2-parse-function-type t)))
((= next-tt js2-COLON)
(if (or (= (js2-peek-token) js2-COMMA) ; match {a:,
Expand Down Expand Up @@ -12768,23 +12812,6 @@ And, if CHECK-ACTIVATION-P is non-nil, use the value of TOKEN."
(setq kind nil))))
(if kind curr-tt nil)))

(defun js2-parse-interface ()
(let ((pos (js2-current-token-beg))
(_ (js2-must-match-name "msg.unnamed.interface.decl"))
(name (js2-create-name-node t))
type-params)
(js2-set-face (js2-node-pos name) (js2-node-end name)
'font-lock-function-name-face 'record)
;; parse type params after name, e.g. class a<T>
(when (= (js2-peek-token) js2-LT)
(setq type-params (js2-parse-type-params)))
(js2-must-match js2-LC "msg.syntax")
(make-js2-interface-node :pos pos
:len (- (js2-current-token-end) pos)
:name name
:type-params type-params
:elems (js2-parse-object-type js2-LT))))

(defun js2-parse-interface ()
"Parse interface declatation, e.g. interface a<b> {}"
(let ((pos (js2-current-token-beg))
Expand All @@ -12793,7 +12820,7 @@ And, if CHECK-ACTIVATION-P is non-nil, use the value of TOKEN."
type-params)
(js2-set-face (js2-node-pos name) (js2-node-end name)
'font-lock-function-name-face 'record)
;; parse type params after name, e.g. class a<T>
;; parse type params after name, e.g. interface a<T>
(when (= (js2-peek-token) js2-LT)
(setq type-params (js2-parse-type-params)))
(js2-must-match js2-LC "msg.syntax")
Expand All @@ -12811,7 +12838,7 @@ And, if CHECK-ACTIVATION-P is non-nil, use the value of TOKEN."
type-params)
(js2-set-face (js2-node-pos name) (js2-node-end name)
'font-lock-function-name-face 'record)
;; parse type params after name, e.g. class a<T>
;; parse type params after name, e.g. type a<T>
(when (= (js2-peek-token) js2-LT)
(setq type-params (js2-parse-type-params)))
(js2-must-match js2-ASSIGN "msg.syntax")
Expand All @@ -12821,6 +12848,29 @@ And, if CHECK-ACTIVATION-P is non-nil, use the value of TOKEN."
:type-params type-params
:bindings (js2-create-type-node t))))

(defun js2-parse-opaque-type-alias ()
"Parse type alias declatation, e.g. opaque type a<b> = c"
(let ((pos (js2-current-token-beg))
(_ (js2-must-match js2-TYPE "msg.syntax"))
(_ (js2-must-match-name "msg.unnamed.type.alias.decl"))
(name (js2-create-name-node t))
type-params subtyping)
(js2-set-face (js2-node-pos name) (js2-node-end name)
'font-lock-function-name-face 'record)
;; parse type params after name, e.g. opaque type a<T>
(when (= (js2-peek-token) js2-LT)
(setq type-params (js2-parse-type-params)))
(when (= (js2-peek-token) js2-COLON)
(setq subtyping (js2-parse-type-annotation)))
;; TODO error pos and msg
(js2-must-match js2-ASSIGN "msg.syntax")
(make-js2-opaque-type-alias-node :pos pos
:len (- (js2-current-token-end) pos)
:name name
:type-params type-params
:bindings (js2-create-type-node t)
:subtyping subtyping)))

;;; Use AST to extract semantic information

(defun js2-get-element-index-from-array-node (elem array-node &optional hardcoded-array-index)
Expand Down
22 changes: 12 additions & 10 deletions tests/flow.el
Original file line number Diff line number Diff line change
Expand Up @@ -956,25 +956,27 @@ the test."
(js2-deftest-parse type-alias
"type a = b;")

;; (js2-deftest-parse type-alias-with-type-params
;; "type a<b> = c;")
(js2-deftest-parse type-alias-with-type-params
"type a<b> = c;")

;; (js2-deftest-parse type-alias-with-export
;; "export type a<b> = c;")

;; Opaque type aliases

;; (js2-deftest-parse opaque-type-alias
;; "opaque type a = b;")
(js2-deftest-parse opaque-type-alias
"opaque type a = b;")

;; (js2-deftest-parse opaque-type-alias-with-type-params
;; "opaque type a<b> = c;")
(js2-deftest-parse opaque-type-alias-with-type-params
"opaque type a<b> = c;")

;; (js2-deftest-parse opaque-type-subtype
;; "opaque type a: b;")
(js2-deftest-parse opaque-type-subtyping
"opaque type a<b>: c = d;")

;; (js2-deftest-parse opaque-type-subtype-binding
;; "opaque type a: b = c;")
(js2-deftest-parse opaque-type-subtyping-no-binding
"opaque type a: b;"
:syntax-error ";"
:errors-count 2)

;; (js2-deftest-parse opaque-type-alias-with-export
;; "export opaque type a<b> = c;")
Expand Down

0 comments on commit 6431b70

Please sign in to comment.