Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: yaml file source #2839

Merged
merged 1 commit into from
May 13, 2024
Merged
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
101 changes: 101 additions & 0 deletions crates/biome_yaml_syntax/src/file_source.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use biome_rowan::FileSourceError;
use std::{ffi::OsStr, path::Path};

#[cfg_attr(feature = "schema", derive(schemars::YamlSchema))]
#[derive(
Debug, Clone, Default, Copy, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize,
)]
pub struct YamlFileSource {
// ?? Options
}

impl YamlFileSource {
// Well-known YAML files
// This list should be SORTED!
// Source: https://github.com/github-linguist/linguist/blob/4ac734c15a96f9e16fd12330d0cb8de82274f700/lib/linguist/languages.yml#L8081-L8083
// Note: we shouldn't include machine generated files
const WELL_KNOWN_YAML_FILES: &'static [&'static str] =
&[".clang-format", ".clang-tidy", ".gemrc"];

pub fn yaml() -> Self {
Self {
// ?? Options
}
}

pub fn is_well_known_yaml_file(file_name: &str) -> bool {
Self::WELL_KNOWN_YAML_FILES
.binary_search(&file_name)
.is_ok()
}

/// Try to return the Yaml file source corresponding to this file name from well-known files
pub fn try_from_well_known(file_name: &str) -> Result<Self, FileSourceError> {
if Self::is_well_known_yaml_file(file_name) {
return Ok(Self::yaml());
}
Err(FileSourceError::UnknownFileName(file_name.into()))
}

/// Try to return the YAML file source corresponding to this file extension
pub fn try_from_extension(extension: &str) -> Result<Self, FileSourceError> {
match extension {
// https://github.com/github-linguist/linguist/blob/4ac734c15a96f9e16fd12330d0cb8de82274f700/lib/linguist/languages.yml#L8070-L8079
// https://yaml.org/spec/1.2.2/
"yaml" | "yml" | "eyaml" | "eyml" | "cff" | "yaml-tmlanguage"
| "yaml-tmpreferences" | "yaml-tmtheme" | "mir" | "reek" | "rviz"
| "sublime-syntax" | "syntax" | "yaml.sed" | "yml.mysql" => Ok(Self::yaml()),
_ => Err(FileSourceError::UnknownExtension(
Default::default(),
extension.into(),
)),
}
}

/// Try to return the YAML file source corresponding to this language ID
///
/// See the [LSP spec] and [VS Code spec] for a list of language identifiers
///
/// The language ID for code snippets is registered by [VS Code built-in extensions]
///
/// [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 {
"yaml" => Ok(Self::yaml()),
_ => Err(FileSourceError::UnknownLanguageId(language_id.into())),
}
}
}

impl TryFrom<&Path> for YamlFileSource {
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)
}
}

#[test]
fn test_order() {
for items in YamlFileSource::WELL_KNOWN_YAML_FILES.windows(2) {
assert!(items[0] < items[1], "{} < {}", items[0], items[1]);
}
}