Skip to content

Commit 7068df3

Browse files
committed
feat: add schema field
1 parent 0f53352 commit 7068df3

File tree

2 files changed

+93
-5
lines changed

2 files changed

+93
-5
lines changed

crates/pglt_configuration/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ pub const VERSION: &str = match option_env!("PGLT_VERSION") {
4545
#[partial(cfg_attr(feature = "schema", derive(schemars::JsonSchema)))]
4646
#[partial(serde(deny_unknown_fields, rename_all = "camelCase"))]
4747
pub struct Configuration {
48+
/// A field for the [JSON schema](https://json-schema.org/) specification
49+
#[partial(serde(rename = "$schema"))]
50+
#[partial(bpaf(hide))]
51+
pub schema: String,
52+
4853
/// The configuration of the VCS integration
4954
#[partial(type, bpaf(external(partial_vcs_configuration), optional, hide_usage))]
5055
pub vcs: VcsConfiguration,
@@ -79,6 +84,10 @@ impl PartialConfiguration {
7984
/// Returns the initial configuration.
8085
pub fn init() -> Self {
8186
Self {
87+
// TODO: Update this once we have a static url
88+
schema: Some(format!(
89+
"https://supabase-community.github.io/postgres_lsp/schemas/{VERSION}/schema.json"
90+
)),
8291
files: Some(PartialFilesConfiguration {
8392
ignore: Some(Default::default()),
8493
..Default::default()

crates/pglt_workspace/src/configuration.rs

Lines changed: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{
77
use pglt_analyse::AnalyserRules;
88
use pglt_configuration::{
99
ConfigurationDiagnostic, ConfigurationPathHint, ConfigurationPayload, PartialConfiguration,
10-
push_to_analyser_rules,
10+
VERSION, push_to_analyser_rules,
1111
};
1212
use pglt_fs::{AutoSearchResult, ConfigName, FileSystem, OpenOptions};
1313

@@ -97,7 +97,7 @@ fn load_config(
9797
// we'll load it directly
9898
if let ConfigurationPathHint::FromUser(ref config_file_path) = base_path {
9999
if file_system.path_is_file(config_file_path) {
100-
let content = file_system.read_file_from_path(config_file_path)?;
100+
let content = strip_jsonc_comments(&file_system.read_file_from_path(config_file_path)?);
101101

102102
let deserialized = serde_json::from_str::<PartialConfiguration>(&content)
103103
.map_err(ConfigurationDiagnostic::new_deserialization_error)?;
@@ -128,8 +128,9 @@ fn load_config(
128128
)? {
129129
let AutoSearchResult { content, file_path } = auto_search_result;
130130

131-
let deserialized = serde_json::from_str::<PartialConfiguration>(&content)
132-
.map_err(ConfigurationDiagnostic::new_deserialization_error)?;
131+
let deserialized =
132+
serde_json::from_str::<PartialConfiguration>(&strip_jsonc_comments(&content))
133+
.map_err(ConfigurationDiagnostic::new_deserialization_error)?;
133134

134135
Ok(Some(ConfigurationPayload {
135136
deserialized,
@@ -150,7 +151,7 @@ fn load_config(
150151
/// - the program doesn't have the write rights
151152
pub fn create_config(
152153
fs: &mut DynRef<dyn FileSystem>,
153-
configuration: PartialConfiguration,
154+
configuration: &mut PartialConfiguration,
154155
) -> Result<(), WorkspaceError> {
155156
let path = PathBuf::from(ConfigName::pglt_json());
156157

@@ -168,6 +169,19 @@ pub fn create_config(
168169
}
169170
})?;
170171

172+
// we now check if biome is installed inside `node_modules` and if so, we use the schema from there
173+
if VERSION == "0.0.0" {
174+
let schema_path = Path::new("./node_modules/@pglt/pglt/schema.json");
175+
let options = OpenOptions::default().read(true);
176+
if fs.open_with_options(schema_path, options).is_ok() {
177+
configuration.schema = schema_path.to_str().map(String::from);
178+
}
179+
} else {
180+
configuration.schema = Some(format!(
181+
"https://supabase-community.github.io/postgres_lsp/schemas/{VERSION}/schema.json"
182+
));
183+
}
184+
171185
let contents = serde_json::to_string_pretty(&configuration)
172186
.map_err(|_| ConfigurationDiagnostic::new_serialization_error())?;
173187

@@ -186,3 +200,68 @@ pub fn to_analyser_rules(settings: &Settings) -> AnalyserRules {
186200
}
187201
analyser_rules
188202
}
203+
204+
/// Takes a string of jsonc content and returns a comment free version
205+
/// which should parse fine as regular json.
206+
/// Nested block comments are supported.
207+
pub fn strip_jsonc_comments(jsonc_input: &str) -> String {
208+
let mut json_output = String::new();
209+
210+
let mut block_comment_depth: u8 = 0;
211+
let mut is_in_string: bool = false; // Comments cannot be in strings
212+
213+
for line in jsonc_input.split('\n') {
214+
let mut last_char: Option<char> = None;
215+
for cur_char in line.chars() {
216+
// Check whether we're in a string
217+
if block_comment_depth == 0 && last_char != Some('\\') && cur_char == '"' {
218+
is_in_string = !is_in_string;
219+
}
220+
221+
// Check for line comment start
222+
if !is_in_string && last_char == Some('/') && cur_char == '/' {
223+
last_char = None;
224+
json_output.push_str(" ");
225+
break; // Stop outputting or parsing this line
226+
}
227+
// Check for block comment start
228+
if !is_in_string && last_char == Some('/') && cur_char == '*' {
229+
block_comment_depth += 1;
230+
last_char = None;
231+
json_output.push_str(" ");
232+
// Check for block comment end
233+
} else if !is_in_string && last_char == Some('*') && cur_char == '/' {
234+
block_comment_depth = block_comment_depth.saturating_sub(1);
235+
last_char = None;
236+
json_output.push_str(" ");
237+
// Output last char if not in any block comment
238+
} else {
239+
if block_comment_depth == 0 {
240+
if let Some(last_char) = last_char {
241+
json_output.push(last_char);
242+
}
243+
} else {
244+
json_output.push_str(" ");
245+
}
246+
last_char = Some(cur_char);
247+
}
248+
}
249+
250+
// Add last char and newline if not in any block comment
251+
if let Some(last_char) = last_char {
252+
if block_comment_depth == 0 {
253+
json_output.push(last_char);
254+
} else {
255+
json_output.push(' ');
256+
}
257+
}
258+
259+
// Remove trailing whitespace from line
260+
while json_output.ends_with(' ') {
261+
json_output.pop();
262+
}
263+
json_output.push('\n');
264+
}
265+
266+
json_output
267+
}

0 commit comments

Comments
 (0)