+
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions crates/rome_cli/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@ impl Execution {
}
}

pub(crate) fn is_ci(&self) -> bool {
pub(crate) const fn is_ci(&self) -> bool {
matches!(self.traversal_mode, TraversalMode::CI { .. })
}

pub(crate) fn is_check(&self) -> bool {
pub(crate) const fn is_check(&self) -> bool {
matches!(self.traversal_mode, TraversalMode::Check { .. })
}

pub(crate) fn is_format(&self) -> bool {
pub(crate) const fn is_format(&self) -> bool {
matches!(self.traversal_mode, TraversalMode::Format { .. })
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ statement();
# Emitted Messages

```block
Formatted 1 file(s) in <TIME>
Formatted 2 file(s) in <TIME>
```


2 changes: 2 additions & 0 deletions crates/rome_json_formatter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ where
N: AstNode<Language = JsonLanguage>,
{
fn fmt(&self, node: &N, f: &mut JsonFormatter) -> FormatResult<()> {
f.comments().mark_suppression_checked(node.syntax());

self.fmt_fields(node, f)
}

Expand Down
1 change: 0 additions & 1 deletion crates/rome_json_parser/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@ fn parse_rest(p: &mut JsonParser, value: ParsedSyntax) {
let range = match parse_value(p) {
Present(value) => value.range(p),
Absent => ParseRecovery::new(JSON_BOGUS_VALUE, VALUE_START)
.enable_recovery_on_line_break()
.recover(p)
.expect("Expect recovery to succeed because parser isn't at EOF nor at a value.")
.range(p),
Expand Down
1 change: 1 addition & 0 deletions crates/rome_service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ rome_js_formatter = { path = "../rome_js_formatter", features = ["serde"] }
rome_js_semantic = { path = "../rome_js_semantic" }
rome_json_parser = { path = "../rome_json_parser" }
rome_json_syntax = { path = "../rome_json_syntax" }
rome_json_formatter = { path = "../rome_json_formatter" }
rome_rowan = { path = "../rome_rowan", features = ["serde"] }
rome_text_edit = { path = "../rome_text_edit" }
indexmap = { workspace = true, features = ["serde"] }
Expand Down
2 changes: 1 addition & 1 deletion crates/rome_service/src/file_handlers/javascript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ pub struct JsLinterSettings {

impl Language for JsLanguage {
type FormatterSettings = JsFormatterSettings;
type FormatOptions = JsFormatOptions;
type LinterSettings = JsLinterSettings;
type FormatOptions = JsFormatOptions;

fn lookup_settings(languages: &LanguagesSettings) -> &LanguageSettings<Self> {
&languages.javascript
Expand Down
138 changes: 134 additions & 4 deletions crates/rome_service/src/file_handlers/json.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
use super::{ExtensionHandler, Mime};
use crate::file_handlers::{Capabilities, ParserCapabilities};
use crate::file_handlers::{Capabilities, FormatterCapabilities, ParserCapabilities};
use crate::file_handlers::{DebugCapabilities, Language as LanguageId};
use crate::settings::{
FormatSettings, Language, LanguageSettings, LanguagesSettings, SettingsHandle,
};
use crate::workspace::server::AnyParse;
use crate::workspace::GetSyntaxTreeResult;
use crate::RomeError;
#[cfg(debug_assertions)]
use rome_formatter::FormatError;
use rome_formatter::Printed;
use rome_fs::RomePath;
use rome_json_formatter::context::JsonFormatOptions;
use rome_json_formatter::format_node;
use rome_json_parser::JsonParse;
use rome_json_syntax::{JsonRoot, JsonSyntaxNode};
use rome_json_syntax::{JsonLanguage, JsonRoot, JsonSyntaxNode};
#[cfg(debug_assertions)]
use rome_rowan::{TextRange, TextSize, TokenAtOffset};
use tracing::debug;

impl Language for JsonLanguage {
type FormatterSettings = ();
type LinterSettings = ();
type FormatOptions = JsonFormatOptions;

fn lookup_settings(language: &LanguagesSettings) -> &LanguageSettings<Self> {
&language.json
}

fn resolve_format_options(
global: &FormatSettings,
_language: &Self::FormatterSettings,
_path: &RomePath,
) -> Self::FormatOptions {
JsonFormatOptions::default()
.with_indent_style(global.indent_style.unwrap_or_default())
.with_line_width(global.line_width.unwrap_or_default())
}
}

#[derive(Debug, Default, PartialEq, Eq)]
pub(crate) struct JsonFileHandler;
Expand All @@ -29,14 +61,28 @@ impl ExtensionHandler for JsonFileHandler {
debug: DebugCapabilities {
debug_syntax_tree: Some(debug_syntax_tree),
debug_control_flow: None,
debug_formatter_ir: None,
debug_formatter_ir: Some(debug_formatter_ir),
},
analyzer: Default::default(),
formatter: Default::default(),
formatter: formatter_capabilities(),
}
}
}

#[cfg(debug_assertions)]
fn formatter_capabilities() -> FormatterCapabilities {
FormatterCapabilities {
format: Some(format),
format_range: Some(format_range),
format_on_type: Some(format_on_type),
}
}

#[cfg(not(debug_assertions))]
fn formatter_capabilities() -> FormatterCapabilities {
FormatterCapabilities::default()
}

fn parse(rome_path: &RomePath, _: LanguageId, text: &str) -> AnyParse {
let file_id = rome_path.file_id();

Expand All @@ -53,6 +99,90 @@ fn debug_syntax_tree(_rome_path: &RomePath, parse: AnyParse) -> GetSyntaxTreeRes
}
}

fn debug_formatter_ir(
rome_path: &RomePath,
parse: AnyParse,
settings: SettingsHandle,
) -> Result<String, RomeError> {
let options = settings.format_options::<JsonLanguage>(rome_path);

let tree = parse.syntax();
let formatted = format_node(options, &tree)?;

let root_element = formatted.into_document();
Ok(root_element.to_string())
}

#[tracing::instrument(level = "debug", skip(parse))]
fn format(
rome_path: &RomePath,
parse: AnyParse,
settings: SettingsHandle,
) -> Result<Printed, RomeError> {
let options = settings.format_options::<JsonLanguage>(rome_path);

debug!("Format with the following options: \n{}", options);

let tree = parse.syntax();
let formatted = format_node(options, &tree)?;

match formatted.print() {
Ok(printed) => Ok(printed),
Err(error) => Err(RomeError::FormatError(error.into())),
}
}

#[cfg(debug_assertions)]
fn format_range(
rome_path: &RomePath,
parse: AnyParse,
settings: SettingsHandle,
range: TextRange,
) -> Result<Printed, RomeError> {
let options = settings.format_options::<JsonLanguage>(rome_path);

let tree = parse.syntax();
let printed = rome_json_formatter::format_range(options, &tree, range)?;
Ok(printed)
}

#[cfg(debug_assertions)]
fn format_on_type(
rome_path: &RomePath,
parse: AnyParse,
settings: SettingsHandle,
offset: TextSize,
) -> Result<Printed, RomeError> {
let options = settings.format_options::<JsonLanguage>(rome_path);

let tree = parse.syntax();

let range = tree.text_range();
if offset < range.start() || offset > range.end() {
return Err(RomeError::FormatError(FormatError::RangeError {
input: TextRange::at(offset, TextSize::from(0)),
tree: range,
}));
}

let token = match tree.token_at_offset(offset) {
// File is empty, do nothing
TokenAtOffset::None => panic!("empty file"),
TokenAtOffset::Single(token) => token,
// The cursor should be right after the closing character that was just typed,
// select the previous token as the correct one
TokenAtOffset::Between(token, _) => token,
};

let root_node = match token.parent() {
Some(node) => node,
None => panic!("found a token with no parent"),
};

let printed = rome_json_formatter::format_sub_tree(options, &root_node)?;
Ok(printed)
}

impl From<JsonParse> for AnyParse {
fn from(parse: JsonParse) -> Self {
let root = parse.syntax();
Expand Down
2 changes: 2 additions & 0 deletions crates/rome_service/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rome_diagnostics::Category;
use rome_formatter::{IndentStyle, LineWidth};
use rome_fs::RomePath;
use rome_js_syntax::JsLanguage;
use rome_json_syntax::JsonLanguage;
use std::{
num::NonZeroU64,
sync::{RwLock, RwLockReadGuard},
Expand Down Expand Up @@ -152,6 +153,7 @@ impl Default for LinterSettings {
#[derive(Debug, Default)]
pub struct LanguagesSettings {
pub javascript: LanguageSettings<JsLanguage>,
pub json: LanguageSettings<JsonLanguage>,
}

pub trait Language: rome_rowan::Language {
Expand Down
70 changes: 43 additions & 27 deletions crates/rome_service/src/workspace/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
use dashmap::{mapref::entry::Entry, DashMap};
use indexmap::IndexSet;
use rome_analyze::{AnalysisFilter, RuleFilter};
use rome_diagnostics::{serde::Diagnostic, DiagnosticExt};
use rome_diagnostics::{serde::Diagnostic as SerdeDiagnostic, Diagnostic, DiagnosticExt, Severity};
use rome_formatter::Printed;
use rome_fs::RomePath;
use rome_parser::diagnostic::ParseDiagnostic;
Expand Down Expand Up @@ -84,8 +84,11 @@ impl AnyParse {
}

/// This function transforms diagnostics coming from the parser into serializable diagnostics
pub(crate) fn into_diagnostics(self) -> Vec<Diagnostic> {
self.diagnostics.into_iter().map(Diagnostic::new).collect()
pub(crate) fn into_diagnostics(self) -> Vec<SerdeDiagnostic> {
self.diagnostics
.into_iter()
.map(SerdeDiagnostic::new)
.collect()
}

fn has_errors(&self) -> bool {
Expand Down Expand Up @@ -372,44 +375,57 @@ impl Workspace for WorkspaceServer {
&self,
params: PullDiagnosticsParams,
) -> Result<PullDiagnosticsResult, RomeError> {
let capabilities = self.get_capabilities(&params.path);
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 had to change the pull_diagnostics implementation to return the parse diagnostics if linting isn't supported instead of emitting an "unsupported" error.

Not sure if the way I did it is the "best".

Copy link
Contributor

Choose a reason for hiding this comment

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

You'd still want to use the lint function, even when the actual linter is disabled. When the linter is disabled, you'd need to create the AnalysisFilter with categories: RuleCategories::SYNTAX instead.

This is necessary because we could have analyzers that work at syntax level. An example is noSuperWithoutExtends

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How would I call into the lint function if it is None? It isn't testing if the linter is disabled, it is testing if the language supports linting.

My understanding is that self.get_capabilities returns the capabilities of the language, which is always Some for languages that support linting and only is None for JSON unrelated if the linter is enabled or not.

Copy link
Contributor

Choose a reason for hiding this comment

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

Unfortunately there's a slight mismatch between "capabilities" and "features": what the lint capability actually represents is whether we have a rome_<lang>_analyze crate for this language (this includes syntax rules, lint rules and assist rules), and not just whether we support linting for this language

let lint = capabilities
.analyzer
.lint
.ok_or_else(self.build_capability_error(&params.path))?;

let settings = self.settings.read().unwrap();
let feature = if params.categories.is_syntax() {
FeatureName::Format
} else {
FeatureName::Lint
};

let parse = self.get_parse(params.path.clone(), Some(feature))?;
let rules = settings.linter().rules.as_ref();
let rule_filter_list = self.build_rule_filter_list(rules);
let mut filter = AnalysisFilter::from_enabled_rules(Some(rule_filter_list.as_slice()));
filter.categories = params.categories;
let settings = self.settings.read().unwrap();

let results = lint(LintParams {
rome_path: &params.path,
parse,
filter,
rules,
settings: self.settings(),
max_diagnostics: params.max_diagnostics,
});
let (diagnostics, errors, skipped_diagnostics) = if let Some(lint) =
self.get_capabilities(&params.path).analyzer.lint
{
let rules = settings.linter().rules.as_ref();
let rule_filter_list = self.build_rule_filter_list(rules);
let mut filter = AnalysisFilter::from_enabled_rules(Some(rule_filter_list.as_slice()));
filter.categories = params.categories;

let results = lint(LintParams {
rome_path: &params.path,
parse,
filter,
rules,
settings: self.settings(),
max_diagnostics: params.max_diagnostics,
});

(
results.diagnostics,
results.errors,
results.skipped_diagnostics,
)
} else {
let parse_diagnostics = parse.into_diagnostics();
let errors = parse_diagnostics
.iter()
.filter(|diag| diag.severity() <= Severity::Error)
.count();

(parse_diagnostics, errors, 0)
};

Ok(PullDiagnosticsResult {
diagnostics: results
.diagnostics
diagnostics: diagnostics
.into_iter()
.map(|diag| {
let diag = diag.with_file_path(params.path.as_path().display().to_string());
Diagnostic::new(diag)
SerdeDiagnostic::new(diag)
})
.collect(),
errors: results.errors,
skipped_diagnostics: results.skipped_diagnostics,
errors,
skipped_diagnostics,
})
}

Expand Down
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载