Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

feat(rome_js_analyze): relax useLiteralEnumMembers #4720

Merged
merged 1 commit into from
Jul 23, 2023
Merged

feat(rome_js_analyze): relax useLiteralEnumMembers #4720

merged 1 commit into from
Jul 23, 2023

Conversation

Conaclos
Copy link
Contributor

@Conaclos Conaclos commented Jul 21, 2023

Summary

This PR relaxes useLiteralEnumMembers to allow referencing to previous enum members. This is commonly used in enum flags (it is used multiple times in the TypeScript Compiler source code). For example:

enum FileAccess {
    None = 0,
    Read = 1,
    Write = 1 << 1,
    All = Read | Write,
}

A wide range of references are recognized (Write, FileAccess.Write, FileAccess["Write"] FileAccess[`Write`])

To be more consistent, the rule is also relaxed to allow arbitrary numeric and string expressions that involve string and number literals.

I wonder if the rule should be renamed to useConstantEnumMembers to better reflect the new implementation.

Test Plan

Tests updated and extended.

@netlify
Copy link

netlify bot commented Jul 21, 2023

Deploy Preview for docs-rometools canceled.

Built without sensitive environment variables

Name Link
🔨 Latest commit 1a8dccb
🔍 Latest deploy log https://app.netlify.com/sites/docs-rometools/deploys/64bd0d736b85ce0009da732d

@github-actions github-actions bot added A-Website Area: website and documentation A-Linter Area: linter L-JavaScript Langauge: JavaScript A-Parser Area: parser labels Jul 21, 2023
@Conaclos Conaclos requested review from ematipico and removed request for ematipico July 21, 2023 12:27
@Conaclos Conaclos marked this pull request as draft July 21, 2023 12:49
@Conaclos Conaclos marked this pull request as ready for review July 21, 2023 19:22
@Conaclos Conaclos requested a review from ematipico July 21, 2023 19:23
Comment on lines 80 to 104
(move || {
let enum_declaration = ctx.query();
let mut result = Vec::new();
let mut enum_member_names = FxHashSet::default();
let enum_name = enum_declaration.id().ok()?;
let enum_name = enum_name.as_js_identifier_binding()?;
let enum_name = enum_name.name_token().ok()?;
let enum_name = enum_name.text_trimmed();
for enum_member in enum_declaration.members() {
let enum_member = enum_member.ok()?;
// no initializer => sequentially assigned literal integer
if let Some(initializer) = enum_member.initializer() {
let initializer = initializer.expression().ok()?;
let range = initializer.range();
if !is_constant_enum_expression(initializer, enum_name, &enum_member_names) {
result.push(range);
}
};
if let Some(name) = enum_member.name().ok()?.name() {
enum_member_names.insert(name.text().to_string());
}
}
} else if let Some(expr) = expr.as_js_template_expression() {
if expr.is_constant() {
return None;
}
}
Some(())
Some(result)
})()
.unwrap_or_default()
Copy link
Contributor

@ematipico ematipico Jul 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can avoid the closure by using .map on any ok(), returning Option<Vec<TextRange>> and using unwrap_or_default. Or create a function.

If you think about it, this code doesn't feel right.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't like all this ceremonial about error handling.
In the linter we still abort as soon as we encounter a syntax error.
Sometimes I dream of a monad that filters these errors, exposing to the linter only well-formed nodes.

crates/rome_js_syntax/src/expr_ext.rs Outdated Show resolved Hide resolved
@Conaclos Conaclos merged commit a624cbe into rome:main Jul 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A-Linter Area: linter A-Parser Area: parser A-Website Area: website and documentation L-JavaScript Langauge: JavaScript
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants