Skip to content

Commit 31bdbf3

Browse files
committed
refactor(lsp): use File_Language instead of Linter_Options for Lintable_Document
Lintable_Document keeps track of a Linter_Options object. This will be problematic when we allow some linter options to be overwritten by a user quick-lint-js.config file. Refactor Lintable_Document to work with File_Language instead. Only create a Linter_Options object at the last minute.
1 parent 7e7071f commit 31bdbf3

File tree

4 files changed

+43
-71
lines changed

4 files changed

+43
-71
lines changed

src/quick-lint-js/lsp/lsp-language.h

Lines changed: 18 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#pragma once
55

66
#include <iterator>
7-
#include <quick-lint-js/fe/linter.h>
7+
#include <quick-lint-js/fe/language.h>
88
#include <quick-lint-js/port/char8.h>
99
#include <quick-lint-js/util/algorithm.h>
1010
#include <quick-lint-js/util/classify-path.h>
@@ -15,17 +15,16 @@ namespace quick_lint_js {
1515
struct LSP_Language {
1616
struct typescript_autodetect_tag {};
1717

18-
constexpr LSP_Language(std::string_view language_id,
19-
Linter_Options lint_options)
20-
: lint_options(lint_options) {
18+
constexpr LSP_Language(std::string_view language_id, File_Language language)
19+
: language(language) {
2120
quick_lint_js::copy(language_id.begin(), language_id.end(),
2221
this->raw_language_id);
2322
this->language_id_size = static_cast<unsigned char>(language_id.size());
2423
}
2524

26-
constexpr LSP_Language(std::string_view language_id,
27-
Linter_Options lint_options, typescript_autodetect_tag)
28-
: LSP_Language(language_id, lint_options) {
25+
constexpr LSP_Language(std::string_view language_id, File_Language language,
26+
typescript_autodetect_tag)
27+
: LSP_Language(language_id, language) {
2928
this->typescript_autodetect = true;
3029
}
3130

@@ -38,44 +37,22 @@ struct LSP_Language {
3837
String8_View uri) {
3938
using namespace std::literals::string_view_literals;
4039

41-
static constexpr Linter_Options jsx = {
42-
.jsx = true,
43-
.typescript = false,
44-
.typescript_definition = false,
45-
.print_parser_visits = false,
46-
};
47-
static constexpr Linter_Options ts = {
48-
.jsx = false,
49-
.typescript = true,
50-
.typescript_definition = false,
51-
.print_parser_visits = false,
52-
};
53-
static constexpr Linter_Options ts_definition = {
54-
.jsx = false,
55-
.typescript = true,
56-
.typescript_definition = true,
57-
.print_parser_visits = false,
58-
};
59-
static constexpr Linter_Options tsx = {
60-
.jsx = true,
61-
.typescript = true,
62-
.typescript_definition = false,
63-
.print_parser_visits = false,
64-
};
6540
static constexpr LSP_Language languages[] = {
6641
// Keep in sync with docs/lsp.adoc.
67-
LSP_Language("javascript"sv, jsx),
68-
LSP_Language("javascriptreact"sv, jsx),
69-
LSP_Language("js"sv, jsx),
70-
LSP_Language("js-jsx"sv, jsx),
42+
LSP_Language("javascript"sv, File_Language::javascript_jsx),
43+
LSP_Language("javascriptreact"sv, File_Language::javascript_jsx),
44+
LSP_Language("js"sv, File_Language::javascript_jsx),
45+
LSP_Language("js-jsx"sv, File_Language::javascript_jsx),
7146

72-
LSP_Language("typescript"sv, ts, typescript_autodetect_tag()),
47+
LSP_Language("typescript"sv, File_Language::typescript,
48+
typescript_autodetect_tag()),
7349

74-
LSP_Language("typescriptdefinition"sv, ts_definition),
75-
LSP_Language("typescriptsource"sv, ts),
50+
LSP_Language("typescriptdefinition"sv,
51+
File_Language::typescript_definition),
52+
LSP_Language("typescriptsource"sv, File_Language::typescript),
7653

77-
LSP_Language("tsx"sv, tsx),
78-
LSP_Language("typescriptreact"sv, tsx),
54+
LSP_Language("tsx"sv, File_Language::typescript_jsx),
55+
LSP_Language("typescriptreact"sv, File_Language::typescript_jsx),
7956
};
8057
const LSP_Language* lang = find_unique_if(
8158
std::begin(languages), std::end(languages),
@@ -97,7 +74,7 @@ struct LSP_Language {
9774

9875
char raw_language_id[20] = {};
9976
unsigned char language_id_size = 0;
100-
Linter_Options lint_options;
77+
File_Language language;
10178
bool typescript_autodetect = false;
10279
};
10380
}

src/quick-lint-js/lsp/lsp-server.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ void Linting_LSP_Server_Handler::handle_text_document_did_open_notification(
480480
LSP_Language::find(notification.language_id, notification.uri.data)) {
481481
auto doc = std::make_unique<LSP_Documents::Lintable_Document>();
482482
init_document(*doc);
483-
doc->lint_options = lang->lint_options;
483+
doc->language = lang->language;
484484

485485
auto config_file =
486486
this->config_loader_.watch_and_load_for_file(document_path,
@@ -754,8 +754,8 @@ LSP_Linter::~LSP_Linter() = default;
754754
void LSP_Linter::lint(LSP_Documents::Lintable_Document& doc,
755755
String8_View uri_json,
756756
Outgoing_JSON_RPC_Message_Queue& outgoing_messages) {
757-
this->lint(*doc.config, doc.lint_options, doc.doc.string(), uri_json,
758-
doc.version_json, outgoing_messages);
757+
this->lint(*doc.config, get_linter_options_from_language(doc.language),
758+
doc.doc.string(), uri_json, doc.version_json, outgoing_messages);
759759
}
760760

761761
void LSP_JavaScript_Linter::lint(

src/quick-lint-js/lsp/lsp-server.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ struct LSP_Documents {
106106
const Configuration_Change&) override;
107107

108108
Configuration* config;
109-
Linter_Options lint_options;
109+
// Resolved parsing mode. Might not match the languageId given in
110+
// textDocument/didOpen.
111+
//
112+
// See LSP_Language for how we determine this value.
113+
File_Language language;
110114
};
111115

112116
struct Unknown_Document final : Document_Base {

test/test-lsp-language.cpp

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,43 +16,36 @@ TEST(Test_LSP_Language, primary_languages) {
1616
const LSP_Language* language =
1717
LSP_Language::find("javascript"sv, dummy_uri);
1818
ASSERT_NE(language, nullptr);
19-
EXPECT_TRUE(language->lint_options.jsx)
19+
EXPECT_EQ(language->language, File_Language::javascript_jsx)
2020
<< "JSX support should be enabled for 'javascript'";
21-
EXPECT_FALSE(language->lint_options.typescript);
2221
}
2322

2423
{
2524
const LSP_Language* language =
2625
LSP_Language::find("javascriptreact"sv, dummy_uri);
2726
ASSERT_NE(language, nullptr);
28-
EXPECT_TRUE(language->lint_options.jsx);
29-
EXPECT_FALSE(language->lint_options.typescript);
27+
EXPECT_EQ(language->language, File_Language::javascript_jsx);
3028
}
3129

3230
{
3331
const LSP_Language* language =
3432
LSP_Language::find("typescriptsource"sv, dummy_uri);
3533
ASSERT_NE(language, nullptr);
36-
EXPECT_FALSE(language->lint_options.jsx);
37-
EXPECT_TRUE(language->lint_options.typescript);
38-
EXPECT_FALSE(language->lint_options.typescript_definition);
34+
EXPECT_EQ(language->language, File_Language::typescript);
3935
}
4036

4137
{
4238
const LSP_Language* language =
4339
LSP_Language::find("typescriptdefinition"sv, dummy_uri);
4440
ASSERT_NE(language, nullptr);
45-
EXPECT_FALSE(language->lint_options.jsx);
46-
EXPECT_TRUE(language->lint_options.typescript);
47-
EXPECT_TRUE(language->lint_options.typescript_definition);
41+
EXPECT_EQ(language->language, File_Language::typescript_definition);
4842
}
4943

5044
{
5145
const LSP_Language* language =
5246
LSP_Language::find("typescriptreact"sv, dummy_uri);
5347
ASSERT_NE(language, nullptr);
54-
EXPECT_TRUE(language->lint_options.jsx);
55-
EXPECT_TRUE(language->lint_options.typescript);
48+
EXPECT_EQ(language->language, File_Language::typescript_jsx);
5649
}
5750
}
5851

@@ -65,7 +58,7 @@ TEST(Test_LSP_Language, language_aliases) {
6558
SCOPED_TRACE(alias);
6659
const LSP_Language* alias_language = LSP_Language::find(alias, dummy_uri);
6760
ASSERT_NE(alias_language, nullptr);
68-
EXPECT_EQ(alias_language->lint_options, main_language->lint_options);
61+
EXPECT_EQ(alias_language->language, main_language->language);
6962
}
7063

7164
for (std::string_view alias : {"js-jsx"sv}) {
@@ -76,7 +69,7 @@ TEST(Test_LSP_Language, language_aliases) {
7669
SCOPED_TRACE(alias);
7770
const LSP_Language* alias_language = LSP_Language::find(alias, dummy_uri);
7871
ASSERT_NE(alias_language, nullptr);
79-
EXPECT_EQ(alias_language->lint_options, main_language->lint_options);
72+
EXPECT_EQ(alias_language->language, main_language->language);
8073
}
8174

8275
for (std::string_view alias : {"tsx"sv}) {
@@ -87,7 +80,7 @@ TEST(Test_LSP_Language, language_aliases) {
8780
SCOPED_TRACE(alias);
8881
const LSP_Language* alias_language = LSP_Language::find(alias, dummy_uri);
8982
ASSERT_NE(alias_language, nullptr);
90-
EXPECT_EQ(alias_language->lint_options, main_language->lint_options);
83+
EXPECT_EQ(alias_language->language, main_language->language);
9184
}
9285
}
9386

@@ -96,22 +89,22 @@ TEST(Test_LSP_Language, typescript_file_without_d_or_tsx_is_source) {
9689
const LSP_Language* language =
9790
LSP_Language::find("typescript"sv, u8"file:///test.ts"_sv);
9891
ASSERT_NE(language, nullptr);
99-
EXPECT_FALSE(language->lint_options.typescript_definition);
92+
EXPECT_EQ(language->language, File_Language::typescript);
10093
}
10194

10295
{
10396
const LSP_Language* language =
10497
LSP_Language::find("typescript"sv, u8"file:///folder.d.ts/test.ts"_sv);
10598
ASSERT_NE(language, nullptr);
106-
EXPECT_FALSE(language->lint_options.typescript_definition)
99+
EXPECT_EQ(language->language, File_Language::typescript)
107100
<< ".d. in containing directory should be ignored";
108101
}
109102

110103
{
111104
const LSP_Language* language =
112105
LSP_Language::find("typescript"sv, u8"file:///folder/test.tsx.ts"_sv);
113106
ASSERT_NE(language, nullptr);
114-
EXPECT_FALSE(language->lint_options.jsx)
107+
EXPECT_EQ(language->language, File_Language::typescript)
115108
<< ".tsx in file name but not in extension should be ignored";
116109
}
117110

@@ -131,45 +124,43 @@ TEST(Test_LSP_Language, typescript_file_with_d_is_definition) {
131124
SCOPED_TRACE(out_string8(uri));
132125
const LSP_Language* language = LSP_Language::find("typescript"sv, uri);
133126
ASSERT_NE(language, nullptr);
134-
EXPECT_TRUE(language->lint_options.typescript_definition);
135-
EXPECT_FALSE(language->lint_options.jsx);
127+
EXPECT_EQ(language->language, File_Language::typescript_definition);
136128
}
137129
}
138130

139131
TEST(Test_LSP_Language, typescript_file_with_tsx_is_typescript_jsx) {
140132
const LSP_Language* language =
141133
LSP_Language::find("typescript"sv, u8"file:///test.tsx"_sv);
142134
ASSERT_NE(language, nullptr);
143-
EXPECT_TRUE(language->lint_options.jsx);
144-
EXPECT_TRUE(language->lint_options.typescript);
135+
EXPECT_EQ(language->language, File_Language::typescript_jsx);
145136
}
146137

147138
TEST(Test_LSP_Language, typescriptsource_ignores_d_in_uri) {
148139
const LSP_Language* language =
149140
LSP_Language::find("typescriptsource"sv, u8"file:///test.d.ts"_sv);
150141
ASSERT_NE(language, nullptr);
151-
EXPECT_FALSE(language->lint_options.typescript_definition);
142+
EXPECT_EQ(language->language, File_Language::typescript);
152143
}
153144

154145
TEST(Test_LSP_Language, typescriptsource_ignores_tsx_in_uri) {
155146
const LSP_Language* language =
156147
LSP_Language::find("typescriptsource"sv, u8"file:///test.tsx"_sv);
157148
ASSERT_NE(language, nullptr);
158-
EXPECT_FALSE(language->lint_options.jsx);
149+
EXPECT_EQ(language->language, File_Language::typescript);
159150
}
160151

161152
TEST(Test_LSP_Language, typescriptdefinition_does_not_require_d_in_uri) {
162153
const LSP_Language* language =
163154
LSP_Language::find("typescriptdefinition"sv, u8"file:///test.ts"_sv);
164155
ASSERT_NE(language, nullptr);
165-
EXPECT_TRUE(language->lint_options.typescript_definition);
156+
EXPECT_EQ(language->language, File_Language::typescript_definition);
166157
}
167158

168159
TEST(Test_LSP_Language, typescriptreact_does_not_require_tsx_in_uri) {
169160
const LSP_Language* language =
170161
LSP_Language::find("typescriptreact"sv, u8"file:///test.ts"_sv);
171162
ASSERT_NE(language, nullptr);
172-
EXPECT_TRUE(language->lint_options.jsx);
163+
EXPECT_EQ(language->language, File_Language::typescript_jsx);
173164
}
174165
}
175166
}

0 commit comments

Comments
 (0)