Skip to content

Commit 525785f

Browse files
Get rescript.json hover info to work
1 parent 304f4ee commit 525785f

File tree

1 file changed

+86
-6
lines changed

1 file changed

+86
-6
lines changed

server/src/jsonConfig.ts

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,14 @@ export function validateConfig(document: TextDocument): Diagnostic[] {
100100

101101
let validate;
102102
try {
103-
validate = ajv.compile(schemaInfo.schema);
103+
// Create a copy of the schema and modify $ref to use Draft 07 instead of Draft 04
104+
const modifiedSchema = JSON.parse(JSON.stringify(schemaInfo.schema));
105+
if (
106+
modifiedSchema.$schema === "http://json-schema.org/draft-04/schema#"
107+
) {
108+
modifiedSchema.$schema = "http://json-schema.org/draft-07/schema#";
109+
}
110+
validate = ajv.compile(modifiedSchema);
104111
} catch (schemaError) {
105112
console.error(`[JSON_CONFIG] Failed to compile schema:`, schemaError);
106113
return [];
@@ -281,6 +288,33 @@ export function getConfigCompletions(document: TextDocument): CompletionItem[] {
281288
);
282289
}
283290

291+
// Helper function to detect if JSON is minified (single line without meaningful whitespace)
292+
function isMinifiedJson(jsonContent: string): boolean {
293+
const lineCount = jsonContent.split("\n").length;
294+
const trimmed = jsonContent.trim();
295+
296+
// Consider it minified if it's just one line, or if it's very compact
297+
return lineCount === 1 || (lineCount <= 3 && trimmed.length < 200);
298+
}
299+
300+
// Helper function to normalize JSON content for position calculations
301+
// Only formats if the JSON appears to be truly minified (single line)
302+
function normalizeJsonContent(jsonContent: string): string {
303+
try {
304+
// Only format if it's clearly minified (single line with no meaningful line breaks)
305+
if (isMinifiedJson(jsonContent)) {
306+
const parsed = JSON.parse(jsonContent);
307+
return JSON.stringify(parsed, null, 2);
308+
}
309+
310+
// Otherwise, use original content to preserve manual formatting
311+
return jsonContent;
312+
} catch {
313+
// If parsing fails, return original content
314+
return jsonContent;
315+
}
316+
}
317+
284318
export function getConfigHover(
285319
document: TextDocument,
286320
position: Position,
@@ -303,16 +337,62 @@ export function getConfigHover(
303337
return null;
304338
}
305339

306-
const line = document.getText(
307-
Range.create(position.line, 0, position.line, 1000),
340+
// Normalize the JSON content for position calculations
341+
const originalContent = document.getText();
342+
const normalizedContent = normalizeJsonContent(originalContent);
343+
344+
// Split into lines for position calculation
345+
const formattedLines = normalizedContent.split("\n");
346+
347+
// Make sure the position is valid
348+
if (position.line >= formattedLines.length) {
349+
return null;
350+
}
351+
352+
const line = formattedLines[position.line];
353+
354+
// Find all quoted strings on the line with their positions
355+
const quotes = [];
356+
const regex = /"([^"]+)"/g;
357+
let match;
358+
while ((match = regex.exec(line)) !== null) {
359+
quotes.push({
360+
text: match[0],
361+
value: match[1],
362+
start: match.index,
363+
end: match.index + match[0].length,
364+
});
365+
}
366+
367+
// Find which quote contains the cursor position
368+
const cursorQuote = quotes.find(
369+
(q) => position.character >= q.start && position.character <= q.end,
308370
);
309-
const match = line.match(/"([^"]+)"/);
310371

311-
if (!match) {
372+
if (!cursorQuote) {
312373
return null;
313374
}
314375

315-
const propertyName = match[1];
376+
// Check if this is a property key (followed by colon) or property value
377+
const isPropertyKey = line.substring(cursorQuote.end).trim().startsWith(":");
378+
379+
let propertyName;
380+
if (isPropertyKey) {
381+
// This is a property key, use it directly
382+
propertyName = cursorQuote.value;
383+
} else {
384+
// This is a property value, try to find the corresponding key
385+
// Look backwards to find the property key
386+
const beforeCursor = line.substring(0, cursorQuote.start);
387+
const keyMatch = beforeCursor.match(/"([^"]+)"\s*:\s*[^:]*$/);
388+
if (keyMatch) {
389+
propertyName = keyMatch[1];
390+
} else {
391+
// If we can't find the key, this might be an array value or nested property
392+
return null;
393+
}
394+
}
395+
316396
const property = schemaInfo.schema.properties[propertyName];
317397

318398
if (property?.description) {

0 commit comments

Comments
 (0)