-
-
Notifications
You must be signed in to change notification settings - Fork 527
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(workspace): adds GraphQL parsing capabilities via feature (#3238)
Co-authored-by: Ze-Zheng Wu <[email protected]>
- Loading branch information
Showing
13 changed files
with
245 additions
and
10 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
use biome_rowan::FileSourceError; | ||
use std::ffi::OsStr; | ||
use std::path::Path; | ||
|
||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] | ||
#[derive( | ||
Debug, Clone, Default, Copy, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize, | ||
)] | ||
pub struct GraphqlFileSource {} | ||
|
||
impl GraphqlFileSource { | ||
/// Try to return the GraphQL file source corresponding to this file name from well-known files | ||
pub fn try_from_well_known(file_name: &str) -> Result<Self, FileSourceError> { | ||
// TODO: to be implemented | ||
Err(FileSourceError::UnknownFileName(file_name.into())) | ||
} | ||
|
||
/// Try to return the GraphQL file source corresponding to this file extension | ||
pub fn try_from_extension(extension: &str) -> Result<Self, FileSourceError> { | ||
match extension { | ||
"graphql" | "gql" => Ok(Self::default()), | ||
_ => Err(FileSourceError::UnknownExtension( | ||
Default::default(), | ||
extension.into(), | ||
)), | ||
} | ||
} | ||
|
||
/// Try to return the GraphQL file source corresponding to this language ID | ||
/// | ||
/// See the [LSP spec] and [VS Code spec] for a list of language identifiers | ||
/// | ||
/// [LSP spec]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentItem | ||
/// [VS Code spec]: https://code.visualstudio.com/docs/languages/identifiers | ||
pub fn try_from_language_id(language_id: &str) -> Result<Self, FileSourceError> { | ||
match language_id { | ||
"graphql" => Ok(Self::default()), | ||
_ => Err(FileSourceError::UnknownLanguageId(language_id.into())), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<&Path> for GraphqlFileSource { | ||
type Error = FileSourceError; | ||
|
||
fn try_from(path: &Path) -> Result<Self, Self::Error> { | ||
let file_name = path | ||
.file_name() | ||
.and_then(OsStr::to_str) | ||
.ok_or_else(|| FileSourceError::MissingFileName(path.into()))?; | ||
|
||
if let Ok(file_source) = Self::try_from_well_known(file_name) { | ||
return Ok(file_source); | ||
} | ||
|
||
// We assume the file extensions are case-insensitive | ||
// and we use the lowercase form of them for pattern matching | ||
let extension = &path | ||
.extension() | ||
.and_then(OsStr::to_str) | ||
.map(str::to_lowercase) | ||
.ok_or_else(|| FileSourceError::MissingFileExtension(path.into()))?; | ||
|
||
Self::try_from_extension(extension) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
use super::{DocumentFileSource, ExtensionHandler, ParseResult}; | ||
use crate::file_handlers::DebugCapabilities; | ||
use crate::file_handlers::{ | ||
AnalyzerCapabilities, Capabilities, FormatterCapabilities, ParserCapabilities, | ||
}; | ||
use crate::settings::{ | ||
FormatSettings, LanguageListSettings, LanguageSettings, LinterSettings, OverrideSettings, | ||
ServiceLanguage, Settings, | ||
}; | ||
use crate::workspace::GetSyntaxTreeResult; | ||
use biome_analyze::{AnalyzerConfiguration, AnalyzerOptions}; | ||
use biome_formatter::SimpleFormatOptions; | ||
use biome_fs::BiomePath; | ||
use biome_graphql_parser::parse_graphql_with_cache; | ||
use biome_graphql_syntax::{GraphqlLanguage, GraphqlRoot, GraphqlSyntaxNode}; | ||
use biome_parser::AnyParse; | ||
use biome_rowan::NodeCache; | ||
|
||
impl ServiceLanguage for GraphqlLanguage { | ||
type FormatterSettings = (); | ||
type LinterSettings = (); | ||
type OrganizeImportsSettings = (); | ||
type FormatOptions = SimpleFormatOptions; | ||
type ParserSettings = (); | ||
type EnvironmentSettings = (); | ||
|
||
fn lookup_settings(language: &LanguageListSettings) -> &LanguageSettings<Self> { | ||
&language.graphql | ||
} | ||
|
||
fn resolve_format_options( | ||
_global: Option<&FormatSettings>, | ||
_overrides: Option<&OverrideSettings>, | ||
_language: Option<&()>, | ||
_path: &BiomePath, | ||
_document_file_source: &DocumentFileSource, | ||
) -> Self::FormatOptions { | ||
SimpleFormatOptions::default() | ||
} | ||
|
||
fn resolve_analyzer_options( | ||
_global: Option<&Settings>, | ||
_linter: Option<&LinterSettings>, | ||
_overrides: Option<&OverrideSettings>, | ||
_language: Option<&Self::LinterSettings>, | ||
path: &BiomePath, | ||
_file_source: &DocumentFileSource, | ||
) -> AnalyzerOptions { | ||
AnalyzerOptions { | ||
configuration: AnalyzerConfiguration::default(), | ||
file_path: path.to_path_buf(), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, Default, PartialEq, Eq)] | ||
pub(crate) struct GraphqlFileHandler; | ||
|
||
impl ExtensionHandler for GraphqlFileHandler { | ||
fn capabilities(&self) -> Capabilities { | ||
Capabilities { | ||
parser: ParserCapabilities { parse: Some(parse) }, | ||
debug: DebugCapabilities { | ||
debug_syntax_tree: Some(debug_syntax_tree), | ||
debug_control_flow: None, | ||
debug_formatter_ir: None, | ||
}, | ||
analyzer: AnalyzerCapabilities { | ||
lint: None, | ||
code_actions: None, | ||
rename: None, | ||
fix_all: None, | ||
organize_imports: None, | ||
}, | ||
formatter: FormatterCapabilities { | ||
format: None, | ||
format_range: None, | ||
format_on_type: None, | ||
}, | ||
} | ||
} | ||
} | ||
|
||
fn parse( | ||
_biome_path: &BiomePath, | ||
file_source: DocumentFileSource, | ||
text: &str, | ||
_settings: Option<&Settings>, | ||
cache: &mut NodeCache, | ||
) -> ParseResult { | ||
let parse = parse_graphql_with_cache(text, cache); | ||
let root = parse.syntax(); | ||
let diagnostics = parse.into_diagnostics(); | ||
|
||
ParseResult { | ||
any_parse: AnyParse::new( | ||
// SAFETY: the parser should always return a root node | ||
root.as_send().unwrap(), | ||
diagnostics, | ||
), | ||
language: Some(file_source), | ||
} | ||
} | ||
|
||
fn debug_syntax_tree(_rome_path: &BiomePath, parse: AnyParse) -> GetSyntaxTreeResult { | ||
let syntax: GraphqlSyntaxNode = parse.syntax(); | ||
let tree: GraphqlRoot = parse.tree(); | ||
GetSyntaxTreeResult { | ||
cst: format!("{syntax:#?}"), | ||
ast: format!("{tree:#?}"), | ||
} | ||
} |
Oops, something went wrong.