Skip to content

Commit 06b5c58

Browse files
committed
fix(lsp): lint-ignore directives follow leading comments
1 parent 2eb0341 commit 06b5c58

File tree

2 files changed

+81
-88
lines changed

2 files changed

+81
-88
lines changed

cli/lsp/analysis.rs

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,51 +1100,59 @@ impl CodeActionCollection {
11001100
.actions
11011101
.push(CodeActionKind::DenoLint(ignore_error_action));
11021102

1103-
// Disable a lint error for the entire file.
1104-
let maybe_ignore_comment = module
1103+
let parsed_source = module
11051104
.open_data
11061105
.as_ref()
1107-
.and_then(|d| d.parsed_source.as_ref())
1108-
.and_then(|ps| {
1109-
let ps = ps.as_ref().ok()?;
1110-
// Note: we can use ps.get_leading_comments() but it doesn't
1111-
// work when shebang is present at the top of the file.
1112-
ps.comments().get_vec().iter().find_map(|c| {
1113-
let comment_text = c.text.trim();
1114-
comment_text.split_whitespace().next().and_then(|prefix| {
1115-
if prefix == "deno-lint-ignore-file" {
1116-
Some(c.clone())
1117-
} else {
1118-
None
1119-
}
1120-
})
1106+
.and_then(|d| d.parsed_source.as_ref()?.as_ref().ok());
1107+
let next_leading_comment_range = {
1108+
let line = parsed_source
1109+
.and_then(|ps| {
1110+
let last_comment = ps.get_leading_comments()?.iter().last()?;
1111+
Some(module.text_info().line_index(last_comment.end()) as u32 + 1)
11211112
})
1122-
});
1123-
1124-
let mut new_text = format!("// deno-lint-ignore-file {code}\n");
1125-
let mut range = lsp::Range {
1126-
start: lsp::Position {
1127-
line: 0,
1128-
character: 0,
1129-
},
1130-
end: lsp::Position {
1131-
line: 0,
1132-
character: 0,
1133-
},
1113+
.unwrap_or(0);
1114+
let position = lsp::Position { line, character: 0 };
1115+
lsp::Range {
1116+
start: position,
1117+
end: position,
1118+
}
11341119
};
1120+
1121+
// Disable a lint error for the entire file.
1122+
let maybe_ignore_comment = parsed_source.and_then(|ps| {
1123+
// Note: we can use ps.get_leading_comments() but it doesn't
1124+
// work when shebang is present at the top of the file.
1125+
ps.comments().get_vec().iter().find_map(|c| {
1126+
let comment_text = c.text.trim();
1127+
comment_text.split_whitespace().next().and_then(|prefix| {
1128+
if prefix == "deno-lint-ignore-file" {
1129+
Some(c.clone())
1130+
} else {
1131+
None
1132+
}
1133+
})
1134+
})
1135+
});
1136+
1137+
let new_text;
1138+
let range;
11351139
// If ignore file comment already exists, append the lint code
11361140
// to the existing comment.
11371141
if let Some(ignore_comment) = maybe_ignore_comment {
11381142
new_text = format!(" {code}");
11391143
// Get the end position of the comment.
1140-
let line = text_info.line_and_column_index(ignore_comment.end());
1144+
let index = text_info.line_and_column_index(ignore_comment.end());
11411145
let position = lsp::Position {
1142-
line: line.line_index as u32,
1143-
character: line.column_index as u32,
1146+
line: index.line_index as u32,
1147+
character: index.column_index as u32,
1148+
};
1149+
range = lsp::Range {
1150+
start: position,
1151+
end: position,
11441152
};
1145-
// Set the edit range to the end of the comment.
1146-
range.start = position;
1147-
range.end = position;
1153+
} else {
1154+
new_text = format!("// deno-lint-ignore-file {code}\n");
1155+
range = next_leading_comment_range;
11481156
}
11491157

11501158
let mut changes = HashMap::new();
@@ -1172,16 +1180,7 @@ impl CodeActionCollection {
11721180
uri.clone(),
11731181
vec![lsp::TextEdit {
11741182
new_text: "// deno-lint-ignore-file\n".to_string(),
1175-
range: lsp::Range {
1176-
start: lsp::Position {
1177-
line: 0,
1178-
character: 0,
1179-
},
1180-
end: lsp::Position {
1181-
line: 0,
1182-
character: 0,
1183-
},
1184-
},
1183+
range: next_leading_comment_range,
11851184
}],
11861185
);
11871186
let ignore_file_action = lsp::CodeAction {

tests/integration/lsp_tests.rs

Lines changed: 38 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14026,32 +14026,26 @@ console.log(snake_case);
1402614026
#[timeout(300_000)]
1402714027
fn lsp_code_actions_lint_fixes() {
1402814028
let context = TestContextBuilder::new().use_temp_cwd().build();
14029+
let temp_dir = context.temp_dir();
14030+
let file = temp_dir
14031+
.source_file("file.ts", "// Copyright x-y. MIT licence.\nwindow;\n");
1402914032
let mut client = context.new_lsp_command().build();
1403014033
client.initialize_default();
14031-
let diagnostics = client.did_open(json!({
14032-
"textDocument": {
14033-
"uri": "file:///a/file.ts",
14034-
"languageId": "typescript",
14035-
"version": 1,
14036-
"text": "window;",
14037-
}
14038-
}));
14034+
let diagnostics = client.did_open_file(&file);
1403914035
let diagnostics = diagnostics.all();
1404014036
let diagnostic = &diagnostics[0];
1404114037
let res = client.write_request(
1404214038
"textDocument/codeAction",
1404314039
json!({
14044-
"textDocument": {
14045-
"uri": "file:///a/file.ts"
14046-
},
14040+
"textDocument": { "uri": file.uri() },
1404714041
"range": {
14048-
"start": { "line": 0, "character": 0 },
14049-
"end": { "line": 0, "character": 6 }
14042+
"start": { "line": 1, "character": 0 },
14043+
"end": { "line": 1, "character": 6 },
1405014044
},
1405114045
"context": {
1405214046
"diagnostics": [diagnostic],
14053-
"only": ["quickfix"]
14054-
}
14047+
"only": ["quickfix"],
14048+
},
1405514049
}),
1405614050
);
1405714051
assert_eq!(
@@ -14062,61 +14056,61 @@ fn lsp_code_actions_lint_fixes() {
1406214056
"diagnostics": [diagnostic],
1406314057
"edit": {
1406414058
"changes": {
14065-
"file:///a/file.ts": [{
14059+
file.uri().as_str(): [{
1406614060
"range": {
14067-
"start": { "line": 0, "character": 0 },
14068-
"end": { "line": 0, "character": 6 }
14061+
"start": { "line": 1, "character": 0 },
14062+
"end": { "line": 1, "character": 6 },
1406914063
},
14070-
"newText": "globalThis"
14071-
}]
14072-
}
14073-
}
14064+
"newText": "globalThis",
14065+
}],
14066+
},
14067+
},
1407414068
}, {
1407514069
"title": "Disable no-window for this line",
1407614070
"kind": "quickfix",
1407714071
"diagnostics": [diagnostic],
1407814072
"edit": {
1407914073
"changes": {
14080-
"file:///a/file.ts": [{
14074+
file.uri().as_str(): [{
1408114075
"range": {
14082-
"start": { "line": 0, "character": 0 },
14083-
"end": { "line": 0, "character": 0 }
14076+
"start": { "line": 1, "character": 0 },
14077+
"end": { "line": 1, "character": 0 },
1408414078
},
14085-
"newText": "// deno-lint-ignore no-window\n"
14086-
}]
14087-
}
14088-
}
14079+
"newText": "// deno-lint-ignore no-window\n",
14080+
}],
14081+
},
14082+
},
1408914083
}, {
1409014084
"title": "Disable no-window for the entire file",
1409114085
"kind": "quickfix",
1409214086
"diagnostics": [diagnostic],
1409314087
"edit": {
1409414088
"changes": {
14095-
"file:///a/file.ts": [{
14089+
file.uri().as_str(): [{
1409614090
"range": {
14097-
"start": { "line": 0, "character": 0 },
14098-
"end": { "line": 0, "character": 0 }
14091+
"start": { "line": 1, "character": 0 },
14092+
"end": { "line": 1, "character": 0 },
1409914093
},
14100-
"newText": "// deno-lint-ignore-file no-window\n"
14101-
}]
14102-
}
14103-
}
14094+
"newText": "// deno-lint-ignore-file no-window\n",
14095+
}],
14096+
},
14097+
},
1410414098
}, {
1410514099
"title": "Ignore lint errors for the entire file",
1410614100
"kind": "quickfix",
1410714101
"diagnostics": [diagnostic],
1410814102
"edit": {
1410914103
"changes": {
14110-
"file:///a/file.ts": [{
14104+
file.uri().as_str(): [{
1411114105
"range": {
14112-
"start": { "line": 0, "character": 0 },
14113-
"end": { "line": 0, "character": 0 }
14106+
"start": { "line": 1, "character": 0 },
14107+
"end": { "line": 1, "character": 0 },
1411414108
},
14115-
"newText": "// deno-lint-ignore-file\n"
14116-
}]
14117-
}
14118-
}
14119-
}])
14109+
"newText": "// deno-lint-ignore-file\n",
14110+
}],
14111+
},
14112+
},
14113+
}]),
1412014114
);
1412114115
client.shutdown();
1412214116
}

0 commit comments

Comments
 (0)