mt-lang 0.3.8 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/milk_tea/base.rb +1 -2
- data/lib/milk_tea/bindings/bindgen/ast_parser.rb +0 -2
- data/lib/milk_tea/bindings/bindgen/declaration.rb +0 -2
- data/lib/milk_tea/bindings/bindgen/emitter.rb +0 -2
- data/lib/milk_tea/bindings/bindgen/overrides.rb +0 -2
- data/lib/milk_tea/bindings/bindgen/type_mapper.rb +51 -53
- data/lib/milk_tea/bindings/imported_bindings/generator.rb +7 -9
- data/lib/milk_tea/bindings/imported_bindings/method_source.rb +0 -2
- data/lib/milk_tea/bindings/imported_bindings/naming.rb +6 -8
- data/lib/milk_tea/bindings/imported_bindings.rb +0 -2
- data/lib/milk_tea/bindings/opengl_registry.rb +3 -7
- data/lib/milk_tea/bindings/steamworks.rb +12 -16
- data/lib/milk_tea/bindings/upstream_sources.rb +10 -14
- data/lib/milk_tea/bindings/vendored_box2d.rb +10 -12
- data/lib/milk_tea/bindings/vendored_cjson.rb +6 -8
- data/lib/milk_tea/bindings/vendored_flecs.rb +10 -12
- data/lib/milk_tea/bindings/vendored_glfw.rb +11 -13
- data/lib/milk_tea/bindings/vendored_libuv.rb +11 -13
- data/lib/milk_tea/bindings/vendored_pcre2.rb +11 -13
- data/lib/milk_tea/bindings/vendored_raylib.rb +6 -10
- data/lib/milk_tea/bindings/vendored_sdl3.rb +11 -13
- data/lib/milk_tea/bindings/vendored_steamworks.rb +1 -5
- data/lib/milk_tea/core/ast.rb +103 -45
- data/lib/milk_tea/core/async_runtime_installer.rb +0 -2
- data/lib/milk_tea/core/bindings/attribute_binding.rb +1 -3
- data/lib/milk_tea/core/c_backend/aggregate_utils.rb +147 -84
- data/lib/milk_tea/core/c_backend/control_flow_emission.rb +394 -396
- data/lib/milk_tea/core/c_backend/expressions.rb +489 -476
- data/lib/milk_tea/core/c_backend/feature_detection.rb +446 -437
- data/lib/milk_tea/core/c_backend/format_helpers.rb +0 -2
- data/lib/milk_tea/core/c_backend/reachability.rb +339 -341
- data/lib/milk_tea/core/c_backend/reinterpret.rb +231 -217
- data/lib/milk_tea/core/c_backend/runtime_helpers.rb +531 -526
- data/lib/milk_tea/core/c_backend/statements.rb +528 -530
- data/lib/milk_tea/core/c_backend/type_collectors.rb +1344 -1346
- data/lib/milk_tea/core/c_backend/type_declaration.rb +215 -213
- data/lib/milk_tea/core/c_backend/type_system.rb +347 -349
- data/lib/milk_tea/core/c_backend.rb +17 -9
- data/lib/milk_tea/core/compatibility_helpers.rb +0 -2
- data/lib/milk_tea/core/compile_time/const_eval.rb +7 -12
- data/lib/milk_tea/core/compile_time.rb +32 -38
- data/lib/milk_tea/core/control_flow/builder.rb +3 -5
- data/lib/milk_tea/core/control_flow/constant_propagation.rb +14 -17
- data/lib/milk_tea/core/control_flow/definite_assignment.rb +0 -1
- data/lib/milk_tea/core/ir.rb +10 -10
- data/lib/milk_tea/core/lexer/character_classes.rb +5 -7
- data/lib/milk_tea/core/lexer/format_strings.rb +7 -9
- data/lib/milk_tea/core/lexer/heredocs.rb +22 -22
- data/lib/milk_tea/core/lexer/indentation.rb +0 -2
- data/lib/milk_tea/core/lexer/numbers.rb +0 -2
- data/lib/milk_tea/core/lexer/recovery.rb +0 -2
- data/lib/milk_tea/core/lexer/strings.rb +0 -2
- data/lib/milk_tea/core/lexer/symbols.rb +0 -2
- data/lib/milk_tea/core/lexer/trivia.rb +0 -2
- data/lib/milk_tea/core/lexer.rb +0 -2
- data/lib/milk_tea/core/lowering/async/analysis.rb +0 -2
- data/lib/milk_tea/core/lowering/async/lowering.rb +1264 -1265
- data/lib/milk_tea/core/lowering/async/normalization.rb +0 -2
- data/lib/milk_tea/core/lowering/async.rb +627 -630
- data/lib/milk_tea/core/lowering/block.rb +413 -416
- data/lib/milk_tea/core/lowering/calls.rb +1381 -1384
- data/lib/milk_tea/core/lowering/declarations.rb +180 -183
- data/lib/milk_tea/core/lowering/dyn.rb +48 -50
- data/lib/milk_tea/core/lowering/events.rb +983 -985
- data/lib/milk_tea/core/lowering/expressions.rb +1513 -1518
- data/lib/milk_tea/core/lowering/foreign_cstr.rb +181 -184
- data/lib/milk_tea/core/lowering/functions.rb +185 -188
- data/lib/milk_tea/core/lowering/loops.rb +1028 -1031
- data/lib/milk_tea/core/lowering/proc.rb +363 -366
- data/lib/milk_tea/core/lowering/resolve.rb +2133 -2135
- data/lib/milk_tea/core/lowering/scans.rb +179 -181
- data/lib/milk_tea/core/lowering/str_buffer.rb +102 -105
- data/lib/milk_tea/core/lowering/utils.rb +1040 -1044
- data/lib/milk_tea/core/lowering.rb +5 -7
- data/lib/milk_tea/core/module_binder.rb +0 -2
- data/lib/milk_tea/core/module_loader/errors.rb +4 -2
- data/lib/milk_tea/core/module_loader.rb +113 -20
- data/lib/milk_tea/core/module_path_resolver.rb +0 -2
- data/lib/milk_tea/core/module_roots.rb +6 -8
- data/lib/milk_tea/core/parser/attributes.rb +0 -2
- data/lib/milk_tea/core/parser/blocks.rb +0 -2
- data/lib/milk_tea/core/parser/declarations.rb +0 -2
- data/lib/milk_tea/core/parser/expressions.rb +31 -14
- data/lib/milk_tea/core/parser/recovery.rb +0 -2
- data/lib/milk_tea/core/parser/statements.rb +0 -2
- data/lib/milk_tea/core/parser/types.rb +8 -10
- data/lib/milk_tea/core/parser.rb +1 -3
- data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +31 -33
- data/lib/milk_tea/core/pretty_printer/base_formatter.rb +0 -2
- data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +0 -2
- data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +0 -2
- data/lib/milk_tea/core/semantic_analyzer/attributes.rb +14 -16
- data/lib/milk_tea/core/semantic_analyzer/calls.rb +0 -2
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +1 -14
- data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +18 -21
- data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +0 -3
- data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +12 -15
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +57 -59
- data/lib/milk_tea/core/semantic_analyzer/interface_conformance.rb +0 -2
- data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +5 -9
- data/lib/milk_tea/core/semantic_analyzer/nullability.rb +0 -3
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +35 -40
- data/lib/milk_tea/core/semantic_analyzer/top_level.rb +10 -12
- data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +0 -6
- data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +102 -105
- data/lib/milk_tea/core/semantic_analyzer.rb +17 -8
- data/lib/milk_tea/core/types/layout.rb +21 -22
- data/lib/milk_tea/core/types/predicates.rb +0 -2
- data/lib/milk_tea/core/types/registry.rb +16 -18
- data/lib/milk_tea/core/types/visitor.rb +0 -4
- data/lib/milk_tea/dap/backends/lldb_dap.rb +0 -2
- data/lib/milk_tea/dap/protocol.rb +1 -1
- data/lib/milk_tea/dap/server/breakpoints.rb +0 -2
- data/lib/milk_tea/dap/server/debug_map.rb +0 -2
- data/lib/milk_tea/dap/server/handlers.rb +0 -2
- data/lib/milk_tea/dap/server/launch.rb +0 -2
- data/lib/milk_tea/dap/server/lldb_backend.rb +8 -10
- data/lib/milk_tea/dap/server/pause_diagnostics.rb +14 -16
- data/lib/milk_tea/dap/server/utilities.rb +0 -2
- data/lib/milk_tea/dap/server/wire.rb +0 -2
- data/lib/milk_tea/dap/server.rb +0 -2
- data/lib/milk_tea/lsp/diagnostics.rb +16 -16
- data/lib/milk_tea/lsp/server/call_hierarchy.rb +11 -12
- data/lib/milk_tea/lsp/server/code_actions.rb +355 -357
- data/lib/milk_tea/lsp/server/code_lens.rb +23 -25
- data/lib/milk_tea/lsp/server/completion.rb +873 -875
- data/lib/milk_tea/lsp/server/configuration.rb +129 -131
- data/lib/milk_tea/lsp/server/debug_info.rb +0 -2
- data/lib/milk_tea/lsp/server/definition.rb +564 -565
- data/lib/milk_tea/lsp/server/diagnostics_scheduling.rb +191 -193
- data/lib/milk_tea/lsp/server/execute_command.rb +0 -2
- data/lib/milk_tea/lsp/server/folding_range.rb +0 -4
- data/lib/milk_tea/lsp/server/formatting.rb +478 -480
- data/lib/milk_tea/lsp/server/hover.rb +1282 -1284
- data/lib/milk_tea/lsp/server/inlay_hints.rb +179 -181
- data/lib/milk_tea/lsp/server/lifecycle.rb +192 -194
- data/lib/milk_tea/lsp/server/linked_editing_range.rb +0 -2
- data/lib/milk_tea/lsp/server/on_type_formatting.rb +0 -2
- data/lib/milk_tea/lsp/server/progress.rb +0 -2
- data/lib/milk_tea/lsp/server/references.rb +316 -318
- data/lib/milk_tea/lsp/server/rename.rb +445 -447
- data/lib/milk_tea/lsp/server/selection_range.rb +0 -4
- data/lib/milk_tea/lsp/server/semantic_tokens.rb +1318 -1320
- data/lib/milk_tea/lsp/server/signature_help.rb +146 -148
- data/lib/milk_tea/lsp/server/text_documents.rb +99 -101
- data/lib/milk_tea/lsp/server/type_hierarchy.rb +2 -4
- data/lib/milk_tea/lsp/server/utilities.rb +397 -399
- data/lib/milk_tea/lsp/server.rb +0 -3
- data/lib/milk_tea/lsp/workspace/analysis.rb +40 -42
- data/lib/milk_tea/lsp/workspace/dependency_graph.rb +4 -10
- data/lib/milk_tea/lsp/workspace/utilities.rb +19 -19
- data/lib/milk_tea/packages/atomic_write.rb +4 -5
- data/lib/milk_tea/packages/dependency_solver.rb +15 -15
- data/lib/milk_tea/packages/lock.rb +4 -4
- data/lib/milk_tea/packages/manager_cli.rb +1 -1
- data/lib/milk_tea/packages/manifest.rb +3 -3
- data/lib/milk_tea/packages/registry_store.rb +4 -6
- data/lib/milk_tea/packages/services.rb +16 -16
- data/lib/milk_tea/packages/source_cache.rb +4 -6
- data/lib/milk_tea/packages/source_resolver.rb +44 -44
- data/lib/milk_tea/packages/version.rb +8 -8
- data/lib/milk_tea/tooling/build.rb +3 -7
- data/lib/milk_tea/tooling/build_cache.rb +0 -2
- data/lib/milk_tea/tooling/debug_info_formatter.rb +31 -33
- data/lib/milk_tea/tooling/debug_map.rb +8 -10
- data/lib/milk_tea/tooling/docs_app.rb +0 -2
- data/lib/milk_tea/tooling/linter/doc_tags.rb +25 -27
- data/lib/milk_tea/tooling/linter/fix_engine.rb +87 -24
- data/lib/milk_tea/tooling/linter/flow_rules.rb +44 -46
- data/lib/milk_tea/tooling/linter/imports_platform.rb +14 -16
- data/lib/milk_tea/tooling/linter/release_rules.rb +3 -5
- data/lib/milk_tea/tooling/linter/reserved_names.rb +23 -25
- data/lib/milk_tea/tooling/linter/rules.rb +87 -89
- data/lib/milk_tea/tooling/linter/source_helpers.rb +40 -42
- data/lib/milk_tea/tooling/linter/trailing_comma.rb +17 -19
- data/lib/milk_tea/tooling/linter/visitors.rb +162 -50
- data/lib/milk_tea/tooling/linter.rb +0 -2
- data/lib/milk_tea/tooling/project_scaffold.rb +0 -2
- data/lib/milk_tea/tooling/run.rb +0 -2
- data/lib/milk_tea/tooling/toolchain_cli.rb +0 -2
- data/std/cli.mt +13 -32
- data/std/color.mt +28 -28
- data/std/encoding.mt +4 -4
- data/std/graph.mt +1 -2
- data/std/hash.mt +14 -14
- data/std/http/server.mt +3 -3
- data/std/input.mt +1 -1
- data/std/json.mt +1 -1
- data/std/linear_algebra.mt +6 -6
- data/std/net/mux.mt +1 -1
- data/std/noise.mt +23 -23
- data/std/parse.mt +2 -2
- data/std/process.mt +3 -4
- data/std/sparse_set.mt +1 -1
- data/std/steering.mt +5 -5
- data/std/str.mt +1 -1
- data/std/tween.mt +4 -4
- data/std/utility.mt +3 -3
- metadata +2 -2
|
@@ -4,1741 +4,1739 @@ module MilkTea
|
|
|
4
4
|
module LSP
|
|
5
5
|
class Server
|
|
6
6
|
module ServerSemanticTokens
|
|
7
|
-
|
|
7
|
+
def handle_semantic_tokens_full(params)
|
|
8
|
+
uri = params.dig('textDocument', 'uri')
|
|
9
|
+
return { data: [] } unless uri
|
|
10
|
+
|
|
11
|
+
total_start = monotonic_time
|
|
12
|
+
|
|
13
|
+
content = @workspace.get_content(uri)
|
|
14
|
+
cache_key = content.hash
|
|
15
|
+
cached = @semantic_tokens_cache[uri]
|
|
16
|
+
if cached && cached[:content_hash] == cache_key
|
|
17
|
+
elapsed = elapsed_ms(total_start)
|
|
18
|
+
short_uri = shorten_uri(uri) || uri
|
|
19
|
+
log_perf_breakdown('textDocument/semanticTokens/full', elapsed,
|
|
20
|
+
"uri=#{short_uri} bytes=#{content.bytesize} lines=#{content.count("\n") + 1} cache=hit data_len=#{cached[:data].length}")
|
|
21
|
+
return { data: cached[:data] }
|
|
22
|
+
end
|
|
8
23
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
24
|
+
tokens_start = monotonic_time
|
|
25
|
+
tokens = @workspace.get_tokens(uri) || []
|
|
26
|
+
tokens_ms = elapsed_ms(tokens_start)
|
|
12
27
|
|
|
13
|
-
|
|
28
|
+
facts_start = monotonic_time
|
|
29
|
+
facts = @workspace.get_facts(uri, allow_last_good_fallback: semantic_tokens_allow_last_good_fallback?(uri))
|
|
30
|
+
facts_ms = elapsed_ms(facts_start)
|
|
14
31
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if cached && cached[:content_hash] == cache_key
|
|
19
|
-
elapsed = elapsed_ms(total_start)
|
|
20
|
-
short_uri = shorten_uri(uri) || uri
|
|
21
|
-
log_perf_breakdown('textDocument/semanticTokens/full', elapsed,
|
|
22
|
-
"uri=#{short_uri} bytes=#{content.bytesize} lines=#{content.count("\n") + 1} cache=hit data_len=#{cached[:data].length}")
|
|
23
|
-
return { data: cached[:data] }
|
|
24
|
-
end
|
|
32
|
+
build_start = monotonic_time
|
|
33
|
+
semantic_entries = build_semantic_token_entries(tokens, facts)
|
|
34
|
+
build_ms = elapsed_ms(build_start)
|
|
25
35
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
encode_start = monotonic_time
|
|
37
|
+
data = encode_semantic_tokens(semantic_entries)
|
|
38
|
+
encode_ms = elapsed_ms(encode_start)
|
|
29
39
|
|
|
30
|
-
|
|
31
|
-
facts = @workspace.get_facts(uri, allow_last_good_fallback: semantic_tokens_allow_last_good_fallback?(uri))
|
|
32
|
-
facts_ms = elapsed_ms(facts_start)
|
|
40
|
+
@semantic_tokens_cache[uri] = { content_hash: cache_key, data: data }
|
|
33
41
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
result_id = next_semantic_token_result_id(uri)
|
|
43
|
+
@semantic_tokens_delta_cache[uri] = {
|
|
44
|
+
result_id: result_id,
|
|
45
|
+
content_hash: cache_key,
|
|
46
|
+
entries: semantic_entries,
|
|
47
|
+
}
|
|
37
48
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
elapsed = elapsed_ms(total_start)
|
|
50
|
+
short_uri = shorten_uri(uri) || uri
|
|
51
|
+
log_perf_breakdown('textDocument/semanticTokens/full', elapsed,
|
|
52
|
+
"uri=#{short_uri} bytes=#{content.bytesize} lines=#{content.count("\n") + 1} cache=miss tokens=#{tokens.length} entries=#{semantic_entries.length} data_len=#{data.length} facts=on stages_ms=tokens:#{tokens_ms},facts:#{facts_ms},build:#{build_ms},encode:#{encode_ms}")
|
|
41
53
|
|
|
42
|
-
|
|
54
|
+
{ data: data }
|
|
55
|
+
rescue StandardError => e
|
|
56
|
+
warn "Error in semanticTokens/full handler: #{e.message}"
|
|
57
|
+
{ data: [] }
|
|
58
|
+
end
|
|
43
59
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
entries: semantic_entries,
|
|
49
|
-
}
|
|
60
|
+
def handle_semantic_tokens_delta(params)
|
|
61
|
+
uri = params.dig('textDocument', 'uri')
|
|
62
|
+
previous_result_id = params['previousResultId']
|
|
63
|
+
return handle_semantic_tokens_full(params) unless uri && previous_result_id
|
|
50
64
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
cached = @semantic_tokens_delta_cache[uri]
|
|
66
|
+
unless cached && cached[:result_id] == previous_result_id
|
|
67
|
+
return handle_semantic_tokens_full(params)
|
|
68
|
+
end
|
|
55
69
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
70
|
+
content = @workspace.get_content(uri)
|
|
71
|
+
cache_key = content.hash
|
|
72
|
+
if cached[:content_hash] == cache_key
|
|
73
|
+
return { resultId: cached[:result_id], edits: [] }
|
|
74
|
+
end
|
|
61
75
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return handle_semantic_tokens_full(params) unless uri && previous_result_id
|
|
76
|
+
tokens = @workspace.get_tokens(uri) || []
|
|
77
|
+
facts = @workspace.get_facts(uri, allow_last_good_fallback: semantic_tokens_allow_last_good_fallback?(uri))
|
|
78
|
+
new_entries = build_semantic_token_entries(tokens, facts)
|
|
66
79
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
new_result_id = next_semantic_token_result_id(uri)
|
|
81
|
+
@semantic_tokens_delta_cache[uri] = {
|
|
82
|
+
result_id: new_result_id,
|
|
83
|
+
content_hash: cache_key,
|
|
84
|
+
entries: new_entries,
|
|
85
|
+
}
|
|
71
86
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
87
|
+
edits = compute_semantic_tokens_edits(cached[:entries], new_entries)
|
|
88
|
+
{ resultId: new_result_id, edits: edits }
|
|
89
|
+
rescue StandardError => e
|
|
90
|
+
warn "Error in semanticTokens/full/delta handler: #{e.message}"
|
|
91
|
+
handle_semantic_tokens_full(params)
|
|
76
92
|
end
|
|
77
93
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
94
|
+
def handle_semantic_tokens_range(params)
|
|
95
|
+
uri = params.dig("textDocument", "uri")
|
|
96
|
+
range = params["range"]
|
|
97
|
+
return { data: [] } unless uri && range
|
|
81
98
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
result_id: new_result_id,
|
|
85
|
-
content_hash: cache_key,
|
|
86
|
-
entries: new_entries,
|
|
87
|
-
}
|
|
99
|
+
content = @workspace.get_content(uri)
|
|
100
|
+
return { data: [] } unless content
|
|
88
101
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
rescue StandardError => e
|
|
92
|
-
warn "Error in semanticTokens/full/delta handler: #{e.message}"
|
|
93
|
-
handle_semantic_tokens_full(params)
|
|
94
|
-
end
|
|
102
|
+
tokens = @workspace.get_tokens(uri) || []
|
|
103
|
+
return { data: [] } if tokens.empty?
|
|
95
104
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
range = params["range"]
|
|
99
|
-
return { data: [] } unless uri && range
|
|
105
|
+
start_line = range.dig("start", "line") + 1
|
|
106
|
+
end_line = range.dig("end", "line") + 1
|
|
100
107
|
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
range_tokens = tokens.select do |t|
|
|
109
|
+
t.line >= start_line && t.line <= end_line &&
|
|
110
|
+
![:newline, :indent, :dedent, :eof].include?(t.type)
|
|
111
|
+
end
|
|
103
112
|
|
|
104
|
-
|
|
105
|
-
|
|
113
|
+
facts = @workspace.get_facts(uri, allow_last_good_fallback: semantic_tokens_allow_last_good_fallback?(uri))
|
|
114
|
+
semantic_entries = build_semantic_token_entries(range_tokens, facts)
|
|
106
115
|
|
|
107
|
-
|
|
108
|
-
|
|
116
|
+
entries_in_range = semantic_entries.select do |entry|
|
|
117
|
+
entry[:line] >= start_line && entry[:line] <= end_line
|
|
118
|
+
end
|
|
109
119
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
120
|
+
data = encode_semantic_tokens(entries_in_range)
|
|
121
|
+
{ data: data }
|
|
122
|
+
rescue StandardError => e
|
|
123
|
+
warn "Error in semanticTokens/range handler: #{e.message}"
|
|
124
|
+
{ data: [] }
|
|
113
125
|
end
|
|
114
126
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
def build_semantic_token_entries(tokens, facts = nil)
|
|
128
|
+
# Precompute line → non-trivia tokens index so non_trivia_tokens_on_line
|
|
129
|
+
# is O(1) per call instead of O(n), turning the overall build from O(n²) to O(n).
|
|
130
|
+
trivia_types = Set[:newline, :indent, :dedent, :eof]
|
|
131
|
+
@tokens_by_line_cache = Hash.new { |h, k| h[k] = [] }
|
|
132
|
+
tokens.each { |t| @tokens_by_line_cache[t.line] << t unless trivia_types.include?(t.type) }
|
|
133
|
+
@attribute_name_semantic_overrides = build_attribute_name_semantic_overrides(tokens, facts)
|
|
121
134
|
|
|
122
|
-
|
|
123
|
-
{ data: data }
|
|
124
|
-
rescue StandardError => e
|
|
125
|
-
warn "Error in semanticTokens/range handler: #{e.message}"
|
|
126
|
-
{ data: [] }
|
|
127
|
-
end
|
|
135
|
+
entries = []
|
|
128
136
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
# is O(1) per call instead of O(n), turning the overall build from O(n²) to O(n).
|
|
132
|
-
trivia_types = Set[:newline, :indent, :dedent, :eof]
|
|
133
|
-
@tokens_by_line_cache = Hash.new { |h, k| h[k] = [] }
|
|
134
|
-
tokens.each { |t| @tokens_by_line_cache[t.line] << t unless trivia_types.include?(t.type) }
|
|
135
|
-
@attribute_name_semantic_overrides = build_attribute_name_semantic_overrides(tokens, facts)
|
|
137
|
+
tokens.each_with_index do |tok, index|
|
|
138
|
+
next if [:newline, :indent, :dedent, :eof].include?(tok.type)
|
|
136
139
|
|
|
137
|
-
|
|
140
|
+
if tok.type == :fstring
|
|
141
|
+
next if embedded_heredoc_token?(tok)
|
|
142
|
+
fstring_interpolation_entries(tok, facts).each { |e| entries << e }
|
|
143
|
+
next
|
|
144
|
+
end
|
|
138
145
|
|
|
139
|
-
|
|
140
|
-
|
|
146
|
+
semantic_type, modifiers = classify_semantic_token(tokens, index, facts)
|
|
147
|
+
next unless semantic_type
|
|
141
148
|
|
|
142
|
-
|
|
143
|
-
next if embedded_heredoc_token?(tok)
|
|
144
|
-
fstring_interpolation_entries(tok, facts).each { |e| entries << e }
|
|
145
|
-
next
|
|
149
|
+
token_semantic_entries(tok, semantic_type, modifiers).each { |entry| entries << entry }
|
|
146
150
|
end
|
|
147
151
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
+
entries.sort_by { |entry| [entry[:line], entry[:start_char]] }
|
|
153
|
+
ensure
|
|
154
|
+
@tokens_by_line_cache = nil
|
|
155
|
+
@attribute_name_semantic_overrides = nil
|
|
152
156
|
end
|
|
153
157
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
@attribute_name_semantic_overrides = nil
|
|
158
|
-
end
|
|
158
|
+
def fstring_interpolation_entries(fstring_tok, facts)
|
|
159
|
+
parts = fstring_tok.literal
|
|
160
|
+
return [{ line: fstring_tok.line - 1, start_char: fstring_tok.column - 1, length: fstring_tok.lexeme.length, type: :string, modifiers: [] }] unless parts.is_a?(Array)
|
|
159
161
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
result = []
|
|
165
|
-
fstr_line = fstring_tok.line - 1 # 0-indexed
|
|
166
|
-
fstr_col0 = fstring_tok.column - 1 # 0-indexed start of `f`
|
|
167
|
-
cursor = fstr_col0
|
|
168
|
-
|
|
169
|
-
parts.each do |part|
|
|
170
|
-
next unless part[:kind] == :expr
|
|
171
|
-
|
|
172
|
-
# part[:column] is 1-indexed column of the first char of the expression source
|
|
173
|
-
# (i.e. the char right after `#{`).
|
|
174
|
-
expr_col0 = part[:column] - 1 # 0-indexed
|
|
175
|
-
hash_col0 = expr_col0 - 2 # 0-indexed position of `#`
|
|
176
|
-
|
|
177
|
-
raw_len = part[:source].length + (part[:format_spec] ? 1 + part[:format_spec].length : 0)
|
|
178
|
-
rbrace_col0 = expr_col0 + raw_len # 0-indexed position of `}`
|
|
179
|
-
|
|
180
|
-
# :string for everything from cursor up to (but not including) `#`
|
|
181
|
-
text_len = hash_col0 - cursor
|
|
182
|
-
result << { line: fstr_line, start_char: cursor, length: text_len, type: :string, modifiers: [] } if text_len > 0
|
|
183
|
-
|
|
184
|
-
# classified entries for the expression source only (not format spec).
|
|
185
|
-
source = part[:source]
|
|
186
|
-
unless source.nil? || source.strip.empty?
|
|
187
|
-
begin
|
|
188
|
-
sub_tokens = interpolation_expression_tokens(part)
|
|
189
|
-
sub_tokens.each_with_index do |sub_tok, i|
|
|
190
|
-
sem_type, modifiers = classify_semantic_token(sub_tokens, i, facts)
|
|
191
|
-
next unless sem_type
|
|
192
|
-
result << {
|
|
193
|
-
line: sub_tok.line - 1,
|
|
194
|
-
start_char: sub_tok.column - 1,
|
|
195
|
-
length: sub_tok.lexeme.length,
|
|
196
|
-
type: sem_type,
|
|
197
|
-
modifiers: modifiers
|
|
198
|
-
}
|
|
199
|
-
end
|
|
200
|
-
rescue MilkTea::LexError
|
|
201
|
-
# Fall back to string coloring for malformed expression.
|
|
202
|
-
result << {
|
|
203
|
-
line: fstr_line,
|
|
204
|
-
start_char: expr_col0,
|
|
205
|
-
length: source.length,
|
|
206
|
-
type: :string,
|
|
207
|
-
modifiers: [],
|
|
208
|
-
}
|
|
209
|
-
end
|
|
210
|
-
end
|
|
162
|
+
result = []
|
|
163
|
+
fstr_line = fstring_tok.line - 1 # 0-indexed
|
|
164
|
+
fstr_col0 = fstring_tok.column - 1 # 0-indexed start of `f`
|
|
165
|
+
cursor = fstr_col0
|
|
211
166
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
#
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
167
|
+
parts.each do |part|
|
|
168
|
+
next unless part[:kind] == :expr
|
|
169
|
+
|
|
170
|
+
# part[:column] is 1-indexed column of the first char of the expression source
|
|
171
|
+
# (i.e. the char right after `#{`).
|
|
172
|
+
expr_col0 = part[:column] - 1 # 0-indexed
|
|
173
|
+
hash_col0 = expr_col0 - 2 # 0-indexed position of `#`
|
|
174
|
+
|
|
175
|
+
raw_len = part[:source].length + (part[:format_spec] ? 1 + part[:format_spec].length : 0)
|
|
176
|
+
rbrace_col0 = expr_col0 + raw_len # 0-indexed position of `}`
|
|
177
|
+
|
|
178
|
+
# :string for everything from cursor up to (but not including) `#`
|
|
179
|
+
text_len = hash_col0 - cursor
|
|
180
|
+
result << { line: fstr_line, start_char: cursor, length: text_len, type: :string, modifiers: [] } if text_len > 0
|
|
181
|
+
|
|
182
|
+
# classified entries for the expression source only (not format spec).
|
|
183
|
+
source = part[:source]
|
|
184
|
+
unless source.nil? || source.strip.empty?
|
|
220
185
|
begin
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
next unless spec_sem_type
|
|
186
|
+
sub_tokens = interpolation_expression_tokens(part)
|
|
187
|
+
sub_tokens.each_with_index do |sub_tok, i|
|
|
188
|
+
sem_type, modifiers = classify_semantic_token(sub_tokens, i, facts)
|
|
189
|
+
next unless sem_type
|
|
226
190
|
result << {
|
|
227
|
-
line:
|
|
228
|
-
start_char:
|
|
229
|
-
length:
|
|
230
|
-
type:
|
|
231
|
-
modifiers:
|
|
191
|
+
line: sub_tok.line - 1,
|
|
192
|
+
start_char: sub_tok.column - 1,
|
|
193
|
+
length: sub_tok.lexeme.length,
|
|
194
|
+
type: sem_type,
|
|
195
|
+
modifiers: modifiers
|
|
232
196
|
}
|
|
233
197
|
end
|
|
234
198
|
rescue MilkTea::LexError
|
|
235
|
-
# Fall back
|
|
199
|
+
# Fall back to string coloring for malformed expression.
|
|
236
200
|
result << {
|
|
237
201
|
line: fstr_line,
|
|
238
|
-
start_char:
|
|
239
|
-
length:
|
|
240
|
-
type: :
|
|
241
|
-
modifiers: []
|
|
202
|
+
start_char: expr_col0,
|
|
203
|
+
length: source.length,
|
|
204
|
+
type: :string,
|
|
205
|
+
modifiers: [],
|
|
242
206
|
}
|
|
243
207
|
end
|
|
244
208
|
end
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
cursor = rbrace_col0 + 1
|
|
248
|
-
end
|
|
249
209
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
210
|
+
# classified entries for format spec (if present), excluding the
|
|
211
|
+
# delimiter token so TextMate interpolation punctuation can style it.
|
|
212
|
+
if part[:format_spec]
|
|
213
|
+
spec_col0 = expr_col0 + source.length
|
|
214
|
+
# Format spec content (e.g., ".0", "3", ".5f") as individual token-like entries.
|
|
215
|
+
# Treat it as lexable content or just string for simplicity.
|
|
216
|
+
spec = part[:format_spec]
|
|
217
|
+
unless spec.empty?
|
|
218
|
+
begin
|
|
219
|
+
spec_tokens = MilkTea::Lexer.new(spec).lex
|
|
220
|
+
.reject { |t| [:newline, :indent, :dedent, :eof].include?(t.type) }
|
|
221
|
+
spec_tokens.each_with_index do |spec_tok, i|
|
|
222
|
+
spec_sem_type, spec_modifiers = classify_semantic_token(spec_tokens, i, facts)
|
|
223
|
+
next unless spec_sem_type
|
|
224
|
+
result << {
|
|
225
|
+
line: fstr_line,
|
|
226
|
+
start_char: spec_col0 + 1 + (spec_tok.column - 1),
|
|
227
|
+
length: spec_tok.lexeme.length,
|
|
228
|
+
type: spec_sem_type,
|
|
229
|
+
modifiers: spec_modifiers
|
|
230
|
+
}
|
|
231
|
+
end
|
|
232
|
+
rescue MilkTea::LexError
|
|
233
|
+
# Fall back: treat spec as a number/string token.
|
|
234
|
+
result << {
|
|
235
|
+
line: fstr_line,
|
|
236
|
+
start_char: spec_col0 + 1,
|
|
237
|
+
length: spec.length,
|
|
238
|
+
type: :number,
|
|
239
|
+
modifiers: []
|
|
240
|
+
}
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
254
244
|
|
|
255
|
-
|
|
256
|
-
|
|
245
|
+
cursor = rbrace_col0 + 1
|
|
246
|
+
end
|
|
257
247
|
|
|
258
|
-
|
|
259
|
-
|
|
248
|
+
# :string for tail text + closing `"`
|
|
249
|
+
fstr_end_col0 = fstr_col0 + fstring_tok.lexeme.length - 1
|
|
250
|
+
tail_len = fstr_end_col0 - cursor + 1
|
|
251
|
+
result << { line: fstr_line, start_char: cursor, length: tail_len, type: :string, modifiers: [] } if tail_len > 0
|
|
260
252
|
|
|
261
|
-
|
|
262
|
-
return classify_name_semantic(tok.lexeme, tokens, index, facts)
|
|
253
|
+
result
|
|
263
254
|
end
|
|
264
255
|
|
|
265
|
-
|
|
266
|
-
|
|
256
|
+
def classify_semantic_token(tokens, index, facts = nil)
|
|
257
|
+
tok = tokens[index]
|
|
267
258
|
|
|
268
|
-
|
|
269
|
-
|
|
259
|
+
if tok.type == :identifier || namespace_keyword_token?(tokens, index)
|
|
260
|
+
return classify_name_semantic(tok.lexeme, tokens, index, facts)
|
|
261
|
+
end
|
|
270
262
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
end
|
|
263
|
+
if [:string, :cstring].include?(tok.type)
|
|
264
|
+
return [nil, []] if embedded_heredoc_token?(tok)
|
|
274
265
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
end
|
|
266
|
+
return [:string, []]
|
|
267
|
+
end
|
|
278
268
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
269
|
+
if tok.type == :comment
|
|
270
|
+
return [:comment, []]
|
|
271
|
+
end
|
|
282
272
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
273
|
+
if [:integer, :float].include?(tok.type)
|
|
274
|
+
return [:number, []]
|
|
275
|
+
end
|
|
286
276
|
|
|
287
|
-
|
|
288
|
-
|
|
277
|
+
if KEYWORD_TOKEN_TYPES.include?(tok.type)
|
|
278
|
+
return [:keyword, []]
|
|
279
|
+
end
|
|
289
280
|
|
|
290
|
-
|
|
291
|
-
|
|
281
|
+
if OPERATOR_TOKEN_TYPES.include?(tok.type)
|
|
282
|
+
return [:operator, []]
|
|
283
|
+
end
|
|
292
284
|
|
|
293
|
-
|
|
294
|
-
|
|
285
|
+
[nil, []]
|
|
286
|
+
end
|
|
295
287
|
|
|
296
|
-
|
|
297
|
-
|
|
288
|
+
def embedded_heredoc_token?(token)
|
|
289
|
+
return false unless [:string, :cstring, :fstring].include?(token.type)
|
|
298
290
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
next if segment.empty?
|
|
291
|
+
tag = token.lexeme[/\A(?:f|c)?<<-([A-Za-z_][A-Za-z0-9_]*)[ \t]*\n/, 1]
|
|
292
|
+
return false if tag.nil?
|
|
302
293
|
|
|
303
|
-
|
|
304
|
-
line: token.line - 1 + index,
|
|
305
|
-
start_char: index.zero? ? (token.column - 1) : 0,
|
|
306
|
-
length: segment.length,
|
|
307
|
-
type: semantic_type,
|
|
308
|
-
modifiers: modifiers
|
|
309
|
-
}
|
|
294
|
+
%w[GLSL VERT FRAG COMP JSON JSONC SQL HTML MT].include?(tag)
|
|
310
295
|
end
|
|
311
|
-
end
|
|
312
296
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
next_tok = next_non_trivia_token(tokens, index + 1)
|
|
317
|
-
parameter_declaration = parameter_declaration_token?(tokens, index)
|
|
318
|
-
user_defined_function = facts ? facts.functions.key?(name) : lexically_declared_free_function_name?(tokens, name)
|
|
297
|
+
def token_semantic_entries(token, semantic_type, modifiers)
|
|
298
|
+
token.lexeme.split("\n", -1).each_with_index.filter_map do |segment, index|
|
|
299
|
+
next if segment.empty?
|
|
319
300
|
|
|
320
|
-
|
|
321
|
-
|
|
301
|
+
{
|
|
302
|
+
line: token.line - 1 + index,
|
|
303
|
+
start_char: index.zero? ? (token.column - 1) : 0,
|
|
304
|
+
length: segment.length,
|
|
305
|
+
type: semantic_type,
|
|
306
|
+
modifiers: modifiers
|
|
307
|
+
}
|
|
308
|
+
end
|
|
322
309
|
end
|
|
323
310
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
311
|
+
def classify_name_semantic(name, tokens, index, facts = nil)
|
|
312
|
+
tok = tokens[index]
|
|
313
|
+
prev_tok = previous_non_trivia_token(tokens, index)
|
|
314
|
+
next_tok = next_non_trivia_token(tokens, index + 1)
|
|
315
|
+
parameter_declaration = parameter_declaration_token?(tokens, index)
|
|
316
|
+
user_defined_function = facts ? facts.functions.key?(name) : lexically_declared_free_function_name?(tokens, name)
|
|
329
317
|
|
|
330
|
-
|
|
318
|
+
if @attribute_name_semantic_overrides && (override = @attribute_name_semantic_overrides[[tok.line, tok.column]])
|
|
319
|
+
return override
|
|
320
|
+
end
|
|
331
321
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
322
|
+
if (import_info = import_path_info_at(tokens, index, allow_keywords: true))
|
|
323
|
+
modifiers = []
|
|
324
|
+
modifiers << 'declaration' if import_info[:role] == :alias
|
|
325
|
+
return [:namespace, modifiers]
|
|
326
|
+
end
|
|
335
327
|
|
|
336
|
-
|
|
337
|
-
return [:type, ['declaration']]
|
|
338
|
-
end
|
|
328
|
+
return [:namespace, []] if module_declaration_path_token?(tokens, index, allow_keywords: true)
|
|
339
329
|
|
|
340
|
-
|
|
330
|
+
if prev_tok && [:function, :fn, :proc].include?(prev_tok.type)
|
|
331
|
+
return [:function, ['declaration']]
|
|
332
|
+
end
|
|
341
333
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
334
|
+
if prev_tok && [:struct, :union, :enum, :flags, :variant, :type, :opaque, :interface].include?(prev_tok.type)
|
|
335
|
+
return [:type, ['declaration']]
|
|
336
|
+
end
|
|
345
337
|
|
|
346
|
-
|
|
347
|
-
return [:variable, ['declaration', 'readonly']]
|
|
348
|
-
end
|
|
338
|
+
return [:variable, []] if name == "_"
|
|
349
339
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
340
|
+
if prev_tok&.type == :event
|
|
341
|
+
return struct_event_declaration_token?(tokens, index) ? [:property, ['declaration']] : [:variable, ['declaration']]
|
|
342
|
+
end
|
|
353
343
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
344
|
+
if prev_tok&.type == :const
|
|
345
|
+
return [:variable, ['declaration', 'readonly']]
|
|
346
|
+
end
|
|
357
347
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
348
|
+
if prev_tok&.type == :let
|
|
349
|
+
return [:variable, ['declaration', 'readonly']] unless next_tok&.type == :lparen
|
|
350
|
+
end
|
|
361
351
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
return [:property, ['declaration']] if field_declaration_token?(tokens, index)
|
|
352
|
+
if prev_tok&.type == :var
|
|
353
|
+
return [:variable, ['declaration']] unless next_tok&.type == :lparen
|
|
354
|
+
end
|
|
366
355
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
356
|
+
if prev_tok&.type == :for
|
|
357
|
+
return [:variable, ['declaration', 'readonly']]
|
|
358
|
+
end
|
|
370
359
|
|
|
371
|
-
|
|
372
|
-
return [:
|
|
373
|
-
return [:
|
|
374
|
-
|
|
360
|
+
return [:variable, ['declaration', 'readonly']] if match_arm_binding_token?(tokens, index)
|
|
361
|
+
return [:parameter, ['declaration']] if callable_parameter_declaration_token?(tokens, index)
|
|
362
|
+
return [:property, ['declaration']] if variant_payload_field_declaration_token?(tokens, index)
|
|
363
|
+
return [:property, ['declaration']] if field_declaration_token?(tokens, index)
|
|
375
364
|
|
|
376
|
-
|
|
377
|
-
|
|
365
|
+
if destructure_let_binding?(tokens, index)
|
|
366
|
+
return [:variable, ['declaration', 'readonly']]
|
|
367
|
+
end
|
|
378
368
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
369
|
+
if facts
|
|
370
|
+
return [:typeParameter, ['declaration']] if type_parameter_declaration_token?(facts, tokens, index)
|
|
371
|
+
return [:typeParameter, []] if type_parameter_reference_token?(facts, tokens, index)
|
|
372
|
+
end
|
|
382
373
|
|
|
383
|
-
|
|
384
|
-
return [:
|
|
385
|
-
return [:type, []] if facts.interfaces.key?(name)
|
|
386
|
-
return [:namespace, []] if facts.imports.key?(name)
|
|
374
|
+
return [:property, []] if named_argument_label_token?(tokens, index) && named_argument_label_in_type_constructor?(tokens, index, facts)
|
|
375
|
+
return [:parameter, []] if named_argument_label_token?(tokens, index)
|
|
387
376
|
|
|
388
|
-
if (
|
|
389
|
-
return
|
|
377
|
+
if facts && prev_tok&.type != :dot && (generic_binding = generic_function_lexical_binding_semantic(facts, tok))
|
|
378
|
+
return generic_binding
|
|
390
379
|
end
|
|
391
380
|
|
|
392
|
-
if
|
|
393
|
-
return
|
|
394
|
-
|
|
395
|
-
|
|
381
|
+
if next_tok&.type == :dot && facts
|
|
382
|
+
return [:type, []] if known_type_name?(facts, name)
|
|
383
|
+
return [:type, []] if facts.interfaces.key?(name)
|
|
384
|
+
return [:namespace, []] if facts.imports.key?(name)
|
|
396
385
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
386
|
+
if (binding = local_semantic_value_binding(facts, tok, allow_same_line_future: parameter_declaration))
|
|
387
|
+
return semantic_value_binding_entry(binding, declaration: binding.kind == :param && parameter_declaration)
|
|
388
|
+
end
|
|
400
389
|
|
|
401
|
-
|
|
390
|
+
if (binding = facts.values[name])
|
|
391
|
+
return semantic_value_binding_entry(binding)
|
|
392
|
+
end
|
|
393
|
+
end
|
|
402
394
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
395
|
+
if facts && (known_type_name?(facts, name) || facts.interfaces.key?(name)) && identifier_in_type_argument_position?(tokens, index)
|
|
396
|
+
return [:type, []]
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
return [:enumMember, ['declaration']] if variant_enum_member_declaration?(tokens, index)
|
|
400
|
+
|
|
401
|
+
if prev_tok&.type == :dot
|
|
402
|
+
if facts
|
|
403
|
+
module_binding = imported_module_binding_for_member(tokens, index, facts)
|
|
404
|
+
if module_binding
|
|
405
|
+
if module_binding.functions.key?(name)
|
|
406
|
+
return [:function, []] if next_tok&.type == :lparen || specialized_call_with_type_args?(tokens, index)
|
|
407
|
+
return [:function, []] if next_tok&.type == :lbracket
|
|
408
|
+
return [:function, []] if imported_module_function_value_member_access_site?(facts, tokens, index)
|
|
409
|
+
return [:property, []]
|
|
410
|
+
end
|
|
411
|
+
return [:type, []] if module_binding.types.key?(name)
|
|
412
|
+
return [:type, []] if module_binding.interfaces.key?(name)
|
|
413
|
+
if (value_binding = module_binding.values[name])
|
|
414
|
+
modifiers = []
|
|
415
|
+
modifiers << 'readonly' if value_binding.respond_to?(:mutable) && value_binding.mutable == false
|
|
416
|
+
return [:variable, modifiers]
|
|
417
|
+
end
|
|
418
|
+
return [:namespace, []] if facts.imports.key?(name)
|
|
419
419
|
end
|
|
420
|
-
|
|
420
|
+
|
|
421
|
+
return [:type, []] if dot_nested_type_member?(tokens, index, facts)
|
|
422
|
+
return [:property, []] if callable_field_member_access?(name, tokens, index, facts)
|
|
423
|
+
return [:method, []] if static_type_member_access?(tokens, index, facts)
|
|
421
424
|
end
|
|
422
425
|
|
|
423
|
-
return [:
|
|
424
|
-
return [:
|
|
425
|
-
return [:
|
|
426
|
+
return [:enumMember, []] if type_name_member_access?(tokens, index, facts)
|
|
427
|
+
return [:method, []] if next_tok&.type == :lparen || specialized_call_with_type_args?(tokens, index)
|
|
428
|
+
return [:property, []]
|
|
426
429
|
end
|
|
427
430
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
431
|
+
if next_tok&.type == :lparen || specialized_call_with_type_args?(tokens, index)
|
|
432
|
+
if facts && (resolved = resolved_call_callee_semantic(name, tok, parameter_declaration, facts))
|
|
433
|
+
return resolved
|
|
434
|
+
end
|
|
432
435
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
+
return [:function, []] if user_defined_function
|
|
437
|
+
|
|
438
|
+
modifiers = []
|
|
439
|
+
modifiers << 'defaultLibrary' if BUILTIN_FUNCTION_NAMES.include?(name)
|
|
440
|
+
if BUILTIN_ASSOCIATED_HOOK_NAMES.include?(name) && specialized_call_with_type_args?(tokens, index) && !user_defined_function
|
|
441
|
+
modifiers << 'defaultLibrary'
|
|
442
|
+
end
|
|
443
|
+
return [:function, modifiers]
|
|
436
444
|
end
|
|
437
445
|
|
|
438
|
-
return [:function, []] if user_defined_function
|
|
446
|
+
return [:function, []] if next_tok&.type == :lbracket && user_defined_function
|
|
439
447
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
448
|
+
if facts && identifier_in_type_reference_position?(tokens, index)
|
|
449
|
+
if known_type_name?(facts, name)
|
|
450
|
+
modifiers = []
|
|
451
|
+
modifiers << 'defaultLibrary' if DEFAULT_LIBRARY_TYPE_NAMES.include?(name)
|
|
452
|
+
return [:type, modifiers]
|
|
453
|
+
end
|
|
454
|
+
return [:type, []] if facts.interfaces.key?(name)
|
|
455
|
+
|
|
456
|
+
if DEFAULT_LIBRARY_TYPE_NAMES.include?(name)
|
|
457
|
+
return [:type, ['defaultLibrary']]
|
|
458
|
+
end
|
|
444
459
|
end
|
|
445
|
-
return [:function, modifiers]
|
|
446
|
-
end
|
|
447
460
|
|
|
448
|
-
|
|
461
|
+
if facts
|
|
449
462
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
463
|
+
if (binding = local_semantic_value_binding(facts, tok, allow_same_line_future: parameter_declaration))
|
|
464
|
+
return semantic_value_binding_entry(binding, declaration: binding.kind == :param && parameter_declaration)
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
if known_type_name?(facts, name)
|
|
468
|
+
modifiers = []
|
|
469
|
+
modifiers << 'defaultLibrary' if DEFAULT_LIBRARY_TYPE_NAMES.include?(name)
|
|
470
|
+
return [:type, modifiers]
|
|
471
|
+
end
|
|
472
|
+
return [:type, []] if facts.interfaces.key?(name)
|
|
473
|
+
|
|
474
|
+
return [:namespace, []] if facts.imports.key?(name)
|
|
475
|
+
|
|
476
|
+
if (binding = facts.values[name])
|
|
477
|
+
return semantic_value_binding_entry(binding)
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
return [:function, []] if bare_function_value_identifier_site?(facts, tok)
|
|
455
481
|
end
|
|
456
|
-
return [:type, []] if facts.interfaces.key?(name)
|
|
457
482
|
|
|
458
483
|
if DEFAULT_LIBRARY_TYPE_NAMES.include?(name)
|
|
459
484
|
return [:type, ['defaultLibrary']]
|
|
460
485
|
end
|
|
486
|
+
|
|
487
|
+
return [:function, ['defaultLibrary']] if bare_builtin_specialization?(name, tokens, index)
|
|
488
|
+
|
|
489
|
+
[:variable, []]
|
|
461
490
|
end
|
|
462
491
|
|
|
463
|
-
|
|
492
|
+
def named_argument_label_token?(tokens, index)
|
|
493
|
+
prev_tok = previous_non_trivia_token(tokens, index)
|
|
494
|
+
next_tok = next_non_trivia_token(tokens, index + 1)
|
|
495
|
+
next_tok&.type == :equal && prev_tok && [:lparen, :comma].include?(prev_tok.type)
|
|
496
|
+
end
|
|
464
497
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
end
|
|
498
|
+
def named_argument_label_in_type_constructor?(tokens, index, facts)
|
|
499
|
+
return false unless facts
|
|
468
500
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
modifiers << 'defaultLibrary' if DEFAULT_LIBRARY_TYPE_NAMES.include?(name)
|
|
472
|
-
return [:type, modifiers]
|
|
473
|
-
end
|
|
474
|
-
return [:type, []] if facts.interfaces.key?(name)
|
|
501
|
+
opener_index = parameter_list_opener_index(tokens, index)
|
|
502
|
+
return false unless opener_index
|
|
475
503
|
|
|
476
|
-
|
|
504
|
+
callee_index = previous_non_trivia_token_index(tokens, opener_index)
|
|
505
|
+
return false unless callee_index
|
|
477
506
|
|
|
478
|
-
if
|
|
479
|
-
|
|
507
|
+
if tokens[callee_index].type == :rbracket
|
|
508
|
+
lbracket_index = matching_opener_index(tokens, callee_index)
|
|
509
|
+
return false unless lbracket_index
|
|
510
|
+
callee_index = previous_non_trivia_token_index(tokens, lbracket_index)
|
|
480
511
|
end
|
|
481
512
|
|
|
482
|
-
return
|
|
483
|
-
end
|
|
484
|
-
|
|
485
|
-
if DEFAULT_LIBRARY_TYPE_NAMES.include?(name)
|
|
486
|
-
return [:type, ['defaultLibrary']]
|
|
487
|
-
end
|
|
513
|
+
return false unless callee_index && tokens[callee_index].type == :identifier
|
|
488
514
|
|
|
489
|
-
|
|
515
|
+
callee_name = tokens[callee_index].lexeme
|
|
516
|
+
return true if facts.types.key?(callee_name) || facts.interfaces.key?(callee_name)
|
|
490
517
|
|
|
491
|
-
|
|
492
|
-
|
|
518
|
+
dot_index = previous_non_trivia_token_index(tokens, callee_index)
|
|
519
|
+
return false unless dot_index && tokens[dot_index].type == :dot
|
|
493
520
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
next_tok = next_non_trivia_token(tokens, index + 1)
|
|
497
|
-
next_tok&.type == :equal && prev_tok && [:lparen, :comma].include?(prev_tok.type)
|
|
498
|
-
end
|
|
521
|
+
receiver_index = previous_non_trivia_token_index(tokens, dot_index)
|
|
522
|
+
return false unless receiver_index
|
|
499
523
|
|
|
500
|
-
|
|
501
|
-
|
|
524
|
+
if tokens[receiver_index].type == :rbracket
|
|
525
|
+
lbracket_index = matching_opener_index(tokens, receiver_index)
|
|
526
|
+
return false unless lbracket_index
|
|
527
|
+
receiver_index = previous_non_trivia_token_index(tokens, lbracket_index)
|
|
528
|
+
end
|
|
502
529
|
|
|
503
|
-
|
|
504
|
-
return false unless opener_index
|
|
530
|
+
return false unless receiver_index && tokens[receiver_index].type == :identifier
|
|
505
531
|
|
|
506
|
-
|
|
507
|
-
|
|
532
|
+
receiver_name = tokens[receiver_index].lexeme
|
|
533
|
+
facts.types.key?(receiver_name) || facts.interfaces.key?(receiver_name)
|
|
534
|
+
end
|
|
508
535
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
536
|
+
def match_arm_binding_token?(tokens, index)
|
|
537
|
+
prev_tok = previous_non_trivia_token(tokens, index)
|
|
538
|
+
next_tok = next_non_trivia_token(tokens, index + 1)
|
|
539
|
+
prev_tok&.type == :as && next_tok&.type == :colon
|
|
513
540
|
end
|
|
514
541
|
|
|
515
|
-
|
|
542
|
+
def field_declaration_token?(tokens, index)
|
|
543
|
+
tok = tokens[index]
|
|
544
|
+
return false unless tok&.type == :identifier
|
|
545
|
+
return false unless first_non_trivia_token_on_line?(tokens, index)
|
|
546
|
+
return false if parameter_declaration_token?(tokens, index)
|
|
547
|
+
return false if match_arm_binding_token?(tokens, index)
|
|
516
548
|
|
|
517
|
-
|
|
518
|
-
|
|
549
|
+
next_tok = next_non_trivia_token(tokens, index + 1)
|
|
550
|
+
next_tok&.type == :colon
|
|
551
|
+
end
|
|
519
552
|
|
|
520
|
-
|
|
521
|
-
|
|
553
|
+
def destructure_let_binding?(tokens, index)
|
|
554
|
+
tok = tokens[index]
|
|
555
|
+
return false unless tok&.type == :identifier
|
|
522
556
|
|
|
523
|
-
|
|
524
|
-
|
|
557
|
+
line_tokens = non_trivia_tokens_on_line(tokens, tok.line)
|
|
558
|
+
return false unless line_tokens.length >= 3
|
|
525
559
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
return false unless lbracket_index
|
|
529
|
-
receiver_index = previous_non_trivia_token_index(tokens, lbracket_index)
|
|
530
|
-
end
|
|
560
|
+
first = line_tokens[0]
|
|
561
|
+
return false unless [:let, :var].include?(first.type)
|
|
531
562
|
|
|
532
|
-
|
|
563
|
+
eq_idx = line_tokens.index { |t| t.type == :equal }
|
|
564
|
+
lparen_idx = line_tokens.index { |t| t.type == :lparen }
|
|
565
|
+
return false unless lparen_idx
|
|
533
566
|
|
|
534
|
-
|
|
535
|
-
facts.types.key?(receiver_name) || facts.interfaces.key?(receiver_name)
|
|
536
|
-
end
|
|
567
|
+
return false if eq_idx && lparen_idx >= eq_idx
|
|
537
568
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
end
|
|
569
|
+
# let (a, b) = ...
|
|
570
|
+
if line_tokens[1]&.type == :lparen
|
|
571
|
+
return first.type == :let
|
|
572
|
+
end
|
|
543
573
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
return false unless tok&.type == :identifier
|
|
547
|
-
return false unless first_non_trivia_token_on_line?(tokens, index)
|
|
548
|
-
return false if parameter_declaration_token?(tokens, index)
|
|
549
|
-
return false if match_arm_binding_token?(tokens, index)
|
|
574
|
+
# let Vec2(x, y) = ... — identifier then lparen adjacency
|
|
575
|
+
return false unless line_tokens[1]&.type == :identifier && lparen_idx == 2
|
|
550
576
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
end
|
|
577
|
+
first.type == :let
|
|
578
|
+
end
|
|
554
579
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
580
|
+
def struct_event_declaration_token?(tokens, index)
|
|
581
|
+
tok = tokens[index]
|
|
582
|
+
return false unless tok&.type == :identifier
|
|
558
583
|
|
|
559
|
-
|
|
560
|
-
|
|
584
|
+
prev_tok = previous_non_trivia_token(tokens, index)
|
|
585
|
+
return false unless prev_tok&.type == :event
|
|
561
586
|
|
|
562
|
-
|
|
563
|
-
|
|
587
|
+
line_tokens = non_trivia_tokens_on_line(tokens, tok.line)
|
|
588
|
+
line_start = line_tokens.first
|
|
589
|
+
return false unless line_start && line_start.column > 1
|
|
564
590
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
591
|
+
i = index - 1
|
|
592
|
+
while i >= 0
|
|
593
|
+
current = tokens[i]
|
|
594
|
+
i -= 1
|
|
595
|
+
next if [:newline, :indent, :dedent, :eof].include?(current.type)
|
|
596
|
+
next if current.line == tok.line
|
|
597
|
+
next if current.column >= line_start.column
|
|
568
598
|
|
|
569
|
-
|
|
599
|
+
header_line_toks = non_trivia_tokens_on_line(tokens, current.line)
|
|
600
|
+
return header_line_toks.first&.type == :struct
|
|
601
|
+
end
|
|
570
602
|
|
|
571
|
-
|
|
572
|
-
if line_tokens[1]&.type == :lparen
|
|
573
|
-
return first.type == :let
|
|
603
|
+
false
|
|
574
604
|
end
|
|
575
605
|
|
|
576
|
-
|
|
577
|
-
|
|
606
|
+
def variant_payload_field_declaration_token?(tokens, index)
|
|
607
|
+
return false unless parameter_declaration_token?(tokens, index)
|
|
578
608
|
|
|
579
|
-
|
|
580
|
-
|
|
609
|
+
opener_index = parameter_list_opener_index(tokens, index)
|
|
610
|
+
return false unless opener_index
|
|
581
611
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
return false unless tok&.type == :identifier
|
|
585
|
-
|
|
586
|
-
prev_tok = previous_non_trivia_token(tokens, index)
|
|
587
|
-
return false unless prev_tok&.type == :event
|
|
612
|
+
head_index = previous_non_trivia_token_index(tokens, opener_index)
|
|
613
|
+
return false unless head_index
|
|
588
614
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
return false unless line_start && line_start.column > 1
|
|
615
|
+
variant_enum_member_declaration?(tokens, head_index)
|
|
616
|
+
end
|
|
592
617
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
current = tokens[i]
|
|
596
|
-
i -= 1
|
|
597
|
-
next if [:newline, :indent, :dedent, :eof].include?(current.type)
|
|
598
|
-
next if current.line == tok.line
|
|
599
|
-
next if current.column >= line_start.column
|
|
618
|
+
FOREIGN_PARAM_MODE_TOKENS = [:out, :in, :inout, :consuming].freeze
|
|
619
|
+
private_constant :FOREIGN_PARAM_MODE_TOKENS
|
|
600
620
|
|
|
601
|
-
|
|
602
|
-
|
|
621
|
+
def parameter_declaration_token?(tokens, index)
|
|
622
|
+
prev_tok = previous_non_trivia_token(tokens, index)
|
|
623
|
+
next_tok = next_non_trivia_token(tokens, index + 1)
|
|
624
|
+
next_tok&.type == :colon && prev_tok && (
|
|
625
|
+
[:lparen, :comma].include?(prev_tok.type) ||
|
|
626
|
+
FOREIGN_PARAM_MODE_TOKENS.include?(prev_tok.type)
|
|
627
|
+
)
|
|
603
628
|
end
|
|
604
629
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
def variant_payload_field_declaration_token?(tokens, index)
|
|
609
|
-
return false unless parameter_declaration_token?(tokens, index)
|
|
630
|
+
def callable_parameter_declaration_token?(tokens, index)
|
|
631
|
+
return false unless parameter_declaration_token?(tokens, index)
|
|
610
632
|
|
|
611
|
-
|
|
612
|
-
|
|
633
|
+
opener_index = parameter_list_opener_index(tokens, index)
|
|
634
|
+
return false unless opener_index
|
|
613
635
|
|
|
614
|
-
|
|
615
|
-
|
|
636
|
+
head_index = previous_non_trivia_token_index(tokens, opener_index)
|
|
637
|
+
return false unless head_index
|
|
616
638
|
|
|
617
|
-
|
|
618
|
-
|
|
639
|
+
head = tokens[head_index]
|
|
640
|
+
return true if [:fn, :proc].include?(head.type)
|
|
619
641
|
|
|
620
|
-
|
|
621
|
-
|
|
642
|
+
if head.type == :rbracket
|
|
643
|
+
lbracket_index = matching_opener_index(tokens, head_index)
|
|
644
|
+
return false unless lbracket_index
|
|
622
645
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
next_tok = next_non_trivia_token(tokens, index + 1)
|
|
626
|
-
next_tok&.type == :colon && prev_tok && (
|
|
627
|
-
[:lparen, :comma].include?(prev_tok.type) ||
|
|
628
|
-
FOREIGN_PARAM_MODE_TOKENS.include?(prev_tok.type)
|
|
629
|
-
)
|
|
630
|
-
end
|
|
646
|
+
head_index = previous_non_trivia_token_index(tokens, lbracket_index)
|
|
647
|
+
return false unless head_index
|
|
631
648
|
|
|
632
|
-
|
|
633
|
-
|
|
649
|
+
head = tokens[head_index]
|
|
650
|
+
end
|
|
634
651
|
|
|
635
|
-
|
|
636
|
-
return false unless opener_index
|
|
652
|
+
return false unless head.type == :identifier
|
|
637
653
|
|
|
638
|
-
|
|
639
|
-
|
|
654
|
+
previous_non_trivia_token(tokens, head_index)&.type == :function
|
|
655
|
+
end
|
|
640
656
|
|
|
641
|
-
|
|
642
|
-
|
|
657
|
+
def parameter_list_opener_index(tokens, index)
|
|
658
|
+
depth = 0
|
|
659
|
+
i = index - 1
|
|
660
|
+
while i >= 0
|
|
661
|
+
tok = tokens[i]
|
|
662
|
+
if tok.type == :rparen
|
|
663
|
+
depth += 1
|
|
664
|
+
elsif tok.type == :lparen
|
|
665
|
+
return i if depth.zero?
|
|
643
666
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
667
|
+
depth -= 1
|
|
668
|
+
end
|
|
669
|
+
i -= 1
|
|
670
|
+
end
|
|
647
671
|
|
|
648
|
-
|
|
649
|
-
|
|
672
|
+
nil
|
|
673
|
+
end
|
|
650
674
|
|
|
651
|
-
|
|
675
|
+
def lexically_declared_free_function_name?(tokens, name)
|
|
676
|
+
lexically_declared_free_function_names(tokens).include?(name)
|
|
652
677
|
end
|
|
653
678
|
|
|
654
|
-
|
|
679
|
+
def lexically_declared_free_function_names(tokens)
|
|
680
|
+
cache = @lexically_declared_free_function_name_cache ||= {}
|
|
681
|
+
cached = cache[tokens.object_id]
|
|
682
|
+
return cached if cached
|
|
655
683
|
|
|
656
|
-
|
|
657
|
-
|
|
684
|
+
cache[tokens.object_id] = tokens.each_with_index.each_with_object(Set.new) do |(token, index), names|
|
|
685
|
+
next unless token.type == :identifier
|
|
686
|
+
|
|
687
|
+
prev_index = previous_non_trivia_token_index(tokens, index)
|
|
688
|
+
next unless prev_index
|
|
658
689
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
while i >= 0
|
|
663
|
-
tok = tokens[i]
|
|
664
|
-
if tok.type == :rparen
|
|
665
|
-
depth += 1
|
|
666
|
-
elsif tok.type == :lparen
|
|
667
|
-
return i if depth.zero?
|
|
690
|
+
prev_tok = tokens[prev_index]
|
|
691
|
+
next unless [:function, :fn, :proc].include?(prev_tok.type)
|
|
692
|
+
next unless first_non_trivia_token_on_line?(tokens, prev_index)
|
|
668
693
|
|
|
669
|
-
|
|
694
|
+
names << token.lexeme
|
|
670
695
|
end
|
|
671
|
-
i -= 1
|
|
672
696
|
end
|
|
673
697
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
698
|
+
def generic_function_lexical_binding_semantic(facts, token)
|
|
699
|
+
kind = generic_function_lexical_binding_kind_at(facts, token.line, token.column, token.lexeme)
|
|
700
|
+
case kind
|
|
701
|
+
when :param
|
|
702
|
+
[:parameter, []]
|
|
703
|
+
when :variable
|
|
704
|
+
[:variable, []]
|
|
705
|
+
else
|
|
706
|
+
nil
|
|
707
|
+
end
|
|
708
|
+
end
|
|
680
709
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
710
|
+
def generic_function_lexical_binding_kind_at(facts, line, column, name)
|
|
711
|
+
generic_function_lexical_binding_scopes(facts).reverse_each do |scope|
|
|
712
|
+
next if line < scope[:start_line] || line > scope[:end_line]
|
|
713
|
+
next if line == scope[:start_line] && column < scope[:start_column]
|
|
685
714
|
|
|
686
|
-
|
|
687
|
-
|
|
715
|
+
kind = scope[:bindings][name]
|
|
716
|
+
return kind if kind
|
|
717
|
+
end
|
|
688
718
|
|
|
689
|
-
|
|
690
|
-
|
|
719
|
+
nil
|
|
720
|
+
end
|
|
691
721
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
722
|
+
def generic_function_lexical_binding_scopes(facts)
|
|
723
|
+
scopes = @generic_function_lexical_binding_scope_cache ||= {}
|
|
724
|
+
cached = scopes[facts.object_id]
|
|
725
|
+
unless cached
|
|
726
|
+
decls = Array(facts.ast&.declarations)
|
|
727
|
+
cached = decls.each_with_index.flat_map do |decl, index|
|
|
728
|
+
generic_function_lexical_scopes_for_declaration(
|
|
729
|
+
decl,
|
|
730
|
+
end_line: declaration_scope_end_line(decls, index),
|
|
731
|
+
)
|
|
732
|
+
end
|
|
733
|
+
scopes[facts.object_id] = cached
|
|
734
|
+
end
|
|
695
735
|
|
|
696
|
-
|
|
736
|
+
cached
|
|
697
737
|
end
|
|
698
|
-
end
|
|
699
738
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
739
|
+
def generic_function_lexical_scopes_for_declaration(decl, end_line: Float::INFINITY)
|
|
740
|
+
if decl.is_a?(AST::ExtendingBlock)
|
|
741
|
+
receiver_type_params = generic_type_parameter_names_for_extending_block(decl)
|
|
742
|
+
methods = Array(decl.methods)
|
|
743
|
+
return methods.each_with_index.flat_map do |method, index|
|
|
744
|
+
generic_method_lexical_scopes(
|
|
745
|
+
method,
|
|
746
|
+
receiver_type_params: receiver_type_params,
|
|
747
|
+
end_line: nested_declaration_scope_end_line(methods, index, fallback_end_line: end_line),
|
|
748
|
+
)
|
|
749
|
+
end
|
|
750
|
+
end
|
|
711
751
|
|
|
712
|
-
|
|
713
|
-
generic_function_lexical_binding_scopes(facts).reverse_each do |scope|
|
|
714
|
-
next if line < scope[:start_line] || line > scope[:end_line]
|
|
715
|
-
next if line == scope[:start_line] && column < scope[:start_column]
|
|
752
|
+
return [] unless generic_function_declaration?(decl)
|
|
716
753
|
|
|
717
|
-
|
|
718
|
-
return kind if kind
|
|
754
|
+
generic_callable_lexical_scopes(decl, end_line: generic_statement_list_end_line(decl.body, decl.line))
|
|
719
755
|
end
|
|
720
756
|
|
|
721
|
-
|
|
722
|
-
|
|
757
|
+
def generic_method_lexical_scopes(method, receiver_type_params:, end_line:)
|
|
758
|
+
return [] unless method.respond_to?(:body) && !method.body.nil?
|
|
759
|
+
return [] if receiver_type_params.empty? && Array(method.type_params).empty?
|
|
723
760
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
cached = decls.each_with_index.flat_map do |decl, index|
|
|
730
|
-
generic_function_lexical_scopes_for_declaration(
|
|
731
|
-
decl,
|
|
732
|
-
end_line: declaration_scope_end_line(decls, index),
|
|
733
|
-
)
|
|
734
|
-
end
|
|
735
|
-
scopes[facts.object_id] = cached
|
|
761
|
+
generic_callable_lexical_scopes(
|
|
762
|
+
method,
|
|
763
|
+
end_line:,
|
|
764
|
+
include_receiver: method.respond_to?(:kind) && method.kind != :static,
|
|
765
|
+
)
|
|
736
766
|
end
|
|
737
767
|
|
|
738
|
-
|
|
739
|
-
|
|
768
|
+
def generic_callable_lexical_scopes(decl, end_line:, include_receiver: false)
|
|
769
|
+
scopes = []
|
|
770
|
+
current_bindings = {}
|
|
771
|
+
current_bindings['this'] = :param if include_receiver
|
|
772
|
+
Array(decl.params).each do |param|
|
|
773
|
+
next unless param.respond_to?(:name)
|
|
740
774
|
|
|
741
|
-
|
|
742
|
-
if decl.is_a?(AST::ExtendingBlock)
|
|
743
|
-
receiver_type_params = generic_type_parameter_names_for_extending_block(decl)
|
|
744
|
-
methods = Array(decl.methods)
|
|
745
|
-
return methods.each_with_index.flat_map do |method, index|
|
|
746
|
-
generic_method_lexical_scopes(
|
|
747
|
-
method,
|
|
748
|
-
receiver_type_params: receiver_type_params,
|
|
749
|
-
end_line: nested_declaration_scope_end_line(methods, index, fallback_end_line: end_line),
|
|
750
|
-
)
|
|
775
|
+
current_bindings[param.name] = :param
|
|
751
776
|
end
|
|
752
|
-
end
|
|
753
777
|
|
|
754
|
-
|
|
778
|
+
unless current_bindings.empty?
|
|
779
|
+
scopes << {
|
|
780
|
+
start_line: decl.line,
|
|
781
|
+
start_column: 0,
|
|
782
|
+
end_line: end_line,
|
|
783
|
+
bindings: current_bindings.dup,
|
|
784
|
+
}
|
|
785
|
+
end
|
|
755
786
|
|
|
756
|
-
|
|
757
|
-
end
|
|
787
|
+
collect_generic_function_local_scopes(Array(decl.body), current_bindings, end_line, scopes)
|
|
758
788
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
return [] if receiver_type_params.empty? && Array(method.type_params).empty?
|
|
789
|
+
scopes
|
|
790
|
+
end
|
|
762
791
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
792
|
+
def generic_function_declaration?(decl)
|
|
793
|
+
decl.respond_to?(:type_params) &&
|
|
794
|
+
Array(decl.type_params).any? &&
|
|
795
|
+
decl.respond_to?(:params) &&
|
|
796
|
+
decl.respond_to?(:body) &&
|
|
797
|
+
!decl.body.nil?
|
|
798
|
+
end
|
|
769
799
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
800
|
+
def collect_generic_function_local_scopes(statements, current_bindings, block_end_line, scopes)
|
|
801
|
+
active_bindings = current_bindings.dup
|
|
802
|
+
Array(statements).each do |statement|
|
|
803
|
+
case statement
|
|
804
|
+
when AST::LocalDecl
|
|
805
|
+
active_bindings[statement.name] = statement.kind == :var ? :var : :let
|
|
806
|
+
scopes << generic_binding_scope(statement, active_bindings, block_end_line)
|
|
807
|
+
when AST::IfStmt
|
|
808
|
+
Array(statement.branches).each do |branch|
|
|
809
|
+
branch_body = Array(branch.body)
|
|
810
|
+
branch_end_line = generic_statement_list_end_line(branch_body, statement.line)
|
|
811
|
+
collect_generic_function_local_scopes(branch_body, active_bindings, branch_end_line, scopes)
|
|
812
|
+
end
|
|
776
813
|
|
|
777
|
-
|
|
814
|
+
else_body = Array(statement.else_body)
|
|
815
|
+
unless else_body.empty?
|
|
816
|
+
else_end_line = generic_statement_list_end_line(else_body, statement.line)
|
|
817
|
+
collect_generic_function_local_scopes(else_body, active_bindings, else_end_line, scopes)
|
|
818
|
+
end
|
|
819
|
+
when AST::MatchStmt
|
|
820
|
+
Array(statement.arms).each do |arm|
|
|
821
|
+
arm_bindings = active_bindings.dup
|
|
822
|
+
arm_body = Array(arm.body)
|
|
823
|
+
arm_end_line = generic_statement_list_end_line(arm_body, statement.line)
|
|
824
|
+
if arm.respond_to?(:binding_name) && arm.binding_name
|
|
825
|
+
arm_bindings[arm.binding_name] = :let
|
|
826
|
+
scopes << generic_binding_scope(arm, arm_bindings, arm_end_line)
|
|
827
|
+
end
|
|
828
|
+
collect_generic_function_local_scopes(arm_body, arm_bindings, arm_end_line, scopes)
|
|
829
|
+
end
|
|
830
|
+
when AST::UnsafeStmt, AST::WhileStmt, AST::DeferStmt
|
|
831
|
+
body = Array(statement.body)
|
|
832
|
+
body_end_line = generic_statement_list_end_line(body, statement.line)
|
|
833
|
+
collect_generic_function_local_scopes(body, active_bindings, body_end_line, scopes)
|
|
834
|
+
when AST::ForStmt
|
|
835
|
+
next unless statement.respond_to?(:name) && statement.name
|
|
836
|
+
|
|
837
|
+
body = Array(statement.body)
|
|
838
|
+
body_end_line = generic_statement_list_end_line(body, statement.line)
|
|
839
|
+
for_bindings = active_bindings.dup
|
|
840
|
+
for_bindings[statement.name] = :let
|
|
841
|
+
scopes << generic_binding_scope(statement, for_bindings, body_end_line)
|
|
842
|
+
collect_generic_function_local_scopes(body, for_bindings, body_end_line, scopes)
|
|
843
|
+
end
|
|
844
|
+
end
|
|
778
845
|
end
|
|
779
846
|
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
start_line:
|
|
783
|
-
start_column: 0,
|
|
847
|
+
def generic_binding_scope(node, bindings, end_line)
|
|
848
|
+
{
|
|
849
|
+
start_line: node.line ? node.line : 0,
|
|
850
|
+
start_column: node.column ? node.column : 0,
|
|
784
851
|
end_line: end_line,
|
|
785
|
-
bindings:
|
|
852
|
+
bindings: bindings.dup,
|
|
786
853
|
}
|
|
787
854
|
end
|
|
788
855
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
856
|
+
def generic_statement_list_end_line(statements, fallback_line)
|
|
857
|
+
Array(statements).reduce(fallback_line || 0) do |max_line, statement|
|
|
858
|
+
[max_line, generic_statement_end_line(statement)].compact.max
|
|
859
|
+
end
|
|
860
|
+
end
|
|
793
861
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
Array(decl.type_params).any? &&
|
|
797
|
-
decl.respond_to?(:params) &&
|
|
798
|
-
decl.respond_to?(:body) &&
|
|
799
|
-
!decl.body.nil?
|
|
800
|
-
end
|
|
862
|
+
def generic_statement_end_line(statement)
|
|
863
|
+
return 0 unless statement
|
|
801
864
|
|
|
802
|
-
def collect_generic_function_local_scopes(statements, current_bindings, block_end_line, scopes)
|
|
803
|
-
active_bindings = current_bindings.dup
|
|
804
|
-
Array(statements).each do |statement|
|
|
805
865
|
case statement
|
|
806
|
-
when AST::LocalDecl
|
|
807
|
-
active_bindings[statement.name] = statement.kind == :var ? :var : :let
|
|
808
|
-
scopes << generic_binding_scope(statement, active_bindings, block_end_line)
|
|
809
866
|
when AST::IfStmt
|
|
810
|
-
Array(statement.branches).
|
|
811
|
-
|
|
812
|
-
branch_end_line = generic_statement_list_end_line(branch_body, statement.line)
|
|
813
|
-
collect_generic_function_local_scopes(branch_body, active_bindings, branch_end_line, scopes)
|
|
814
|
-
end
|
|
815
|
-
|
|
816
|
-
else_body = Array(statement.else_body)
|
|
817
|
-
unless else_body.empty?
|
|
818
|
-
else_end_line = generic_statement_list_end_line(else_body, statement.line)
|
|
819
|
-
collect_generic_function_local_scopes(else_body, active_bindings, else_end_line, scopes)
|
|
867
|
+
branch_lines = Array(statement.branches).map do |branch|
|
|
868
|
+
generic_statement_list_end_line(Array(branch.body), branch.line || statement.line)
|
|
820
869
|
end
|
|
870
|
+
else_line = generic_statement_list_end_line(Array(statement.else_body), statement.line)
|
|
871
|
+
([statement.line, else_line] + branch_lines).compact.max
|
|
821
872
|
when AST::MatchStmt
|
|
822
|
-
Array(statement.arms).
|
|
823
|
-
|
|
824
|
-
arm_body = Array(arm.body)
|
|
825
|
-
arm_end_line = generic_statement_list_end_line(arm_body, statement.line)
|
|
826
|
-
if arm.respond_to?(:binding_name) && arm.binding_name
|
|
827
|
-
arm_bindings[arm.binding_name] = :let
|
|
828
|
-
scopes << generic_binding_scope(arm, arm_bindings, arm_end_line)
|
|
829
|
-
end
|
|
830
|
-
collect_generic_function_local_scopes(arm_body, arm_bindings, arm_end_line, scopes)
|
|
873
|
+
arm_lines = Array(statement.arms).map do |arm|
|
|
874
|
+
generic_statement_list_end_line(Array(arm.body), arm.line || statement.line)
|
|
831
875
|
end
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
next unless statement.respond_to?(:name) && statement.name
|
|
838
|
-
|
|
839
|
-
body = Array(statement.body)
|
|
840
|
-
body_end_line = generic_statement_list_end_line(body, statement.line)
|
|
841
|
-
for_bindings = active_bindings.dup
|
|
842
|
-
for_bindings[statement.name] = :let
|
|
843
|
-
scopes << generic_binding_scope(statement, for_bindings, body_end_line)
|
|
844
|
-
collect_generic_function_local_scopes(body, for_bindings, body_end_line, scopes)
|
|
876
|
+
([statement.line] + arm_lines).compact.max
|
|
877
|
+
when AST::UnsafeStmt, AST::WhileStmt, AST::ForStmt, AST::DeferStmt
|
|
878
|
+
[statement.line, generic_statement_list_end_line(Array(statement.body), statement.line)].compact.max
|
|
879
|
+
else
|
|
880
|
+
statement.line || 0
|
|
845
881
|
end
|
|
846
882
|
end
|
|
847
|
-
end
|
|
848
883
|
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
start_column: node.respond_to?(:column) && node.column ? node.column : 0,
|
|
853
|
-
end_line: end_line,
|
|
854
|
-
bindings: bindings.dup,
|
|
855
|
-
}
|
|
856
|
-
end
|
|
884
|
+
def namespace_keyword_token?(tokens, index)
|
|
885
|
+
tok = tokens[index]
|
|
886
|
+
return false unless tok && Token::KEYWORDS.value?(tok.type)
|
|
857
887
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
[max_line, generic_statement_end_line(statement)].compact.max
|
|
861
|
-
end
|
|
862
|
-
end
|
|
863
|
-
|
|
864
|
-
def generic_statement_end_line(statement)
|
|
865
|
-
return 0 unless statement
|
|
888
|
+
import_path_info_at(tokens, index, allow_keywords: true) ||
|
|
889
|
+
module_declaration_path_token?(tokens, index, allow_keywords: true)
|
|
866
890
|
|
|
867
|
-
case statement
|
|
868
|
-
when AST::IfStmt
|
|
869
|
-
branch_lines = Array(statement.branches).map do |branch|
|
|
870
|
-
generic_statement_list_end_line(Array(branch.body), branch.respond_to?(:line) ? branch.line : statement.line)
|
|
871
|
-
end
|
|
872
|
-
else_line = generic_statement_list_end_line(Array(statement.else_body), statement.line)
|
|
873
|
-
([statement.line, else_line] + branch_lines).compact.max
|
|
874
|
-
when AST::MatchStmt
|
|
875
|
-
arm_lines = Array(statement.arms).map do |arm|
|
|
876
|
-
generic_statement_list_end_line(Array(arm.body), arm.respond_to?(:line) ? arm.line : statement.line)
|
|
877
|
-
end
|
|
878
|
-
([statement.line] + arm_lines).compact.max
|
|
879
|
-
when AST::UnsafeStmt, AST::WhileStmt, AST::ForStmt, AST::DeferStmt
|
|
880
|
-
[statement.line, generic_statement_list_end_line(Array(statement.body), statement.line)].compact.max
|
|
881
|
-
else
|
|
882
|
-
statement.respond_to?(:line) ? statement.line : 0
|
|
883
891
|
end
|
|
884
|
-
end
|
|
885
|
-
|
|
886
|
-
def namespace_keyword_token?(tokens, index)
|
|
887
|
-
tok = tokens[index]
|
|
888
|
-
return false unless tok && Token::KEYWORDS.value?(tok.type)
|
|
889
892
|
|
|
890
|
-
|
|
891
|
-
|
|
893
|
+
def local_semantic_value_binding(facts, token, allow_same_line_future: false)
|
|
894
|
+
char = token.column - 1
|
|
895
|
+
[token.line - 1, token.line].uniq.each do |line|
|
|
896
|
+
frame = enclosing_completion_frame(facts, line)
|
|
897
|
+
next unless frame
|
|
892
898
|
|
|
893
|
-
|
|
899
|
+
snapshot = latest_completion_snapshot(frame, line, char)
|
|
900
|
+
binding = snapshot&.bindings&.dig(token.lexeme)
|
|
901
|
+
return binding if binding
|
|
894
902
|
|
|
895
|
-
|
|
896
|
-
char = token.column - 1
|
|
897
|
-
[token.line - 1, token.line].uniq.each do |line|
|
|
898
|
-
frame = enclosing_completion_frame(facts, line)
|
|
899
|
-
next unless frame
|
|
903
|
+
next unless allow_same_line_future
|
|
900
904
|
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
905
|
+
future_snapshot = same_line_future_completion_snapshot(frame, line, char)
|
|
906
|
+
binding = future_snapshot&.bindings&.dig(token.lexeme)
|
|
907
|
+
return binding if binding
|
|
908
|
+
end
|
|
904
909
|
|
|
905
|
-
|
|
910
|
+
nil
|
|
911
|
+
end
|
|
906
912
|
|
|
907
|
-
|
|
908
|
-
binding
|
|
909
|
-
|
|
913
|
+
def semantic_value_binding_entry(binding, declaration: false)
|
|
914
|
+
case binding.kind
|
|
915
|
+
when :param
|
|
916
|
+
modifiers = []
|
|
917
|
+
modifiers << 'declaration' if declaration
|
|
918
|
+
[:parameter, modifiers]
|
|
919
|
+
when :const, :let
|
|
920
|
+
[:variable, ['readonly']]
|
|
921
|
+
else
|
|
922
|
+
modifiers = []
|
|
923
|
+
modifiers << 'declaration' if declaration
|
|
924
|
+
[:variable, modifiers]
|
|
925
|
+
end
|
|
910
926
|
end
|
|
911
927
|
|
|
912
|
-
|
|
913
|
-
|
|
928
|
+
def resolved_call_callee_semantic(name, token, parameter_declaration, facts)
|
|
929
|
+
if (binding = local_semantic_value_binding(facts, token, allow_same_line_future: parameter_declaration))
|
|
930
|
+
return semantic_value_binding_entry(binding, declaration: binding.kind == :param && parameter_declaration)
|
|
931
|
+
end
|
|
932
|
+
|
|
933
|
+
if (binding = facts.values[name])
|
|
934
|
+
return semantic_value_binding_entry(binding)
|
|
935
|
+
end
|
|
914
936
|
|
|
915
|
-
def semantic_value_binding_entry(binding, declaration: false)
|
|
916
|
-
case binding.kind
|
|
917
|
-
when :param
|
|
918
|
-
modifiers = []
|
|
919
|
-
modifiers << 'declaration' if declaration
|
|
920
|
-
[:parameter, modifiers]
|
|
921
|
-
when :const, :let
|
|
922
|
-
[:variable, ['readonly']]
|
|
923
|
-
else
|
|
924
937
|
modifiers = []
|
|
925
|
-
modifiers << '
|
|
926
|
-
[:
|
|
927
|
-
|
|
928
|
-
|
|
938
|
+
modifiers << 'defaultLibrary' if BUILTIN_FUNCTION_NAMES.include?(name)
|
|
939
|
+
return [:function, modifiers] if BUILTIN_FUNCTION_NAMES.include?(name)
|
|
940
|
+
return [:function, modifiers] if facts.functions.key?(name)
|
|
941
|
+
return [:type, []] if constructible_semantic_type?(facts.types[name])
|
|
929
942
|
|
|
930
|
-
|
|
931
|
-
if (binding = local_semantic_value_binding(facts, token, allow_same_line_future: parameter_declaration))
|
|
932
|
-
return semantic_value_binding_entry(binding, declaration: binding.kind == :param && parameter_declaration)
|
|
943
|
+
nil
|
|
933
944
|
end
|
|
934
945
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
946
|
+
def callable_field_member_access?(name, tokens, index, facts)
|
|
947
|
+
next_tok = next_non_trivia_token(tokens, index + 1)
|
|
948
|
+
return false unless next_tok&.type == :lparen
|
|
938
949
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
return [:function, modifiers] if BUILTIN_FUNCTION_NAMES.include?(name)
|
|
942
|
-
return [:function, modifiers] if facts.functions.key?(name)
|
|
943
|
-
return [:type, []] if constructible_semantic_type?(facts.types[name])
|
|
950
|
+
dot_index = previous_non_trivia_token_index(tokens, index)
|
|
951
|
+
return false unless dot_index && tokens[dot_index].type == :dot
|
|
944
952
|
|
|
945
|
-
|
|
946
|
-
|
|
953
|
+
receiver_index = previous_non_trivia_token_index(tokens, dot_index)
|
|
954
|
+
return false unless receiver_index
|
|
947
955
|
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
return false unless next_tok&.type == :lparen
|
|
956
|
+
receiver_tok = tokens[receiver_index]
|
|
957
|
+
return false unless receiver_tok.type == :identifier
|
|
951
958
|
|
|
952
|
-
|
|
953
|
-
|
|
959
|
+
resolve_receiver_value_type(facts, receiver_tok).then do |receiver_type|
|
|
960
|
+
next false unless receiver_type
|
|
954
961
|
|
|
955
|
-
|
|
956
|
-
|
|
962
|
+
field_receiver_type = project_field_receiver_type_for_completion(receiver_type, facts)
|
|
963
|
+
next false unless field_receiver_type.respond_to?(:field)
|
|
957
964
|
|
|
958
|
-
|
|
959
|
-
|
|
965
|
+
callable_semantic_type?(field_receiver_type.field(name))
|
|
966
|
+
end
|
|
967
|
+
end
|
|
960
968
|
|
|
961
|
-
resolve_receiver_value_type(facts,
|
|
962
|
-
|
|
969
|
+
def resolve_receiver_value_type(facts, token)
|
|
970
|
+
char = token.column
|
|
963
971
|
|
|
964
|
-
|
|
965
|
-
|
|
972
|
+
[token.line - 1, token.line].uniq.each do |line|
|
|
973
|
+
receiver_type = resolve_dot_receiver_value_type(facts, token.lexeme, line, char)
|
|
974
|
+
return receiver_type if receiver_type
|
|
975
|
+
end
|
|
966
976
|
|
|
967
|
-
|
|
977
|
+
nil
|
|
968
978
|
end
|
|
969
|
-
end
|
|
970
979
|
|
|
971
|
-
|
|
972
|
-
|
|
980
|
+
def callable_semantic_type?(type)
|
|
981
|
+
type.is_a?(Types::Function) || type.is_a?(Types::Proc)
|
|
982
|
+
end
|
|
973
983
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
return
|
|
984
|
+
def known_type_name?(facts, name)
|
|
985
|
+
return false unless facts
|
|
986
|
+
return true if facts.types.key?(name)
|
|
987
|
+
facts.types.each_value do |type|
|
|
988
|
+
return true if type.respond_to?(:nested_types) && type.nested_types.key?(name)
|
|
989
|
+
end
|
|
990
|
+
false
|
|
977
991
|
end
|
|
978
992
|
|
|
979
|
-
|
|
980
|
-
|
|
993
|
+
def dot_nested_type_member?(tokens, index, facts)
|
|
994
|
+
return false unless facts
|
|
981
995
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
996
|
+
dot_index = index - 1
|
|
997
|
+
return false unless dot_index >= 0 && tokens[dot_index].type == :dot
|
|
998
|
+
|
|
999
|
+
receiver_index = previous_non_trivia_token_index(tokens, dot_index)
|
|
1000
|
+
return false unless receiver_index && tokens[receiver_index].type == :identifier
|
|
985
1001
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1002
|
+
receiver_name = tokens[receiver_index].lexeme
|
|
1003
|
+
type = resolve_struct_type_name(facts, receiver_name)
|
|
1004
|
+
return false unless type.is_a?(Types::Struct)
|
|
1005
|
+
|
|
1006
|
+
member_name = tokens[index].lexeme
|
|
1007
|
+
type.nested_types.key?(member_name)
|
|
991
1008
|
end
|
|
992
|
-
false
|
|
993
|
-
end
|
|
994
1009
|
|
|
995
|
-
|
|
996
|
-
|
|
1010
|
+
def resolve_struct_type_name(facts, name)
|
|
1011
|
+
type = facts.types[name]
|
|
1012
|
+
return type if type.is_a?(Types::Struct)
|
|
1013
|
+
facts.types.each_value do |t|
|
|
1014
|
+
next unless t.respond_to?(:nested_types)
|
|
1015
|
+
found = t.nested_types[name]
|
|
1016
|
+
return found if found.is_a?(Types::Struct)
|
|
1017
|
+
end
|
|
1018
|
+
nil
|
|
1019
|
+
end
|
|
997
1020
|
|
|
998
|
-
|
|
999
|
-
|
|
1021
|
+
def constructible_semantic_type?(type)
|
|
1022
|
+
type.is_a?(Types::Struct) || type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::StringView) || type.is_a?(Types::Task) || type.is_a?(Types::Vector) || type.is_a?(Types::Matrix) || type.is_a?(Types::Quaternion)
|
|
1023
|
+
end
|
|
1000
1024
|
|
|
1001
|
-
|
|
1002
|
-
|
|
1025
|
+
def bare_builtin_specialization?(name, tokens, index)
|
|
1026
|
+
return false unless name == 'zero' || name == 'default'
|
|
1003
1027
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
return false unless type.is_a?(Types::Struct)
|
|
1028
|
+
next_index = next_non_trivia_token_index(tokens, index + 1)
|
|
1029
|
+
return false unless next_index && tokens[next_index].type == :lbracket
|
|
1007
1030
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
end
|
|
1031
|
+
rbracket_index = matching_closer_index(tokens, next_index, :lbracket, :rbracket)
|
|
1032
|
+
return false unless rbracket_index
|
|
1011
1033
|
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
return type if type.is_a?(Types::Struct)
|
|
1015
|
-
facts.types.each_value do |t|
|
|
1016
|
-
next unless t.respond_to?(:nested_types)
|
|
1017
|
-
found = t.nested_types[name]
|
|
1018
|
-
return found if found.is_a?(Types::Struct)
|
|
1034
|
+
after_bracket_index = next_non_trivia_token_index(tokens, rbracket_index + 1)
|
|
1035
|
+
after_bracket_index.nil? || tokens[after_bracket_index].type != :lparen
|
|
1019
1036
|
end
|
|
1020
|
-
nil
|
|
1021
|
-
end
|
|
1022
1037
|
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1038
|
+
def bare_function_value_identifier_site?(facts, token)
|
|
1039
|
+
facts.functions.key?(token.lexeme) &&
|
|
1040
|
+
facts.callable_value_identifier_sites.fetch([token.line, token.column], false)
|
|
1041
|
+
end
|
|
1026
1042
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1043
|
+
def imported_module_function_value_member_access_site?(facts, tokens, index)
|
|
1044
|
+
dot_index = previous_non_trivia_token_index(tokens, index)
|
|
1045
|
+
return false unless dot_index && tokens[dot_index].type == :dot
|
|
1029
1046
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1047
|
+
receiver_index = previous_non_trivia_token_index(tokens, dot_index)
|
|
1048
|
+
return false unless receiver_index
|
|
1032
1049
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1050
|
+
receiver = tokens[receiver_index]
|
|
1051
|
+
return false unless receiver.type == :identifier
|
|
1035
1052
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1053
|
+
facts.callable_value_member_access_sites.fetch(
|
|
1054
|
+
[receiver.lexeme, receiver.line, receiver.column, tokens[index].lexeme],
|
|
1055
|
+
false,
|
|
1056
|
+
)
|
|
1057
|
+
end
|
|
1039
1058
|
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
end
|
|
1059
|
+
def imported_module_binding_for_member(tokens, index, facts)
|
|
1060
|
+
dot_index = previous_non_trivia_token_index(tokens, index)
|
|
1061
|
+
return nil unless dot_index && tokens[dot_index].type == :dot
|
|
1044
1062
|
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
return false unless dot_index && tokens[dot_index].type == :dot
|
|
1063
|
+
receiver_index = previous_non_trivia_token_index(tokens, dot_index)
|
|
1064
|
+
return nil unless receiver_index
|
|
1048
1065
|
|
|
1049
|
-
|
|
1050
|
-
|
|
1066
|
+
receiver = tokens[receiver_index]
|
|
1067
|
+
return nil unless receiver.type == :identifier
|
|
1051
1068
|
|
|
1052
|
-
|
|
1053
|
-
|
|
1069
|
+
facts.imports[receiver.lexeme]
|
|
1070
|
+
end
|
|
1054
1071
|
|
|
1055
|
-
facts
|
|
1056
|
-
|
|
1057
|
-
false
|
|
1058
|
-
)
|
|
1059
|
-
end
|
|
1072
|
+
def static_type_member_access?(tokens, index, facts)
|
|
1073
|
+
receiver_info = dot_type_receiver_info(tokens, index, facts)
|
|
1074
|
+
return false unless receiver_info
|
|
1060
1075
|
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
return nil unless dot_index && tokens[dot_index].type == :dot
|
|
1076
|
+
!static_method_binding_for_receiver(facts, receiver_info[:type], tokens[index].lexeme).nil?
|
|
1077
|
+
end
|
|
1064
1078
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1079
|
+
def dot_type_receiver_info(tokens, index, facts)
|
|
1080
|
+
dot_index = previous_non_trivia_token_index(tokens, index)
|
|
1081
|
+
return nil unless dot_index && tokens[dot_index].type == :dot
|
|
1067
1082
|
|
|
1068
|
-
|
|
1069
|
-
|
|
1083
|
+
receiver_index = previous_non_trivia_token_index(tokens, dot_index)
|
|
1084
|
+
return nil unless receiver_index
|
|
1070
1085
|
|
|
1071
|
-
|
|
1072
|
-
|
|
1086
|
+
if tokens[receiver_index].type == :rbracket
|
|
1087
|
+
lbracket_index = matching_opener_index(tokens, receiver_index)
|
|
1088
|
+
return nil unless lbracket_index
|
|
1073
1089
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1090
|
+
receiver_index = previous_non_trivia_token_index(tokens, lbracket_index)
|
|
1091
|
+
return nil unless receiver_index
|
|
1092
|
+
end
|
|
1077
1093
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1094
|
+
receiver = tokens[receiver_index]
|
|
1095
|
+
return nil unless receiver.type == :identifier
|
|
1080
1096
|
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
return nil unless dot_index && tokens[dot_index].type == :dot
|
|
1097
|
+
receiver_name = receiver.lexeme
|
|
1098
|
+
receiver_path = receiver_name
|
|
1084
1099
|
|
|
1085
|
-
|
|
1086
|
-
|
|
1100
|
+
module_dot_index = previous_non_trivia_token_index(tokens, receiver_index)
|
|
1101
|
+
if module_dot_index && tokens[module_dot_index].type == :dot
|
|
1102
|
+
module_index = previous_non_trivia_token_index(tokens, module_dot_index)
|
|
1103
|
+
return nil unless module_index && tokens[module_index].type == :identifier
|
|
1087
1104
|
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
return nil unless lbracket_index
|
|
1105
|
+
receiver_path = "#{tokens[module_index].lexeme}.#{receiver_name}"
|
|
1106
|
+
end
|
|
1091
1107
|
|
|
1092
|
-
|
|
1093
|
-
return nil unless receiver_index
|
|
1108
|
+
resolve_type_receiver_info(facts, receiver_name, receiver_path)
|
|
1094
1109
|
end
|
|
1095
1110
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
receiver_name = receiver.lexeme
|
|
1100
|
-
receiver_path = receiver_name
|
|
1111
|
+
def specialized_call_with_type_args?(tokens, index)
|
|
1112
|
+
next_index = next_non_trivia_token_index(tokens, index + 1)
|
|
1113
|
+
return false unless next_index && tokens[next_index].type == :lbracket
|
|
1101
1114
|
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
module_index = previous_non_trivia_token_index(tokens, module_dot_index)
|
|
1105
|
-
return nil unless module_index && tokens[module_index].type == :identifier
|
|
1115
|
+
rbracket_index = matching_closer_index(tokens, next_index, :lbracket, :rbracket)
|
|
1116
|
+
return false unless rbracket_index
|
|
1106
1117
|
|
|
1107
|
-
|
|
1118
|
+
after_bracket_index = next_non_trivia_token_index(tokens, rbracket_index + 1)
|
|
1119
|
+
after_bracket_index && tokens[after_bracket_index].type == :lparen
|
|
1108
1120
|
end
|
|
1109
1121
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1122
|
+
def identifier_in_type_argument_position?(tokens, index)
|
|
1123
|
+
lbracket_index = previous_non_trivia_token_index(tokens, index)
|
|
1124
|
+
return false unless lbracket_index
|
|
1112
1125
|
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1126
|
+
if tokens[lbracket_index].type == :comma
|
|
1127
|
+
depth = 0
|
|
1128
|
+
i = lbracket_index - 1
|
|
1129
|
+
lbracket_index = nil
|
|
1130
|
+
while i >= 0
|
|
1131
|
+
tok = tokens[i]
|
|
1132
|
+
if tok.type == :rbracket
|
|
1133
|
+
depth += 1
|
|
1134
|
+
elsif tok.type == :lbracket
|
|
1135
|
+
if depth.zero?
|
|
1136
|
+
lbracket_index = i
|
|
1137
|
+
break
|
|
1138
|
+
end
|
|
1116
1139
|
|
|
1117
|
-
|
|
1118
|
-
|
|
1140
|
+
depth -= 1
|
|
1141
|
+
end
|
|
1142
|
+
i -= 1
|
|
1143
|
+
end
|
|
1144
|
+
end
|
|
1119
1145
|
|
|
1120
|
-
|
|
1121
|
-
after_bracket_index && tokens[after_bracket_index].type == :lparen
|
|
1122
|
-
end
|
|
1146
|
+
return false unless lbracket_index && tokens[lbracket_index].type == :lbracket
|
|
1123
1147
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
return false unless lbracket_index
|
|
1148
|
+
rbracket_index = matching_closer_index(tokens, lbracket_index, :lbracket, :rbracket)
|
|
1149
|
+
return false unless rbracket_index
|
|
1127
1150
|
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
i = lbracket_index - 1
|
|
1131
|
-
lbracket_index = nil
|
|
1132
|
-
while i >= 0
|
|
1133
|
-
tok = tokens[i]
|
|
1134
|
-
if tok.type == :rbracket
|
|
1135
|
-
depth += 1
|
|
1136
|
-
elsif tok.type == :lbracket
|
|
1137
|
-
if depth.zero?
|
|
1138
|
-
lbracket_index = i
|
|
1139
|
-
break
|
|
1140
|
-
end
|
|
1151
|
+
next_index = next_non_trivia_token_index(tokens, index + 1)
|
|
1152
|
+
return false unless next_index
|
|
1141
1153
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
i -= 1
|
|
1145
|
-
end
|
|
1154
|
+
# Type argument entries should stay inside the current [] pair.
|
|
1155
|
+
next_index <= rbracket_index
|
|
1146
1156
|
end
|
|
1147
1157
|
|
|
1148
|
-
|
|
1158
|
+
def type_parameter_declaration_token?(facts, tokens, index)
|
|
1159
|
+
info = type_parameter_declaration_info_on_line(tokens, tokens[index].line)
|
|
1160
|
+
info && info[:tokens].any? { |token| token.equal?(tokens[index]) }
|
|
1161
|
+
end
|
|
1149
1162
|
|
|
1150
|
-
|
|
1151
|
-
|
|
1163
|
+
def type_parameter_reference_token?(facts, tokens, index)
|
|
1164
|
+
tok = tokens[index]
|
|
1165
|
+
return false unless type_parameter_names_in_scope(facts, tok.line).include?(tok.lexeme)
|
|
1166
|
+
return false if type_parameter_declaration_token?(facts, tokens, index)
|
|
1152
1167
|
|
|
1153
|
-
|
|
1154
|
-
|
|
1168
|
+
identifier_in_type_parameter_reference_position?(tokens, index)
|
|
1169
|
+
end
|
|
1155
1170
|
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
end
|
|
1171
|
+
def identifier_in_type_parameter_reference_position?(tokens, index)
|
|
1172
|
+
return true if identifier_in_type_argument_position?(tokens, index)
|
|
1159
1173
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
end
|
|
1174
|
+
prev_tok = previous_non_trivia_token(tokens, index)
|
|
1175
|
+
[:colon, :arrow].include?(prev_tok&.type)
|
|
1176
|
+
end
|
|
1164
1177
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
return false unless type_parameter_names_in_scope(facts, tok.line).include?(tok.lexeme)
|
|
1168
|
-
return false if type_parameter_declaration_token?(facts, tokens, index)
|
|
1178
|
+
def identifier_in_type_reference_position?(tokens, index)
|
|
1179
|
+
return true if identifier_in_type_argument_position?(tokens, index)
|
|
1169
1180
|
|
|
1170
|
-
|
|
1171
|
-
|
|
1181
|
+
prev_tok = previous_non_trivia_token(tokens, index)
|
|
1182
|
+
return true if [:colon, :arrow, :as].include?(prev_tok&.type)
|
|
1172
1183
|
|
|
1173
|
-
|
|
1174
|
-
|
|
1184
|
+
line_tokens = non_trivia_tokens_on_line(tokens, tokens[index].line)
|
|
1185
|
+
return true if prev_tok&.type == :equal && line_tokens.first&.type == :type
|
|
1175
1186
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
end
|
|
1187
|
+
next_index = next_non_trivia_token_index(tokens, index + 1)
|
|
1188
|
+
return false unless next_index && tokens[next_index].type == :less
|
|
1179
1189
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1190
|
+
minus_index = next_non_trivia_token_index(tokens, next_index + 1)
|
|
1191
|
+
return false unless minus_index && tokens[minus_index].type == :minus
|
|
1182
1192
|
|
|
1183
|
-
|
|
1184
|
-
|
|
1193
|
+
tokens[next_index].line == tokens[index].line &&
|
|
1194
|
+
tokens[next_index].column == (tokens[index].column + tokens[index].lexeme.length) &&
|
|
1195
|
+
tokens[minus_index].line == tokens[next_index].line &&
|
|
1196
|
+
tokens[minus_index].column == (tokens[next_index].column + tokens[next_index].lexeme.length)
|
|
1197
|
+
end
|
|
1185
1198
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1199
|
+
def type_parameter_declaration_info_on_line(tokens, line)
|
|
1200
|
+
line_tokens = non_trivia_tokens_on_line(tokens, line)
|
|
1201
|
+
return nil if line_tokens.empty?
|
|
1188
1202
|
|
|
1189
|
-
|
|
1190
|
-
|
|
1203
|
+
header_index = line_tokens.index { |line_tok| generic_type_parameter_header_token?(line_tok.type) }
|
|
1204
|
+
return nil unless header_index
|
|
1191
1205
|
|
|
1192
|
-
|
|
1193
|
-
|
|
1206
|
+
name_index = ((header_index + 1)...line_tokens.length).find { |i| line_tokens[i].type == :identifier }
|
|
1207
|
+
return nil unless name_index
|
|
1194
1208
|
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
tokens[minus_index].line == tokens[next_index].line &&
|
|
1198
|
-
tokens[minus_index].column == (tokens[next_index].column + tokens[next_index].lexeme.length)
|
|
1199
|
-
end
|
|
1209
|
+
lbracket_index = name_index + 1
|
|
1210
|
+
return nil unless line_tokens[lbracket_index]&.type == :lbracket
|
|
1200
1211
|
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
tokens: type_param_tokens,
|
|
1229
|
-
} if depth.zero?
|
|
1230
|
-
when :comma
|
|
1231
|
-
expect_name = true if depth == 1
|
|
1232
|
-
when :at
|
|
1233
|
-
expect_name = false if depth == 1
|
|
1234
|
-
when :implements
|
|
1235
|
-
expect_name = false if depth == 1
|
|
1236
|
-
else
|
|
1237
|
-
if depth == 1 && expect_name && tok.type == :identifier
|
|
1238
|
-
type_param_tokens << tok
|
|
1239
|
-
expect_name = false
|
|
1212
|
+
depth = 0
|
|
1213
|
+
type_param_tokens = []
|
|
1214
|
+
expect_name = false
|
|
1215
|
+
i = lbracket_index
|
|
1216
|
+
while i < line_tokens.length
|
|
1217
|
+
tok = line_tokens[i]
|
|
1218
|
+
case tok.type
|
|
1219
|
+
when :lbracket
|
|
1220
|
+
depth += 1
|
|
1221
|
+
expect_name = true if depth == 1
|
|
1222
|
+
when :rbracket
|
|
1223
|
+
depth -= 1
|
|
1224
|
+
return {
|
|
1225
|
+
names: type_param_tokens.map(&:lexeme),
|
|
1226
|
+
tokens: type_param_tokens,
|
|
1227
|
+
} if depth.zero?
|
|
1228
|
+
when :comma
|
|
1229
|
+
expect_name = true if depth == 1
|
|
1230
|
+
when :at
|
|
1231
|
+
expect_name = false if depth == 1
|
|
1232
|
+
when :implements
|
|
1233
|
+
expect_name = false if depth == 1
|
|
1234
|
+
else
|
|
1235
|
+
if depth == 1 && expect_name && tok.type == :identifier
|
|
1236
|
+
type_param_tokens << tok
|
|
1237
|
+
expect_name = false
|
|
1238
|
+
end
|
|
1240
1239
|
end
|
|
1240
|
+
i += 1
|
|
1241
1241
|
end
|
|
1242
|
-
|
|
1242
|
+
|
|
1243
|
+
nil
|
|
1243
1244
|
end
|
|
1244
1245
|
|
|
1245
|
-
|
|
1246
|
-
|
|
1246
|
+
def generic_type_parameter_header_token?(type)
|
|
1247
|
+
[:function, :struct, :union, :enum, :flags, :variant, :type, :extending].include?(type)
|
|
1248
|
+
end
|
|
1247
1249
|
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1250
|
+
def type_parameter_names_in_scope(facts, line)
|
|
1251
|
+
scopes = @type_parameter_scope_cache ||= {}
|
|
1252
|
+
cached = scopes[facts.object_id]
|
|
1253
|
+
unless cached
|
|
1254
|
+
decls = Array(facts.ast&.declarations)
|
|
1255
|
+
cached = decls.each_with_index.flat_map do |decl, index|
|
|
1256
|
+
type_parameter_scopes_for_declaration(
|
|
1257
|
+
decl,
|
|
1258
|
+
end_line: declaration_scope_end_line(decls, index),
|
|
1259
|
+
)
|
|
1260
|
+
end
|
|
1261
|
+
scopes[facts.object_id] = cached
|
|
1262
|
+
end
|
|
1251
1263
|
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
cached = scopes[facts.object_id]
|
|
1255
|
-
unless cached
|
|
1256
|
-
decls = Array(facts.ast&.declarations)
|
|
1257
|
-
cached = decls.each_with_index.flat_map do |decl, index|
|
|
1258
|
-
type_parameter_scopes_for_declaration(
|
|
1259
|
-
decl,
|
|
1260
|
-
end_line: declaration_scope_end_line(decls, index),
|
|
1261
|
-
)
|
|
1264
|
+
cached.reverse_each do |scope|
|
|
1265
|
+
return scope[:names] if line >= scope[:start_line] && line <= scope[:end_line]
|
|
1262
1266
|
end
|
|
1263
|
-
scopes[facts.object_id] = cached
|
|
1264
|
-
end
|
|
1265
1267
|
|
|
1266
|
-
|
|
1267
|
-
return scope[:names] if line >= scope[:start_line] && line <= scope[:end_line]
|
|
1268
|
+
[]
|
|
1268
1269
|
end
|
|
1269
1270
|
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
return methods.each_with_index.filter_map do |method, index|
|
|
1278
|
-
names = receiver_names + generic_type_parameter_names_for_declaration(method)
|
|
1279
|
-
next if names.empty? || method.line.nil?
|
|
1271
|
+
def type_parameter_scopes_for_declaration(decl, end_line: Float::INFINITY)
|
|
1272
|
+
if decl.is_a?(AST::ExtendingBlock)
|
|
1273
|
+
receiver_names = generic_type_parameter_names_for_extending_block(decl)
|
|
1274
|
+
methods = Array(decl.methods)
|
|
1275
|
+
return methods.each_with_index.filter_map do |method, index|
|
|
1276
|
+
names = receiver_names + generic_type_parameter_names_for_declaration(method)
|
|
1277
|
+
next if names.empty? || method.line.nil?
|
|
1280
1278
|
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1279
|
+
{
|
|
1280
|
+
start_line: method.line,
|
|
1281
|
+
end_line: nested_declaration_scope_end_line(methods, index, fallback_end_line: end_line),
|
|
1282
|
+
names: names.uniq,
|
|
1283
|
+
}
|
|
1284
|
+
end
|
|
1286
1285
|
end
|
|
1287
|
-
end
|
|
1288
1286
|
|
|
1289
|
-
|
|
1290
|
-
|
|
1287
|
+
names = generic_type_parameter_names_for_declaration(decl)
|
|
1288
|
+
return [] if names.empty? || decl.line.nil?
|
|
1291
1289
|
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1290
|
+
[{
|
|
1291
|
+
start_line: decl.line,
|
|
1292
|
+
end_line: end_line,
|
|
1293
|
+
names: names,
|
|
1294
|
+
}]
|
|
1295
|
+
end
|
|
1298
1296
|
|
|
1299
|
-
|
|
1300
|
-
|
|
1297
|
+
def generic_type_parameter_names_for_declaration(decl)
|
|
1298
|
+
return [] unless decl.respond_to?(:type_params)
|
|
1301
1299
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1300
|
+
Array(decl.type_params).filter_map { |type_param| type_param.respond_to?(:name) ? type_param.name : nil }
|
|
1301
|
+
end
|
|
1304
1302
|
|
|
1305
|
-
|
|
1306
|
-
|
|
1303
|
+
def generic_type_parameter_names_for_extending_block(decl)
|
|
1304
|
+
return [] unless decl.respond_to?(:type_name)
|
|
1307
1305
|
|
|
1308
|
-
|
|
1309
|
-
|
|
1306
|
+
type_ref = decl.type_name
|
|
1307
|
+
return [] unless type_ref.is_a?(AST::TypeRef)
|
|
1310
1308
|
|
|
1311
|
-
|
|
1312
|
-
|
|
1309
|
+
Array(type_ref.arguments).filter_map do |argument|
|
|
1310
|
+
simple_type_parameter_name_from_type_argument(argument)
|
|
1311
|
+
end
|
|
1313
1312
|
end
|
|
1314
|
-
end
|
|
1315
1313
|
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1314
|
+
def simple_type_parameter_name_from_type_argument(argument)
|
|
1315
|
+
value = argument.respond_to?(:value) ? argument.value : nil
|
|
1316
|
+
return nil unless value.is_a?(AST::TypeRef)
|
|
1317
|
+
return nil unless value.arguments.empty? && !value.nullable && value.name.parts.length == 1
|
|
1320
1318
|
|
|
1321
|
-
|
|
1322
|
-
|
|
1319
|
+
value.name.parts.first
|
|
1320
|
+
end
|
|
1323
1321
|
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1322
|
+
def declaration_scope_end_line(decls, index)
|
|
1323
|
+
nested_declaration_scope_end_line(decls, index, fallback_end_line: Float::INFINITY)
|
|
1324
|
+
end
|
|
1327
1325
|
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1326
|
+
def nested_declaration_scope_end_line(decls, index, fallback_end_line:)
|
|
1327
|
+
next_decl = decls[(index + 1)..]&.find { |candidate| candidate.line }
|
|
1328
|
+
next_decl ? next_decl.line - 1 : fallback_end_line
|
|
1329
|
+
end
|
|
1332
1330
|
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1331
|
+
def matching_closer_index(tokens, opener_index, opener_type, closer_type)
|
|
1332
|
+
depth = 0
|
|
1333
|
+
i = opener_index
|
|
1334
|
+
while i < tokens.length
|
|
1335
|
+
tok = tokens[i]
|
|
1336
|
+
if tok.type == opener_type
|
|
1337
|
+
depth += 1
|
|
1338
|
+
elsif tok.type == closer_type
|
|
1339
|
+
depth -= 1
|
|
1340
|
+
return i if depth.zero?
|
|
1341
|
+
end
|
|
1342
|
+
i += 1
|
|
1343
1343
|
end
|
|
1344
|
-
|
|
1344
|
+
nil
|
|
1345
1345
|
end
|
|
1346
|
-
nil
|
|
1347
|
-
end
|
|
1348
1346
|
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1347
|
+
def import_path_info_at(tokens, index, allow_keywords: false)
|
|
1348
|
+
tok = tokens[index]
|
|
1349
|
+
return nil unless tok
|
|
1350
|
+
return nil unless tok.type == :identifier || (allow_keywords && Token::KEYWORDS.value?(tok.type))
|
|
1353
1351
|
|
|
1354
|
-
|
|
1355
|
-
|
|
1352
|
+
line_tokens = non_trivia_tokens_on_line(tokens, tok.line)
|
|
1353
|
+
return nil if line_tokens.empty? || line_tokens.first.type != :import
|
|
1356
1354
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1355
|
+
as_index = line_tokens.index { |line_tok| line_tok.type == :as }
|
|
1356
|
+
module_tokens = line_tokens[1...(as_index || line_tokens.length)] || []
|
|
1357
|
+
alias_token = as_index ? line_tokens[as_index + 1] : nil
|
|
1360
1358
|
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1359
|
+
module_identifiers = module_tokens.select do |line_tok|
|
|
1360
|
+
line_tok.type == :identifier || (allow_keywords && Token::KEYWORDS.value?(line_tok.type))
|
|
1361
|
+
end
|
|
1362
|
+
return nil if module_identifiers.empty?
|
|
1365
1363
|
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1364
|
+
module_name = module_identifiers.map(&:lexeme).join('.')
|
|
1365
|
+
return { module_name: module_name, role: :module_path } if module_identifiers.include?(tok)
|
|
1366
|
+
return { module_name: module_name, role: :alias } if alias_token == tok
|
|
1369
1367
|
|
|
1370
|
-
|
|
1371
|
-
|
|
1368
|
+
nil
|
|
1369
|
+
end
|
|
1372
1370
|
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1371
|
+
def variant_enum_member_declaration?(tokens, index)
|
|
1372
|
+
tok = tokens[index]
|
|
1373
|
+
line_tokens = non_trivia_tokens_on_line(tokens, tok.line)
|
|
1374
|
+
return false unless line_tokens.first.equal?(tok) && tok.column > 1
|
|
1377
1375
|
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1376
|
+
i = index - 1
|
|
1377
|
+
while i >= 0
|
|
1378
|
+
t = tokens[i]
|
|
1379
|
+
i -= 1
|
|
1380
|
+
next if [:newline, :indent, :dedent, :eof].include?(t.type)
|
|
1381
|
+
next if t.line == tok.line
|
|
1382
|
+
next if t.column >= tok.column
|
|
1385
1383
|
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1384
|
+
header_line_toks = non_trivia_tokens_on_line(tokens, t.line)
|
|
1385
|
+
header_kind = header_line_toks.find { |header_tok| [:variant, :enum, :flags].include?(header_tok.type) }
|
|
1386
|
+
return !header_kind.nil?
|
|
1387
|
+
end
|
|
1388
|
+
false
|
|
1389
1389
|
end
|
|
1390
|
-
false
|
|
1391
|
-
end
|
|
1392
1390
|
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1391
|
+
def type_name_member_access?(tokens, index, facts = nil)
|
|
1392
|
+
dot_index = previous_non_trivia_token_index(tokens, index)
|
|
1393
|
+
return false unless dot_index && tokens[dot_index].type == :dot
|
|
1396
1394
|
|
|
1397
|
-
|
|
1398
|
-
|
|
1395
|
+
receiver_index = previous_non_trivia_token_index(tokens, dot_index)
|
|
1396
|
+
return false unless receiver_index
|
|
1399
1397
|
|
|
1400
|
-
|
|
1401
|
-
|
|
1398
|
+
type_name_receiver_token?(tokens, receiver_index, facts)
|
|
1399
|
+
end
|
|
1402
1400
|
|
|
1403
|
-
|
|
1404
|
-
|
|
1401
|
+
def type_name_receiver_token?(tokens, index, facts = nil)
|
|
1402
|
+
receiver = tokens[index]
|
|
1405
1403
|
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1404
|
+
if receiver.type == :identifier
|
|
1405
|
+
return true if receiver.lexeme.match?(/\A[A-Z]/)
|
|
1406
|
+
return true if facts && facts.types.key?(receiver.lexeme)
|
|
1409
1407
|
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1408
|
+
if facts
|
|
1409
|
+
module_binding = imported_module_binding_for_member(tokens, index, facts)
|
|
1410
|
+
return true if module_binding && module_binding.types.key?(receiver.lexeme)
|
|
1411
|
+
end
|
|
1412
|
+
|
|
1413
|
+
return false
|
|
1413
1414
|
end
|
|
1414
1415
|
|
|
1415
|
-
|
|
1416
|
-
|
|
1416
|
+
if receiver.type == :rbracket
|
|
1417
|
+
lbracket_i = matching_opener_index(tokens, index)
|
|
1418
|
+
return false unless lbracket_i
|
|
1417
1419
|
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
return false unless lbracket_i
|
|
1420
|
+
base_index = previous_non_trivia_token_index(tokens, lbracket_i)
|
|
1421
|
+
return false unless base_index
|
|
1421
1422
|
|
|
1422
|
-
|
|
1423
|
-
|
|
1423
|
+
return type_name_receiver_token?(tokens, base_index, facts)
|
|
1424
|
+
end
|
|
1424
1425
|
|
|
1425
|
-
|
|
1426
|
+
false
|
|
1426
1427
|
end
|
|
1427
1428
|
|
|
1428
|
-
|
|
1429
|
-
|
|
1429
|
+
def matching_opener_index(tokens, closer_index)
|
|
1430
|
+
closer = tokens[closer_index]
|
|
1431
|
+
return nil unless closer
|
|
1430
1432
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1433
|
+
opener_type, closer_type = case closer.type
|
|
1434
|
+
when :rbracket then [:lbracket, :rbracket]
|
|
1435
|
+
when :rparen then [:lparen, :rparen]
|
|
1436
|
+
else return nil
|
|
1437
|
+
end
|
|
1434
1438
|
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
+
depth = 0
|
|
1440
|
+
i = closer_index
|
|
1441
|
+
while i >= 0
|
|
1442
|
+
t = tokens[i]
|
|
1443
|
+
if t.type == closer_type
|
|
1444
|
+
depth += 1
|
|
1445
|
+
elsif t.type == opener_type
|
|
1446
|
+
depth -= 1
|
|
1447
|
+
return i if depth.zero?
|
|
1448
|
+
end
|
|
1449
|
+
i -= 1
|
|
1450
|
+
end
|
|
1451
|
+
nil
|
|
1439
1452
|
end
|
|
1440
1453
|
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
depth += 1
|
|
1447
|
-
elsif t.type == opener_type
|
|
1448
|
-
depth -= 1
|
|
1449
|
-
return i if depth.zero?
|
|
1454
|
+
def non_trivia_tokens_on_line(tokens, line)
|
|
1455
|
+
return @tokens_by_line_cache[line] if @tokens_by_line_cache
|
|
1456
|
+
|
|
1457
|
+
tokens.select do |tok|
|
|
1458
|
+
tok.line == line && ![:newline, :indent, :dedent, :eof].include?(tok.type)
|
|
1450
1459
|
end
|
|
1451
|
-
i -= 1
|
|
1452
1460
|
end
|
|
1453
|
-
nil
|
|
1454
|
-
end
|
|
1455
1461
|
|
|
1456
|
-
|
|
1457
|
-
|
|
1462
|
+
def build_attribute_name_semantic_overrides(tokens, facts)
|
|
1463
|
+
return {} unless facts&.respond_to?(:ast) && facts.ast
|
|
1458
1464
|
|
|
1459
|
-
|
|
1460
|
-
|
|
1465
|
+
token_indices_by_position = tokens.each_with_index.each_with_object({}) do |(token, index), positions|
|
|
1466
|
+
positions[[token.line, token.column]] = index
|
|
1467
|
+
end
|
|
1468
|
+
overrides = {}
|
|
1469
|
+
|
|
1470
|
+
walk_ast_nodes(facts.ast) do |node|
|
|
1471
|
+
case node
|
|
1472
|
+
when AST::AttributeDecl
|
|
1473
|
+
mark_attribute_name_override(
|
|
1474
|
+
overrides,
|
|
1475
|
+
token_indices_by_position,
|
|
1476
|
+
tokens,
|
|
1477
|
+
[node.name],
|
|
1478
|
+
line: node.line,
|
|
1479
|
+
column: node.column,
|
|
1480
|
+
declaration: true,
|
|
1481
|
+
)
|
|
1482
|
+
when AST::AttributeApplication
|
|
1483
|
+
mark_attribute_name_override(
|
|
1484
|
+
overrides,
|
|
1485
|
+
token_indices_by_position,
|
|
1486
|
+
tokens,
|
|
1487
|
+
node.name.parts,
|
|
1488
|
+
line: node.line,
|
|
1489
|
+
column: node.column,
|
|
1490
|
+
)
|
|
1491
|
+
when AST::Call
|
|
1492
|
+
mark_attribute_reflection_name_overrides(overrides, token_indices_by_position, tokens, node)
|
|
1493
|
+
end
|
|
1494
|
+
end
|
|
1495
|
+
|
|
1496
|
+
overrides
|
|
1461
1497
|
end
|
|
1462
|
-
end
|
|
1463
1498
|
|
|
1464
|
-
|
|
1465
|
-
|
|
1499
|
+
def walk_ast_nodes(node, &block)
|
|
1500
|
+
case node
|
|
1501
|
+
when Array
|
|
1502
|
+
node.each { |entry| walk_ast_nodes(entry, &block) }
|
|
1503
|
+
when String, Symbol, Numeric, TrueClass, FalseClass, NilClass
|
|
1504
|
+
nil
|
|
1505
|
+
else
|
|
1506
|
+
return unless node.class.name&.start_with?("MilkTea::AST::")
|
|
1466
1507
|
|
|
1467
|
-
|
|
1468
|
-
|
|
1508
|
+
yield node
|
|
1509
|
+
node.to_h.each_value { |value| walk_ast_nodes(value, &block) }
|
|
1510
|
+
end
|
|
1469
1511
|
end
|
|
1470
|
-
overrides = {}
|
|
1471
1512
|
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1513
|
+
def mark_attribute_reflection_name_overrides(overrides, token_indices_by_position, tokens, call_expression)
|
|
1514
|
+
callee = call_expression.callee
|
|
1515
|
+
return unless callee.is_a?(AST::Identifier)
|
|
1516
|
+
return unless %w[has_attribute attribute_of].include?(callee.name)
|
|
1517
|
+
return unless call_expression.arguments.length >= 2
|
|
1518
|
+
|
|
1519
|
+
attribute_name_expression = call_expression.arguments[1].value
|
|
1520
|
+
|
|
1521
|
+
case attribute_name_expression
|
|
1522
|
+
when AST::Identifier
|
|
1475
1523
|
mark_attribute_name_override(
|
|
1476
1524
|
overrides,
|
|
1477
1525
|
token_indices_by_position,
|
|
1478
1526
|
tokens,
|
|
1479
|
-
[
|
|
1480
|
-
line:
|
|
1481
|
-
column:
|
|
1482
|
-
declaration: true,
|
|
1527
|
+
[attribute_name_expression.name],
|
|
1528
|
+
line: attribute_name_expression.line,
|
|
1529
|
+
column: attribute_name_expression.column,
|
|
1483
1530
|
)
|
|
1484
|
-
when AST::
|
|
1531
|
+
when AST::MemberAccess
|
|
1532
|
+
return unless attribute_name_expression.receiver.is_a?(AST::Identifier)
|
|
1533
|
+
|
|
1485
1534
|
mark_attribute_name_override(
|
|
1486
1535
|
overrides,
|
|
1487
1536
|
token_indices_by_position,
|
|
1488
1537
|
tokens,
|
|
1489
|
-
|
|
1490
|
-
line:
|
|
1491
|
-
column:
|
|
1538
|
+
[attribute_name_expression.receiver.name, attribute_name_expression.member],
|
|
1539
|
+
line: attribute_name_expression.receiver.line,
|
|
1540
|
+
column: attribute_name_expression.receiver.column,
|
|
1492
1541
|
)
|
|
1493
|
-
when AST::Call
|
|
1494
|
-
mark_attribute_reflection_name_overrides(overrides, token_indices_by_position, tokens, node)
|
|
1495
1542
|
end
|
|
1496
1543
|
end
|
|
1497
1544
|
|
|
1498
|
-
overrides
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
def walk_ast_nodes(node, &block)
|
|
1502
|
-
case node
|
|
1503
|
-
when Array
|
|
1504
|
-
node.each { |entry| walk_ast_nodes(entry, &block) }
|
|
1505
|
-
when String, Symbol, Numeric, TrueClass, FalseClass, NilClass
|
|
1506
|
-
nil
|
|
1507
|
-
else
|
|
1508
|
-
return unless node.class.name&.start_with?("MilkTea::AST::")
|
|
1509
|
-
|
|
1510
|
-
yield node
|
|
1511
|
-
node.to_h.each_value { |value| walk_ast_nodes(value, &block) }
|
|
1512
|
-
end
|
|
1513
|
-
end
|
|
1545
|
+
def mark_attribute_name_override(overrides, token_indices_by_position, tokens, parts, line:, column:, declaration: false)
|
|
1546
|
+
current_index = token_indices_by_position[[line, column]]
|
|
1547
|
+
return unless current_index
|
|
1514
1548
|
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
return unless %w[has_attribute attribute_of].include?(callee.name)
|
|
1519
|
-
return unless call_expression.arguments.length >= 2
|
|
1520
|
-
|
|
1521
|
-
attribute_name_expression = call_expression.arguments[1].value
|
|
1522
|
-
|
|
1523
|
-
case attribute_name_expression
|
|
1524
|
-
when AST::Identifier
|
|
1525
|
-
mark_attribute_name_override(
|
|
1526
|
-
overrides,
|
|
1527
|
-
token_indices_by_position,
|
|
1528
|
-
tokens,
|
|
1529
|
-
[attribute_name_expression.name],
|
|
1530
|
-
line: attribute_name_expression.line,
|
|
1531
|
-
column: attribute_name_expression.column,
|
|
1532
|
-
)
|
|
1533
|
-
when AST::MemberAccess
|
|
1534
|
-
return unless attribute_name_expression.receiver.is_a?(AST::Identifier)
|
|
1535
|
-
|
|
1536
|
-
mark_attribute_name_override(
|
|
1537
|
-
overrides,
|
|
1538
|
-
token_indices_by_position,
|
|
1539
|
-
tokens,
|
|
1540
|
-
[attribute_name_expression.receiver.name, attribute_name_expression.member],
|
|
1541
|
-
line: attribute_name_expression.receiver.line,
|
|
1542
|
-
column: attribute_name_expression.receiver.column,
|
|
1543
|
-
)
|
|
1544
|
-
end
|
|
1545
|
-
end
|
|
1549
|
+
parts.each_with_index do |part, part_index|
|
|
1550
|
+
token = tokens[current_index]
|
|
1551
|
+
return unless token&.lexeme == part
|
|
1546
1552
|
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1553
|
+
if part_index == parts.length - 1
|
|
1554
|
+
modifiers = []
|
|
1555
|
+
modifiers << 'declaration' if declaration
|
|
1556
|
+
overrides[[token.line, token.column]] = [:decorator, modifiers]
|
|
1557
|
+
return
|
|
1558
|
+
end
|
|
1550
1559
|
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1560
|
+
overrides[[token.line, token.column]] = [:namespace, []]
|
|
1561
|
+
dot_index = next_non_trivia_token_index(tokens, current_index + 1)
|
|
1562
|
+
return unless dot_index && tokens[dot_index].type == :dot
|
|
1554
1563
|
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
modifiers << 'declaration' if declaration
|
|
1558
|
-
overrides[[token.line, token.column]] = [:decorator, modifiers]
|
|
1559
|
-
return
|
|
1564
|
+
current_index = next_non_trivia_token_index(tokens, dot_index + 1)
|
|
1565
|
+
return unless current_index
|
|
1560
1566
|
end
|
|
1567
|
+
end
|
|
1561
1568
|
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
return unless dot_index && tokens[dot_index].type == :dot
|
|
1565
|
-
|
|
1566
|
-
current_index = next_non_trivia_token_index(tokens, dot_index + 1)
|
|
1567
|
-
return unless current_index
|
|
1569
|
+
def module_declaration_path_token?(tokens, index, allow_keywords: false)
|
|
1570
|
+
!module_declaration_info_at(tokens, index, allow_keywords:).nil?
|
|
1568
1571
|
end
|
|
1569
|
-
end
|
|
1570
1572
|
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1573
|
+
def module_declaration_info_at(tokens, index, allow_keywords: false)
|
|
1574
|
+
tok = tokens[index]
|
|
1575
|
+
return nil unless tok&.type == :identifier || (allow_keywords && Token::KEYWORDS.value?(tok.type))
|
|
1574
1576
|
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
return nil unless tok&.type == :identifier || (allow_keywords && Token::KEYWORDS.value?(tok.type))
|
|
1577
|
+
line_tokens = non_trivia_tokens_on_line(tokens, tok.line)
|
|
1578
|
+
return nil if line_tokens.empty? || line_tokens.first.type != :module
|
|
1578
1579
|
|
|
1579
|
-
|
|
1580
|
-
|
|
1580
|
+
path_tokens = line_tokens[1..].to_a.select do |line_tok|
|
|
1581
|
+
line_tok.type == :identifier || (allow_keywords && Token::KEYWORDS.value?(line_tok.type))
|
|
1582
|
+
end
|
|
1583
|
+
return nil unless path_tokens.any? { |line_tok| line_tok.equal?(tok) }
|
|
1581
1584
|
|
|
1582
|
-
|
|
1583
|
-
|
|
1585
|
+
{
|
|
1586
|
+
module_name: path_tokens.map(&:lexeme).join('.'),
|
|
1587
|
+
}
|
|
1584
1588
|
end
|
|
1585
|
-
return nil unless path_tokens.any? { |line_tok| line_tok.equal?(tok) }
|
|
1586
1589
|
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
end
|
|
1590
|
+
def previous_non_trivia_token(tokens, index)
|
|
1591
|
+
prev_index = previous_non_trivia_token_index(tokens, index)
|
|
1592
|
+
return nil unless prev_index
|
|
1591
1593
|
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
return nil unless prev_index
|
|
1594
|
+
tokens[prev_index]
|
|
1595
|
+
end
|
|
1595
1596
|
|
|
1596
|
-
tokens
|
|
1597
|
-
|
|
1597
|
+
def first_non_trivia_token_on_line?(tokens, index)
|
|
1598
|
+
token = tokens[index]
|
|
1599
|
+
return false unless token
|
|
1598
1600
|
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1601
|
+
i = index - 1
|
|
1602
|
+
while i >= 0
|
|
1603
|
+
previous = tokens[i]
|
|
1604
|
+
return true if previous.type == :newline
|
|
1605
|
+
return false if previous.line == token.line && ![:indent, :dedent].include?(previous.type)
|
|
1602
1606
|
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
previous = tokens[i]
|
|
1606
|
-
return true if previous.type == :newline
|
|
1607
|
-
return false if previous.line == token.line && ![:indent, :dedent].include?(previous.type)
|
|
1607
|
+
i -= 1
|
|
1608
|
+
end
|
|
1608
1609
|
|
|
1609
|
-
|
|
1610
|
+
true
|
|
1610
1611
|
end
|
|
1611
1612
|
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
i -= 1
|
|
1613
|
+
def previous_non_trivia_token_index(tokens, index)
|
|
1614
|
+
i = index - 1
|
|
1615
|
+
while i >= 0
|
|
1616
|
+
tok = tokens[i]
|
|
1617
|
+
return i unless [:newline, :indent, :dedent].include?(tok.type)
|
|
1618
|
+
i -= 1
|
|
1619
|
+
end
|
|
1620
|
+
nil
|
|
1621
1621
|
end
|
|
1622
|
-
nil
|
|
1623
|
-
end
|
|
1624
1622
|
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1623
|
+
def next_non_trivia_token_index(tokens, index)
|
|
1624
|
+
i = index
|
|
1625
|
+
while i < tokens.length
|
|
1626
|
+
tok = tokens[i]
|
|
1627
|
+
return i unless [:newline, :indent, :dedent].include?(tok.type)
|
|
1628
|
+
i += 1
|
|
1629
|
+
end
|
|
1630
|
+
nil
|
|
1631
1631
|
end
|
|
1632
|
-
nil
|
|
1633
|
-
end
|
|
1634
1632
|
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1633
|
+
def encode_semantic_tokens(entries)
|
|
1634
|
+
data = []
|
|
1635
|
+
prev_line = 0
|
|
1636
|
+
prev_char = 0
|
|
1639
1637
|
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1638
|
+
entries.each do |entry|
|
|
1639
|
+
delta_line = entry[:line] - prev_line
|
|
1640
|
+
delta_start = delta_line.zero? ? entry[:start_char] - prev_char : entry[:start_char]
|
|
1641
|
+
type_index = SEMANTIC_TOKEN_TYPES.index(entry[:type].to_s) || 0
|
|
1642
|
+
modifiers_bitset = semantic_modifiers_bitset(entry[:modifiers])
|
|
1645
1643
|
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1644
|
+
data << delta_line
|
|
1645
|
+
data << delta_start
|
|
1646
|
+
data << entry[:length]
|
|
1647
|
+
data << type_index
|
|
1648
|
+
data << modifiers_bitset
|
|
1651
1649
|
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1650
|
+
prev_line = entry[:line]
|
|
1651
|
+
prev_char = entry[:start_char]
|
|
1652
|
+
end
|
|
1655
1653
|
|
|
1656
|
-
|
|
1657
|
-
|
|
1654
|
+
data
|
|
1655
|
+
end
|
|
1658
1656
|
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1657
|
+
def next_semantic_token_result_id(uri)
|
|
1658
|
+
@semantic_token_result_counter ||= 0
|
|
1659
|
+
@semantic_token_result_counter += 1
|
|
1660
|
+
"#{uri}:#{@semantic_token_result_counter}"
|
|
1661
|
+
end
|
|
1664
1662
|
|
|
1665
|
-
|
|
1666
|
-
|
|
1663
|
+
def compute_semantic_tokens_edits(old_entries, new_entries)
|
|
1664
|
+
return [] if old_entries == new_entries
|
|
1667
1665
|
|
|
1668
|
-
|
|
1669
|
-
|
|
1666
|
+
prefix = find_semantic_token_common_prefix(old_entries, new_entries)
|
|
1667
|
+
suffix = find_semantic_token_common_suffix(old_entries, new_entries, prefix)
|
|
1670
1668
|
|
|
1671
|
-
|
|
1672
|
-
|
|
1669
|
+
old_mid = old_entries.length - prefix - suffix
|
|
1670
|
+
new_mid = new_entries.length - prefix - suffix
|
|
1673
1671
|
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1672
|
+
if old_mid.zero? && new_mid.zero?
|
|
1673
|
+
return []
|
|
1674
|
+
end
|
|
1677
1675
|
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1676
|
+
start_offset = prefix * 5
|
|
1677
|
+
delete_count = old_mid * 5
|
|
1678
|
+
insert_tokens = encode_semantic_tokens(new_entries[prefix...(new_entries.length - suffix)])
|
|
1681
1679
|
|
|
1682
|
-
|
|
1683
|
-
end
|
|
1684
|
-
|
|
1685
|
-
def find_semantic_token_common_prefix(old_entries, new_entries)
|
|
1686
|
-
limit = [old_entries.length, new_entries.length].min
|
|
1687
|
-
prefix = 0
|
|
1688
|
-
while prefix < limit && semantic_token_entry_equal?(old_entries[prefix], new_entries[prefix])
|
|
1689
|
-
prefix += 1
|
|
1680
|
+
[{ start: start_offset, deleteCount: delete_count, data: insert_tokens }]
|
|
1690
1681
|
end
|
|
1691
|
-
prefix
|
|
1692
|
-
end
|
|
1693
1682
|
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1683
|
+
def find_semantic_token_common_prefix(old_entries, new_entries)
|
|
1684
|
+
limit = [old_entries.length, new_entries.length].min
|
|
1685
|
+
prefix = 0
|
|
1686
|
+
while prefix < limit && semantic_token_entry_equal?(old_entries[prefix], new_entries[prefix])
|
|
1687
|
+
prefix += 1
|
|
1688
|
+
end
|
|
1689
|
+
prefix
|
|
1690
|
+
end
|
|
1691
|
+
|
|
1692
|
+
def find_semantic_token_common_suffix(old_entries, new_entries, prefix)
|
|
1693
|
+
old_limit = old_entries.length - prefix
|
|
1694
|
+
new_limit = new_entries.length - prefix
|
|
1695
|
+
limit = [old_limit, new_limit].min
|
|
1696
|
+
suffix = 0
|
|
1697
|
+
while suffix < limit &&
|
|
1698
|
+
semantic_token_entry_equal?(old_entries[old_entries.length - 1 - suffix],
|
|
1699
|
+
new_entries[new_entries.length - 1 - suffix])
|
|
1700
|
+
suffix += 1
|
|
1701
|
+
end
|
|
1702
|
+
suffix
|
|
1703
|
+
end
|
|
1706
1704
|
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1705
|
+
def semantic_token_entry_equal?(a, b)
|
|
1706
|
+
a[:line] == b[:line] &&
|
|
1707
|
+
a[:start_char] == b[:start_char] &&
|
|
1708
|
+
a[:length] == b[:length] &&
|
|
1709
|
+
a[:type] == b[:type] &&
|
|
1710
|
+
a[:modifiers] == b[:modifiers]
|
|
1711
|
+
end
|
|
1714
1712
|
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1713
|
+
def semantic_modifiers_bitset(modifiers)
|
|
1714
|
+
bits = 0
|
|
1715
|
+
Array(modifiers).each do |modifier|
|
|
1716
|
+
idx = SEMANTIC_TOKEN_MODIFIERS.index(modifier.to_s)
|
|
1717
|
+
next unless idx
|
|
1720
1718
|
|
|
1721
|
-
|
|
1719
|
+
bits |= (1 << idx)
|
|
1720
|
+
end
|
|
1721
|
+
bits
|
|
1722
1722
|
end
|
|
1723
|
-
bits
|
|
1724
|
-
end
|
|
1725
1723
|
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1724
|
+
def generic_function_binding_for_line(facts, line)
|
|
1725
|
+
generic_function_bindings(facts).filter_map do |binding|
|
|
1726
|
+
next unless binding.ast.respond_to?(:body) && binding.ast.line
|
|
1729
1727
|
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1728
|
+
start_line = binding.ast.line
|
|
1729
|
+
end_line = generic_statement_list_end_line(Array(binding.ast.body), start_line)
|
|
1730
|
+
next unless start_line <= line && line <= end_line
|
|
1733
1731
|
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1732
|
+
[end_line - start_line, -start_line, binding]
|
|
1733
|
+
end.min_by { |span, start_line, _binding| [span, start_line] }&.last
|
|
1734
|
+
end
|
|
1737
1735
|
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1736
|
+
def generic_function_bindings(facts)
|
|
1737
|
+
facts.functions.each_value.select { |binding| binding.type_params.any? } +
|
|
1738
|
+
facts.methods.each_value.flat_map(&:values).select { |binding| binding.type_params.any? }
|
|
1739
|
+
end
|
|
1742
1740
|
end
|
|
1743
1741
|
end
|
|
1744
1742
|
end
|