@@ -7,7 +7,7 @@ use std::{
7
7
use pglt_analyse:: AnalyserRules ;
8
8
use pglt_configuration:: {
9
9
ConfigurationDiagnostic , ConfigurationPathHint , ConfigurationPayload , PartialConfiguration ,
10
- push_to_analyser_rules,
10
+ VERSION , push_to_analyser_rules,
11
11
} ;
12
12
use pglt_fs:: { AutoSearchResult , ConfigName , FileSystem , OpenOptions } ;
13
13
@@ -97,7 +97,7 @@ fn load_config(
97
97
// we'll load it directly
98
98
if let ConfigurationPathHint :: FromUser ( ref config_file_path) = base_path {
99
99
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) ?) ;
101
101
102
102
let deserialized = serde_json:: from_str :: < PartialConfiguration > ( & content)
103
103
. map_err ( ConfigurationDiagnostic :: new_deserialization_error) ?;
@@ -128,8 +128,9 @@ fn load_config(
128
128
) ? {
129
129
let AutoSearchResult { content, file_path } = auto_search_result;
130
130
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) ?;
133
134
134
135
Ok ( Some ( ConfigurationPayload {
135
136
deserialized,
@@ -150,7 +151,7 @@ fn load_config(
150
151
/// - the program doesn't have the write rights
151
152
pub fn create_config (
152
153
fs : & mut DynRef < dyn FileSystem > ,
153
- configuration : PartialConfiguration ,
154
+ configuration : & mut PartialConfiguration ,
154
155
) -> Result < ( ) , WorkspaceError > {
155
156
let path = PathBuf :: from ( ConfigName :: pglt_json ( ) ) ;
156
157
@@ -168,6 +169,19 @@ pub fn create_config(
168
169
}
169
170
} ) ?;
170
171
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
+
171
185
let contents = serde_json:: to_string_pretty ( & configuration)
172
186
. map_err ( |_| ConfigurationDiagnostic :: new_serialization_error ( ) ) ?;
173
187
@@ -186,3 +200,68 @@ pub fn to_analyser_rules(settings: &Settings) -> AnalyserRules {
186
200
}
187
201
analyser_rules
188
202
}
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