Skip to content

Commit b1df447

Browse files
committed
add tests for read and write variables
remove no longer needed hacks in completions
1 parent ed2d2ca commit b1df447

File tree

6 files changed

+296
-39
lines changed

6 files changed

+296
-39
lines changed

apps/language_server/lib/language_server/providers/completion/suggestion.ex

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -145,32 +145,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion.Suggestion do
145145
{{line, column - String.length(prefix)}, {line, column + String.length(suffix)}}
146146
end
147147

148-
env =
149-
Metadata.get_cursor_env(metadata, {line, column}, surround)
150-
|> Metadata.add_scope_vars(
151-
metadata,
152-
{line, column},
153-
&(to_string(&1.name) != hint)
154-
)
155-
156-
# if variable is rebound then in env there are many variables with the same name
157-
# find the one defined closest to cursor
158-
vars =
159-
env.vars
160-
|> Enum.group_by(fn %State.VarInfo{name: name} -> name end)
161-
|> Enum.map(fn {_name, list} ->
162-
list
163-
|> Enum.max_by(fn
164-
%State.VarInfo{positions: [_position]} ->
165-
# variable is being defined - it's not a good candidate
166-
{0, 0}
167-
168-
%State.VarInfo{positions: positions} ->
169-
Enum.min(positions)
170-
end)
171-
end)
172-
173-
env = %{env | vars: vars}
148+
env = Metadata.get_cursor_env(metadata, {line, column}, surround)
174149

175150
module_store = ModuleStore.build()
176151

apps/language_server/lib/language_server/providers/definition/locator.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ defmodule ElixirLS.LanguageServer.Providers.Definition.Locator do
9191

9292
%Location{type: :variable, file: nil, line: definition_line, column: definition_column}
9393
else
94+
# find local call
9495
find_function_or_module(
9596
{nil, variable},
9697
context,

apps/language_server/test/providers/completion/suggestions_test.exs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,6 +1908,45 @@ defmodule ElixirLS.LanguageServer.Providers.Completion.SuggestionTest do
19081908
]
19091909
end
19101910

1911+
test "lists write vars in match context" do
1912+
buffer = """
1913+
defmodule MyServer do
1914+
def my(arg = 1, a), do: :ok
1915+
end
1916+
"""
1917+
1918+
list =
1919+
Suggestion.suggestions(buffer, 2, 20)
1920+
|> Enum.filter(fn s -> s.type == :variable end)
1921+
1922+
assert list == [
1923+
%{name: "arg", type: :variable}
1924+
]
1925+
end
1926+
1927+
test "does not list write vars" do
1928+
buffer = """
1929+
defmodule MyServer do
1930+
[arg = 1, a]
1931+
a
1932+
end
1933+
"""
1934+
1935+
list =
1936+
Suggestion.suggestions(buffer, 2, 14)
1937+
|> Enum.filter(fn s -> s.type == :variable end)
1938+
1939+
# arg is a write var and is not available for read in the cursor context
1940+
assert list == []
1941+
1942+
list =
1943+
Suggestion.suggestions(buffer, 3, 4)
1944+
|> Enum.filter(fn s -> s.type == :variable end)
1945+
1946+
# arg is a read var here
1947+
assert list == [%{name: "arg", type: :variable}]
1948+
end
1949+
19111950
test "lists params and vars in cond clauses" do
19121951
buffer = """
19131952
defmodule MyServer do

apps/language_server/test/providers/definition/locator_test.exs

Lines changed: 113 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -921,19 +921,19 @@ defmodule ElixirLS.LanguageServer.Providers.Definition.LocatorTest do
921921
end
922922
"""
923923

924-
# assert Locator.definition(buffer, 2, 32) == %Location{
925-
# type: :variable,
926-
# file: nil,
927-
# line: 2,
928-
# column: 14
929-
# }
930-
931-
# assert Locator.definition(buffer, 4, 16) == %Location{
932-
# type: :variable,
933-
# file: nil,
934-
# line: 4,
935-
# column: 7
936-
# }
924+
assert Locator.definition(buffer, 2, 32) == %Location{
925+
type: :variable,
926+
file: nil,
927+
line: 2,
928+
column: 14
929+
}
930+
931+
assert Locator.definition(buffer, 4, 16) == %Location{
932+
type: :variable,
933+
file: nil,
934+
line: 4,
935+
column: 7
936+
}
937937

