+
Skip to content
This repository was archived by the owner on Aug 31, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 12 additions & 92 deletions crates/rome_js_analyze/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
pub use crate::registry::visit_registry;
use crate::semantic_services::{SemanticModelBuilderVisitor, SemanticModelVisitor};
use crate::suppression_action::apply_suppression_comment;
use control_flow::make_visitor;
use rome_analyze::context::ServiceBagRuleOptionsWrapper;
use rome_analyze::options::OptionsDeserializationDiagnostic;
use rome_analyze::{
AnalysisFilter, Analyzer, AnalyzerContext, AnalyzerOptions, AnalyzerSignal, ControlFlow,
DeserializableRuleOptions, InspectMatcher, LanguageRoot, MatchQueryParams, MetadataRegistry,
Phases, RuleAction, RuleRegistry, ServiceBag, SuppressionCommentEmitterPayload,
SuppressionKind, SyntaxVisitor,
Phases, RuleAction, RuleRegistry, ServiceBag, SuppressionKind, SyntaxVisitor,
};
use rome_aria::{AriaProperties, AriaRoles};
use rome_diagnostics::{category, FileId};
use rome_js_factory::make::{jsx_expression_child, token};
use rome_js_syntax::suppression::SuppressionDiagnostic;
use rome_js_syntax::{
suppression::parse_suppression_comment, AnyJsxChild, JsLanguage, JsSyntaxToken, T,
};
use rome_rowan::{AstNode, TokenAtOffset, TriviaPieceKind};
use rome_js_syntax::{suppression::parse_suppression_comment, JsLanguage};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use std::{borrow::Cow, error::Error};
Expand All @@ -30,13 +28,10 @@ mod react;
mod registry;
mod semantic_analyzers;
mod semantic_services;
mod suppression_action;
mod syntax;
pub mod utils;

pub use crate::registry::visit_registry;
use crate::semantic_services::{SemanticModelBuilderVisitor, SemanticModelVisitor};
use crate::utils::batch::JsBatchMutation;

pub(crate) type JsRuleAction = RuleAction<JsLanguage>;

/// Return the static [MetadataRegistry] for the JS analyzer rules
Expand Down Expand Up @@ -231,14 +226,17 @@ mod tests {
String::from_utf8(buffer).unwrap()
}

const SOURCE: &str = r#"<span aria-current="invalid"></span>
"#;
const SOURCE: &str = r#"something.forEach((Element, index) => {
return <List
><div key={index}>foo</div>
</List>;
})"#;

let parsed = parse(SOURCE, FileId::zero(), SourceType::jsx());

let mut error_ranges: Vec<TextRange> = Vec::new();
let options = AnalyzerOptions::default();
let rule_filter = RuleFilter::Rule("correctness", "noUselessFragments");
let rule_filter = RuleFilter::Rule("correctness", "noArrayIndexKey");
analyze(
FileId::zero(),
&parsed.tree(),
Expand Down Expand Up @@ -455,81 +453,3 @@ impl std::fmt::Display for RuleError {
}

impl Error for RuleError {}

/// We now try to "guess" the token where to apply the suppression comment.
/// Considering that the detection of suppression comments in the linter is "line based", we start
/// querying the node covered by the text range of the diagnostic, until we find the first token that has a newline
/// among its leading trivia.
///
/// If we're not able to find any token, it means that the range is
/// placed at row 1, so we take the root itself.
fn apply_suppression_comment(payload: SuppressionCommentEmitterPayload<JsLanguage>) {
let SuppressionCommentEmitterPayload {
token_offset,
mutation,
suppression_text,
diagnostic_text_range,
} = payload;
let current_token = match token_offset {
TokenAtOffset::None => None,
TokenAtOffset::Single(token) => Some(match find_token_with_newline(token.clone()) {
None => token,
Some(token) => token,
}),
TokenAtOffset::Between(left_token, right_token) => {
let chosen_token = if right_token.text_range().start() == diagnostic_text_range.start()
{
right_token
} else {
left_token
};
Some(chosen_token)
}
};
if let Some(current_token) = current_token {
if let Some(element) = current_token.ancestors().find_map(AnyJsxChild::cast) {
let jsx_comment = jsx_expression_child(
token(T!['{']).with_trailing_trivia([(
TriviaPieceKind::SingleLineComment,
format!("/* {} */", suppression_text).as_str(),
)]),
token(T!['}']),
);
mutation.add_jsx_element_before_element(
&element,
&AnyJsxChild::JsxExpressionChild(jsx_comment.build()),
);
} else {
let new_token = current_token.with_leading_trivia([
(TriviaPieceKind::Newline, "\n"),
(
TriviaPieceKind::SingleLineComment,
format!("// {} ", suppression_text).as_str(),
),
(TriviaPieceKind::Newline, "\n"),
]);
mutation.replace_token_transfer_trivia(current_token, new_token);
}
}
}

/// It checks if the current token has leading trivia newline. If not, it
/// it peeks the previous token and recursively call itself
fn find_token_with_newline(token: JsSyntaxToken) -> Option<JsSyntaxToken> {
let mut current_token = token;
loop {
let trivia = current_token.leading_trivia();
if trivia.pieces().any(|trivia| trivia.is_newline())
|| current_token.text_trimmed().contains('\n')
{
break;
} else if let Some(token) = current_token.prev_token() {
current_token = token;
continue;
} else {
return None;
}
}

Some(current_token)
}
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载