Skip to content

Commit 041196b

Browse files
authored
fix(noInvalidUseBeforeDeclaration): don't report use before ambient var declaration (#8104)
1 parent 0f0a658 commit 041196b

File tree

4 files changed

+41
-6
lines changed

4 files changed

+41
-6
lines changed

.changeset/some-brooms-pull.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
"@biomejs/biome": patch
3+
---
4+
5+
Fixed [`noInvalidUseBeforeDeclaration`](https://biomejs.dev/linter/rules/no-invalid-use-before-declaration/).
6+
The rule no longer reports a use of an ambient variable before its declarations.
7+
The rule also completely ignores TypeScript declaration files.
8+
The following code is no longer reported as invalid:
9+
10+
```ts
11+
CONSTANT;
12+
declare const CONSTANT: number;
13+
```

crates/biome_js_analyze/src/lint/correctness/no_invalid_use_before_declaration.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use biome_analyze::{Rule, RuleDiagnostic, RuleSource, context::RuleContext, decl
33
use biome_console::markup;
44
use biome_diagnostics::Severity;
55
use biome_js_syntax::{
6-
AnyJsExportNamedSpecifier, AnyJsIdentifierUsage,
6+
AnyJsExportNamedSpecifier, AnyJsIdentifierUsage, JsFileSource, JsVariableDeclarationClause,
7+
TsDeclareStatement,
78
binding_ext::{AnyJsBindingDeclaration, AnyJsIdentifierBinding},
89
};
910
use biome_rowan::{AstNode, SyntaxNodeOptionExt, TextRange};
@@ -81,6 +82,13 @@ impl Rule for NoInvalidUseBeforeDeclaration {
8182
fn run(ctx: &RuleContext<Self>) -> Self::Signals {
8283
let model = ctx.model();
8384
let mut result = vec![];
85+
let is_declaration_file = ctx
86+
.source_type::<JsFileSource>()
87+
.language()
88+
.is_definition_file();
89+
if is_declaration_file {
90+
return Box::default();
91+
}
8492
for binding in model.all_bindings() {
8593
let id = binding.tree();
8694
if matches!(
@@ -212,8 +220,21 @@ impl TryFrom<&AnyJsBindingDeclaration> for DeclarationKind {
212220
| AnyJsBindingDeclaration::JsArrayBindingPatternRestElement(_)
213221
| AnyJsBindingDeclaration::JsObjectBindingPatternProperty(_)
214222
| AnyJsBindingDeclaration::JsObjectBindingPatternRest(_)
215-
| AnyJsBindingDeclaration::JsObjectBindingPatternShorthandProperty(_)
216-
| AnyJsBindingDeclaration::JsVariableDeclarator(_) => Ok(Self::Variable),
223+
| AnyJsBindingDeclaration::JsObjectBindingPatternShorthandProperty(_) => {
224+
Ok(Self::Variable)
225+
}
226+
AnyJsBindingDeclaration::JsVariableDeclarator(declarator) => {
227+
if let Some(var_decl) = declarator.declaration()
228+
&& let Some(var_decl_clause) = var_decl.parent::<JsVariableDeclarationClause>()
229+
&& var_decl_clause.parent::<TsDeclareStatement>().is_some()
230+
{
231+
// Ambient variables, such as `declare const c;`,
232+
// can be used before their declarations.
233+
Err(())
234+
} else {
235+
Ok(Self::Variable)
236+
}
237+
}
217238
// Parameters
218239
AnyJsBindingDeclaration::JsFormalParameter(_)
219240
| AnyJsBindingDeclaration::JsRestParameter(_)

crates/biome_js_analyze/tests/specs/correctness/noInvalidUseBeforeDeclaration/valid.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ interface NestedBar {child: {grandChild: {[FOO]: typeof FOO; enumFoo: EnumFoo}}
2323
const FOO = 'foo';
2424
enum EnumFoo {BAR = 'bar'}
2525

26-
26+
c;
27+
declare const c: number;

crates/biome_js_analyze/tests/specs/correctness/noInvalidUseBeforeDeclaration/valid.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
---
22
source: crates/biome_js_analyze/tests/spec_tests.rs
3-
assertion_line: 135
43
expression: valid.ts
54
---
65
# Input
@@ -30,6 +29,7 @@ interface NestedBar {child: {grandChild: {[FOO]: typeof FOO; enumFoo: EnumFoo}}
3029
const FOO = 'foo';
3130
enum EnumFoo {BAR = 'bar'}
3231
33-
32+
c;
33+
declare const c: number;
3434
3535
```

0 commit comments

Comments
 (0)