Finally, documentation for table.insert
This commit is contained in:
parent
308f7d9930
commit
0a766c6425
File diff suppressed because it is too large
Load Diff
@ -99,17 +99,17 @@ fntype is one of fn or λ or lambda"
|
||||
:Snippet 15 :Color 16 :File 17 :Reference 18 :Folder 19 :EnumMember 20
|
||||
:Constant 21 :Struct 22 :Event 23 :Operator 24 :TypeParameter 25})
|
||||
|
||||
(λ completion-item-format [label def]
|
||||
(λ completion-item-format [label result]
|
||||
"Makes a completion item"
|
||||
(doto
|
||||
(case (analyze-fn def.definition)
|
||||
(case (analyze-fn result.definition)
|
||||
{:fntype _} {: label
|
||||
:kind (if (label:find ":") kinds.Method kinds.Function)
|
||||
:textEdit {:newText label}}
|
||||
_ {: label
|
||||
:kind kinds.Variable
|
||||
:textEdit {:newText label}})
|
||||
(tset :documentation (hover-format def))))
|
||||
(tset :documentation (hover-format result))))
|
||||
|
||||
{: hover-format
|
||||
: completion-item-format}
|
||||
|
||||
@ -78,7 +78,7 @@ Every time the client sends a message, it gets handled by a function in the corr
|
||||
(. file.require-calls parent)
|
||||
(language.search-ast self file parent [] {:stop-early? true})
|
||||
;; regular symbol
|
||||
(language.search-main self file symbol {:stop-early? true} byte))
|
||||
(language.search-main self file symbol {:stop-early? true} {: byte}))
|
||||
result
|
||||
(if result.file
|
||||
(message.range-and-uri self result.file (or result.binding result.definition)))
|
||||
@ -107,7 +107,7 @@ Every time the client sends a message, it gets handled by a function in the corr
|
||||
(let [file (state.get-by-uri self uri)
|
||||
byte (utils.position->byte file.text position self.position-encoding)]
|
||||
(case-try (language.find-symbol file.ast byte)
|
||||
symbol (language.search-main self file symbol {} byte)
|
||||
symbol (language.search-main self file symbol {} {: byte})
|
||||
result {:contents (formatter.hover-format result)
|
||||
:range (message.ast->range self file symbol)}
|
||||
(catch _ nil))))
|
||||
@ -153,31 +153,32 @@ Every time the client sends a message, it gets handled by a function in the corr
|
||||
(make-completion-item self file k scope))))
|
||||
|
||||
(λ field-completion [self file symbol split]
|
||||
(case (. file.references symbol)
|
||||
ref
|
||||
(let [stack (fcollect [i (- (length split) 1) 2 -1]
|
||||
(. split i))
|
||||
last-found-binding []]
|
||||
(case (language.search-assignment self file ref stack {:save-last-binding last-found-binding})
|
||||
{: definition : file}
|
||||
(case (values definition (type definition))
|
||||
;; fields of a string are hardcoded to "string"
|
||||
(_str :string) (icollect [label _ (pairs string)]
|
||||
{: label :kind kinds.Field :textEdit {:newText label}})
|
||||
;; fields of a table
|
||||
(tbl :table) (let [keys []]
|
||||
(icollect [label _ (pairs tbl) &into keys]
|
||||
label)
|
||||
(when (?. last-found-binding 1 :fields)
|
||||
(icollect [label _ (pairs (. last-found-binding 1 :fields)) &into keys]
|
||||
label))
|
||||
(icollect [_ label (pairs keys)]
|
||||
(if (= (type label) :string)
|
||||
(case (language.search-ast self file tbl [label] {})
|
||||
def (formatter.completion-item-format label def)
|
||||
_ {: label :kind kinds.Field :textEdit {:newText label}})))))
|
||||
|
||||
_ nil))))
|
||||
(let [stack (fcollect [i (- (length split) 1) 2 -1]
|
||||
(. split i))
|
||||
last-found-binding []
|
||||
result (language.search-main self file symbol {:save-last-binding last-found-binding} {: stack})]
|
||||
(case result
|
||||
{: definition : file}
|
||||
(case (values definition (type definition))
|
||||
;; fields of a string are hardcoded to "string"
|
||||
(_str :string) (icollect [label _ (pairs string)]
|
||||
{: label :kind kinds.Field :textEdit {:newText label}})
|
||||
;; fields of a table
|
||||
(tbl :table) (let [keys []]
|
||||
(icollect [label _ (pairs tbl) &into keys]
|
||||
label)
|
||||
(when (?. last-found-binding 1 :fields)
|
||||
(icollect [label _ (pairs (. last-found-binding 1 :fields)) &into keys]
|
||||
label))
|
||||
(icollect [_ label (pairs keys)]
|
||||
(if (= (type label) :string)
|
||||
(case (language.search-ast self file tbl [label] {})
|
||||
def (formatter.completion-item-format label def)
|
||||
_ {: label :kind kinds.Field :textEdit {:newText label}})))))
|
||||
{: metadata : fields}
|
||||
(icollect [label info (pairs fields)]
|
||||
(formatter.completion-item-format label info))
|
||||
_ nil)))
|
||||
|
||||
(λ requests.textDocument/completion [self send {: position :textDocument {: uri}}]
|
||||
(let [file (state.get-by-uri self uri)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
"Language
|
||||
This module is for searching through the data provided by compiler.fnl. It
|
||||
provides functions to search through a file.
|
||||
This module is for searching through the data provided by compiler.fnl.
|
||||
It searches through a file to find information about symbols that appear
|
||||
in the file.
|
||||
|
||||
Imagine you have the following code.
|
||||
```fnl
|
||||
@ -23,18 +24,18 @@ The search failed, and encountered something that isn't implemented.
|
||||
# A definition: `{:definition _ :file _}`
|
||||
The search succeeded and found a file with a user definition of a value.
|
||||
|
||||
# A binding: `{:definition _ :file _ :binding _ :multival ?_ :keys ?_ :referenced-by ?_ :var? ?true :fields ?extra_fields}`
|
||||
# A document: `{:metadata {:fnl/docstring _ :fnl/arglist ?_} :fields ?{<key> <document>}}`
|
||||
A document is a definition that doesn't come from user code. For example,
|
||||
searching `table.insert` will find a document, but that info does not come from
|
||||
a user-written file.
|
||||
|
||||
# A binding (if opts.stop-early?): `{:definition _ :file _ :binding _ :multival ?_ :keys ?_ :referenced-by ?_ :var? ?true :fields ?extra_fields}`
|
||||
If you set the option `opts.stop-early?`, search may stop at a binding instead
|
||||
of a true definition. A binding is a place where an identifier gets introduced.
|
||||
|
||||
In the code example above, a search on the final symbol `z` would normally
|
||||
find the definition `10`, but if `opts.stop-early?` is set, it would find
|
||||
{:binding z :definition y}, referring to the `(local z y)` binding.
|
||||
|
||||
# A document: `{:metadata {:fnl/docstring _ :fnl/arglist ?_ :fnl-ls/fields ?_}}`
|
||||
A document is a definition that doesn't come from user code. For example,
|
||||
searching `table.insert` will find a document, but that info does not come from
|
||||
a user-written file.
|
||||
"
|
||||
|
||||
(local {: sym? : list? : sequence? : varg? : sym} (require :fennel))
|
||||
@ -155,17 +156,24 @@ a user-written file.
|
||||
nil)))
|
||||
|
||||
|
||||
(λ search-main [self file symbol opts ?byte]
|
||||
;; the options thing is getting out of hand
|
||||
(λ search-main [self file symbol opts initialization-opts]
|
||||
"Find the definition of a symbol"
|
||||
|
||||
(assert (= (type initialization-opts) :table))
|
||||
;; The stack is the multi-sym parts still to search
|
||||
;; for example, if I'm searching for "foo.bar.baz", my immediate priority is to find foo,
|
||||
;; and the stack has ["baz" "bar"]. "bar" is at the "top"/"end" of the stack as the next key to search.
|
||||
(if (sym? symbol)
|
||||
(let [split (utils.multi-sym-split symbol (if ?byte (- ?byte symbol.bytestart)))
|
||||
stack (stack-add-split! [] split)]
|
||||
(let [stack
|
||||
(if initialization-opts.stack
|
||||
initialization-opts.stack
|
||||
(let [?byte initialization-opts.byte
|
||||
split (utils.multi-sym-split symbol (if ?byte (- ?byte symbol.bytestart)))]
|
||||
(stack-add-split! [] split)))]
|
||||
|
||||
(case (docs.get-global-metadata (. split 1))
|
||||
document (search-document self document (stack-add-split! stack split) opts)
|
||||
(case (docs.get-global-metadata (utils.multi-sym-base symbol))
|
||||
document (search-document self document stack opts)
|
||||
_ (case (. file.references symbol)
|
||||
ref (search-assignment self file ref stack opts)
|
||||
_ (case (. file.definitions symbol)
|
||||
@ -247,7 +255,7 @@ a user-written file.
|
||||
(λ find-nearest-definition [self file symbol ?byte]
|
||||
(if (. file.definitions symbol)
|
||||
(. file.definitions symbol)
|
||||
(search-main self file symbol {:stop-early? true} ?byte)))
|
||||
(search-main self file symbol {:stop-early? true} {:byte ?byte})))
|
||||
|
||||
{: find-symbol
|
||||
: find-nearest-definition
|
||||
|
||||
@ -158,6 +158,15 @@ WARNING: this is only used in the test code, not in the real language server"
|
||||
(icollect [word (: (.. symbol ".") :gmatch "(.-)[.:]")]
|
||||
word))))
|
||||
|
||||
(fn multi-sym-base [symbol]
|
||||
(if (or (= symbol ".")
|
||||
(= symbol "..")
|
||||
(= symbol "...")
|
||||
(= symbol ":")
|
||||
(= symbol "?."))
|
||||
(tostring symbol)
|
||||
(pick-values 1 (: (tostring symbol) :match "[^.:]*"))))
|
||||
|
||||
(λ type= [val typ]
|
||||
(= (type val) typ))
|
||||
|
||||
@ -184,6 +193,7 @@ WARNING: this is only used in the test code, not in the real language server"
|
||||
: apply-changes
|
||||
: apply-edits
|
||||
: multi-sym-split
|
||||
: multi-sym-base
|
||||
: get-ast-info
|
||||
: uniq-by
|
||||
: type=
|
||||
|
||||
@ -191,6 +191,21 @@
|
||||
|
||||
nil)
|
||||
|
||||
(fn test-module []
|
||||
(check "(coroutine.y|"
|
||||
[{:label "yield"
|
||||
:documentation #(and $.value ($.value:find "```fnl\n(yield ...)\n```" 1 true))}]
|
||||
["coroutine" "_G" "do"
|
||||
{:documentation #(= nil $)}])
|
||||
(check "(local c coroutine)
|
||||
(c.y"
|
||||
[{:label "yield"}]
|
||||
["coroutine" "_G" "do"])
|
||||
(check "(local t table)
|
||||
(t.i"
|
||||
["insert"]
|
||||
[{:documentation #(= nil $)}])
|
||||
nil)
|
||||
;; ;; Future tests / features
|
||||
;; ;; Scope Ordering Rules
|
||||
;; (it "does not suggest locals past the suggestion location when a symbol is partially typed")
|
||||
@ -221,4 +236,5 @@
|
||||
: test-local-in-macro
|
||||
: test-fn-arg
|
||||
: test-field
|
||||
: test-docs}
|
||||
: test-docs
|
||||
: test-module}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user