938938
assert Locator.definition(buffer, 7, 32) == %Location{
939939
type: :variable,
@@ -1060,6 +1060,106 @@ defmodule ElixirLS.LanguageServer.Providers.Definition.LocatorTest do
10601060
}
10611061
end
10621062

1063+
# TODO not supported in Code.Fragment.surround_context
1064+
# test "find definition of &1 capture variable" do
1065+
# buffer = """
1066+
# defmodule MyModule do
1067+
# def go() do
1068+
# abc = 5
1069+
# & [
1070+
# &1,
1071+
# abc,
1072+
# cde = 1,
1073+
# record_env()
1074+
# ]
1075+
# end
1076+
# end
1077+
# """
1078+
1079+
# assert Locator.definition(buffer, 4, 8) == %Location{
1080+
# type: :variable,
1081+
# file: nil,
1082+
# line: 4,
1083+
# column: 7
1084+
# }
1085+
# end
1086+
1087+
test "find definition of write variable on definition" do
1088+
buffer = """
1089+
defmodule MyModule do
1090+
def go() do
1091+
abc = 5
1092+
& [
1093+
&1,
1094+
abc,
1095+
cde = 1,
1096+
record_env()
1097+
]
1098+
end
1099+
end
1100+
"""
1101+
1102+
assert Locator.definition(buffer, 7, 8) == %Location{
1103+
type: :variable,
1104+
file: nil,
1105+
line: 7,
1106+
column: 7
1107+
}
1108+
end
1109+
1110+
test "does not find definition of write variable on read" do
1111+
buffer = """
1112+
defmodule MyModule do
1113+
def go() do
1114+
abc = 5
1115+
& [
1116+
&1,
1117+
abc,
1118+
cde = 1,
1119+
record_env(cde)
1120+
]
1121+
end
1122+
end
1123+
"""
1124+
1125+
assert Locator.definition(buffer, 8, 19) == nil
1126+
end
1127+
1128+
test "find definition of write variable in match context" do
1129+
buffer = """
1130+
defmodule MyModule do
1131+
def go(asd = 3, asd) do
1132+
:ok
1133+
end
1134+
1135+
def go(asd = 3, [2, asd]) do
1136+
:ok
1137+
end
1138+
end
1139+
"""
1140+
1141+
assert Locator.definition(buffer, 2, 11) == %Location{
1142+
type: :variable,
1143+
file: nil,
1144+
line: 2,
1145+
column: 10
1146+
}
1147+
1148+
assert Locator.definition(buffer, 2, 20) == %Location{
1149+
type: :variable,
1150+
file: nil,
1151+
line: 2,
1152+
column: 10
1153+
}
1154+
1155+
assert Locator.definition(buffer, 6, 24) == %Location{
1156+
type: :variable,
1157+
file: nil,
1158+
line: 6,
1159+
column: 10
1160+
}
1161+
end
1162+
10631163
test "find definition of a variable when using pin operator" do
10641164
buffer = """
10651165
defmodule MyModule do

apps/language_server/test/providers/hover/docs_test.exs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,6 +1846,70 @@ defmodule ElixirLS.LanguageServer.Providers.Hover.DocsTest do
18461846
docs: [%{kind: :variable}]
18471847
} = Docs.docs(buffer, 8, 21)
18481848
end
1849+
1850+
test "find docs for write variable on definition" do
1851+
buffer = """
1852+
defmodule MyModule do
1853+
def go() do
1854+
abc = 5
1855+
& [
1856+
&1,
1857+
abc,
1858+
cde = 1,
1859+
record_env()
1860+
]
1861+
end
1862+
end
1863+
"""
1864+
1865+
assert %{
1866+
docs: [%{kind: :variable}]
1867+
} = Docs.docs(buffer, 7, 8)
1868+
end
1869+
1870+
test "does not find docs for write variable on read" do
1871+
buffer = """
1872+
defmodule MyModule do
1873+
def go() do
1874+
abc = 5
1875+
& [
1876+
&1,
1877+
abc,
1878+
cde = 1,
1879+
record_env(cde)
1880+
]
1881+
end
1882+
end
1883+
"""
1884+
1885+
assert Docs.docs(buffer, 8, 19) == nil
1886+
end
1887+
1888+
test "finds docs for write variable in match context" do
1889+
buffer = """
1890+
defmodule MyModule do
1891+
def go(asd = 3, asd) do
1892+
:ok
1893+
end
1894+
1895+
def go(asd = 3, [2, asd]) do
1896+
:ok
1897+
end
1898+
end
1899+
"""
1900+
1901+
assert %{
1902+
docs: [%{kind: :variable}]
1903+
} = Docs.docs(buffer, 2, 11)
1904+
1905+
assert %{
1906+
docs: [%{kind: :variable}]
1907+
} = Docs.docs(buffer, 2, 20)
1908+
1909+
assert %{
1910+
docs: [%{kind: :variable}]
1911+
} = Docs.docs(buffer, 6, 24)
1912+
end
18491913
end
18501914

18511915
test "find local type in typespec local def elsewhere" do

apps/language_server/test/providers/references/locator_test.exs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,84 @@ defmodule ElixirLS.LanguageServer.Providers.References.LocatorTest do
15741574
assert Locator.references(buffer, 8, 21, trace) == expected_references
15751575
end
15761576

1577+
test "find references of write variable on definition", %{trace: trace} do
1578+
buffer = """
1579+
defmodule MyModule do
1580+
def go() do
1581+
abc = 5
1582+
& [
1583+
&1,
1584+
abc,
1585+
cde = 1,
1586+
record_env()
1587+
]
1588+
end
1589+
end
1590+
"""
1591+
1592+
expected_references = [
1593+
%{uri: nil, range: %{start: %{line: 7, column: 7}, end: %{line: 7, column: 10}}}
1594+
]
1595+
1596+
assert Locator.references(buffer, 7, 8, trace) == expected_references
1597+
end
1598+
1599+
test "does not find references of write variable on read", %{trace: trace} do
1600+
buffer = """
1601+
defmodule MyModule do
1602+
def go() do
1603+
abc = 5
1604+
& [
1605+
&1,
1606+
abc,
1607+
cde = 1,
1608+
record_env(cde)
1609+
]
1610+
end
1611+
end
1612+
"""
1613+
1614+
expected_references = [
1615+
%{uri: nil, range: %{start: %{line: 7, column: 7}, end: %{line: 7, column: 10}}}
1616+
]
1617+
1618+
# cde in cde = 1 is defined
1619+
assert Locator.references(buffer, 7, 8, trace) == expected_references
1620+
1621+
# cde in record_env(cde) is undefined
1622+
assert Locator.references(buffer, 8, 19, trace) == []
1623+
end
1624+
1625+
test "find definition of write variable in match context", %{trace: trace} do
1626+
buffer = """
1627+
defmodule MyModule do
1628+
def go(asd = 3, asd) do
1629+
:ok
1630+
end
1631+
1632+
def go(asd = 3, [2, asd]) do
1633+
:ok
1634+
end
1635+
end
1636+
"""
1637+
1638+
expected_references = [
1639+
%{uri: nil, range: %{start: %{line: 2, column: 10}, end: %{line: 2, column: 13}}},
1640+
%{uri: nil, range: %{start: %{line: 2, column: 19}, end: %{line: 2, column: 22}}}
1641+
]
1642+
1643+
assert Locator.references(buffer, 2, 11, trace) == expected_references
1644+
1645+
assert Locator.references(buffer, 2, 20, trace) == expected_references
1646+
1647+
expected_references = [
1648+
%{uri: nil, range: %{start: %{line: 6, column: 10}, end: %{line: 6, column: 13}}},
1649+
%{uri: nil, range: %{start: %{line: 6, column: 23}, end: %{line: 6, column: 26}}}
1650+
]
1651+
1652+
assert Locator.references(buffer, 6, 24, trace) == expected_references
1653+
end
1654+
15771655
test "find references of attributes", %{trace: trace} do
15781656
buffer = """
15791657
defmodule MyModule do

0 commit comments

Comments
 (0)