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

Taplo Integration Tracking #15908

Closed
wants to merge 2 commits into from
Closed
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
252 changes: 226 additions & 26 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ stdx = { path = "./crates/stdx", version = "0.0.0" }
syntax = { path = "./crates/syntax", version = "0.0.0" }
text-edit = { path = "./crates/text-edit", version = "0.0.0" }
toolchain = { path = "./crates/toolchain", version = "0.0.0" }
toml-syntax = { path = "./crates/toml-syntax", version = "0.0.0" }
tt = { path = "./crates/tt", version = "0.0.0" }
vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
vfs = { path = "./crates/vfs", version = "0.0.0" }
Expand Down
1 change: 1 addition & 0 deletions crates/rust-analyzer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ serde.workspace = true
num_cpus = "1.15.0"
mimalloc = { version = "0.1.30", default-features = false, optional = true }
lsp-server.workspace = true
taplo = "0.12.1"
tracing.workspace = true
tracing-subscriber.workspace = true
tracing-log = "0.2.0"
Expand Down
79 changes: 79 additions & 0 deletions crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ use project_model::{
};
use rustc_hash::{FxHashMap, FxHashSet};
use serde::{de::DeserializeOwned, Deserialize};
use taplo::{
dom::{node::Key, KeyOrIndex, Keys},
parser,
};
use vfs::{AbsPath, AbsPathBuf};

use crate::{
Expand All @@ -39,6 +43,17 @@ use crate::{

mod patch_old_style;

/// Where are configurations coming from?
/// There are two sources :
/// 1. Client sends them in its `InitializationOptions` in JSON format.
/// 2. .rust-analyzer.toml in TOML format.
enum ConfigSource {
Client(serde_json::Value),
RATOML(TomlContent),
}

struct TomlContent(String);

// Conventions for configuration keys to preserve maximal extendability without breakage:
// - Toggles (be it binary true/false or with more options in-between) should almost always suffix as `_enable`
// This has the benefit of namespaces being extensible, and if the suffix doesn't fit later it can be changed without breakage.
Expand Down Expand Up @@ -2119,6 +2134,43 @@ macro_rules! _config_data {
},)*
])
}


}


impl TryFrom<TomlContent> for ConfigData {
type Error = Vec<taplo::parser::Error>;

fn try_from(value: TomlContent) -> Result<Self, Self::Error> {
let content = value.0.as_str();
let parsed = parser::parse(content);

if !parsed.errors.is_empty() {
eprintln!("There are errors.");
return Err(parsed.errors)
}

let dom = parsed.into_dom();
$({
let subkeys = stringify!($field)
.split("_")
.into_iter()
.map(|sfix| KeyOrIndex::Key(Key::new(sfix)));
let keys = Keys::new(subkeys);
let matches = dom.find_all_matches(keys , true);

if let Ok(o) = matches {
o.into_iter().for_each(|elem| {
dbg!(&elem.0);
dbg!(&elem.1);
});
}

})*

Ok(ConfigData::default())
}
}

#[test]
Expand Down Expand Up @@ -2738,4 +2790,31 @@ mod tests {
matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(PathBuf::from("other_folder")))
);
}

mod ratoml {
use crate::config::{ConfigData, ConfigSource, TomlContent};

#[test]
fn test_1() {
let toml_file: &'static str = r#"
[assist]
emitMustUse = true
expressionFillDefault = "todo"

[cargo]
buildScripts.enable = true

[cargo.buildScripts]
invocationLocation = "workspace"
"#;
let config = TomlContent(toml_file.to_string());
let data: Result<ConfigData, _> = config.try_into();

if let Ok(config) = data {
eprintln!("YUPPI");
} else {
eprintln!("Oh no it failed.");
}
}
}
}
15 changes: 15 additions & 0 deletions crates/toml-sema/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "toml-sema"
version = "0.0.0"
rust-version.workspace = true
edition.workspace = true
license.workspace = true
authors.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
toml-syntax.workspace = true
semver.workspace = true
either.workspace = true
serde.workspace = true
96 changes: 96 additions & 0 deletions crates/toml-sema/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#![allow(dead_code)]
use semver;
use serde::Deserializer;
use std::collections::HashMap;
use toml_syntax::dom;

struct Semantics {
dict: HashMap<dom::Keys, Value>,
}

struct KeyValuePair {
key: dom::Keys,
value: Value,
}

struct Optional<T> {
default: T,
}

enum Value<T = ValueInner> {
Optional(Optional<T>),
Mandatory(T),
}

enum ValueInner {
Bool(bool),
Integer(Integer),
String(String),
Semver(semver::Version),
SemverReq(semver::VersionReq),
}

enum Integer {
RangedInteger(Ranged<i32>),
Integer(i32),
}

struct Ranged<T> {
lower: T,
upper: T,
}

enum String<T> {

EitherOf(T),
}

fn str_to_keys(s: &'_ str) -> dom::Keys {
let subkeys = s.split(".").into_iter().map(|sfix| {
assert!(!sfix.is_empty());
dom::KeyOrIndex::Key(dom::node::Key::new(sfix))
});
dom::Keys::new(subkeys)
}

impl Semantics {
fn new(kvs: Vec<(&str, Value)>) -> Semantics {
Semantics { dict: kvs.into_iter().map(|kv| (str_to_keys(kv.0), kv.1)).collect() }
}
}

#[cfg(test)]
mod tests {
use serde::Deserialize;
use toml_syntax::dom::{node::Key, KeyOrIndex, Keys};

use crate::{KeyValuePair, Optional, Semantics, Value};

fn test_1() {
let a = r#"
[assist]
emitMustUse = true
expressionFillDefault = "todo"

[cargo]
buildScripts.enable = true

[cargo.buildScripts]
invocationLocation = "workspace"
"#;
let parsed = toml_syntax::parse_toml(a);
let dom = parsed.into_dom();

#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
enum ExprFillDefaultDef {
Todo,
Default,
}

let kv1 = ("assist.emitMustUse", Value::Optional(Optional { default: false }));
let kv2 = ( "assist.expressionFillDefault" , Value::Optional(Optional { default: }));

let sema = Semantics::new(vec![]);
}
}
12 changes: 12 additions & 0 deletions crates/toml-syntax/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "toml-syntax"
version = "0.0.0"
rust-version.workspace = true
edition.workspace = true
license.workspace = true
authors.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
taplo = "0.12.1"
7 changes: 7 additions & 0 deletions crates/toml-syntax/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use taplo::parser;

pub use taplo::dom;

pub fn parse_toml<'a>(content: &'a str) -> parser::Parse {
parser::parse(content)
}
Loading