correctly 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +6 -2
- package/README.md +21 -15
- package/dist/ajv.d.mts +11 -0
- package/dist/ajv.d.mts.map +1 -0
- package/dist/ajv.mjs +221 -0
- package/dist/ajv.mjs.map +1 -0
- package/dist/check-BI7U3ZLc.mjs +88 -0
- package/dist/check-BI7U3ZLc.mjs.map +1 -0
- package/dist/cli.mjs +14 -62
- package/dist/cli.mjs.map +1 -1
- package/dist/config-Bx1-XXeo.d.mts +189 -0
- package/dist/config-Bx1-XXeo.d.mts.map +1 -0
- package/dist/config-Cb6o4YnJ.mjs +348 -0
- package/dist/config-Cb6o4YnJ.mjs.map +1 -0
- package/dist/core.d.mts +27 -125
- package/dist/core.d.mts.map +1 -1
- package/dist/core.mjs +5 -2
- package/dist/diagnostics-BqD1WOy4.mjs +70 -0
- package/dist/diagnostics-BqD1WOy4.mjs.map +1 -0
- package/dist/engine-VST0hoSk.mjs +111 -0
- package/dist/engine-VST0hoSk.mjs.map +1 -0
- package/dist/extensions-ClclWslY.d.mts +11 -0
- package/dist/extensions-ClclWslY.d.mts.map +1 -0
- package/dist/hints-HvSIhuMM.mjs +57 -0
- package/dist/hints-HvSIhuMM.mjs.map +1 -0
- package/dist/lsp.mjs +40 -91
- package/dist/lsp.mjs.map +1 -1
- package/dist/renovate.d.mts +5 -0
- package/dist/renovate.d.mts.map +1 -0
- package/dist/renovate.mjs +11 -0
- package/dist/renovate.mjs.map +1 -0
- package/dist/schemas-UxCtIdo2.mjs +265 -0
- package/dist/schemas-UxCtIdo2.mjs.map +1 -0
- package/dist/session-DCFav56x.mjs +113 -0
- package/dist/session-DCFav56x.mjs.map +1 -0
- package/dist/worker.mjs +80 -0
- package/dist/worker.mjs.map +1 -0
- package/docs/guide.md +166 -34
- package/examples/basic/correctly.config.ts +13 -0
- package/package.json +69 -60
- package/src/cli/check.ts +41 -11
- package/src/cli/main.ts +3 -2
- package/src/cli/readable.ts +24 -5
- package/src/cli/vsix.ts +1 -0
- package/src/core/adapters.ts +54 -0
- package/src/core/config.ts +201 -64
- package/src/core/engine.ts +118 -218
- package/src/core/extensions.ts +144 -0
- package/src/core/index.ts +3 -0
- package/src/core/parse.ts +26 -2
- package/src/core/parsers.ts +22 -0
- package/src/core/schema-walk.ts +43 -0
- package/src/core/schemas.ts +21 -41
- package/src/core/types.ts +33 -6
- package/src/extensions/renovate.ts +4 -0
- package/src/lsp/hints.ts +22 -12
- package/src/lsp/server.ts +9 -2
- package/src/lsp/workspace.ts +49 -54
- package/src/runtime/session.ts +173 -0
- package/src/runtime/worker.ts +99 -0
- package/src/validators/ajv.ts +257 -0
- package/src/vscode/README.md +1 -1
- package/src/vscode/extension.ts +2 -4
- package/src/vscode/package.json +9 -2
- package/dist/engine-BgWBnb1A.mjs +0 -746
- package/dist/engine-BgWBnb1A.mjs.map +0 -1
- package/examples/basic/correctly.config.json +0 -10
- package/src/core/config.schema.json +0 -47
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { parentPort } from "node:worker_threads"
|
|
2
|
+
import { registerHooks } from "node:module"
|
|
3
|
+
import { TextDocument } from "vscode-languageserver-textdocument"
|
|
4
|
+
import { loadProject, readText } from "../core/config.ts"
|
|
5
|
+
import { Engine } from "../core/engine.ts"
|
|
6
|
+
import { failure, type Position } from "../core/types.ts"
|
|
7
|
+
import { Hints } from "../lsp/hints.ts"
|
|
8
|
+
import { checkProject } from "../cli/check.ts"
|
|
9
|
+
|
|
10
|
+
if (!parentPort) throw new Error("Correctly project runtime requires a worker")
|
|
11
|
+
const port = parentPort
|
|
12
|
+
let engine: Engine | undefined
|
|
13
|
+
const hints = new Hints()
|
|
14
|
+
const controller = new AbortController()
|
|
15
|
+
const dependencies = new Set<string>()
|
|
16
|
+
function dependency(uri: string, kind: "module" | "resource") {
|
|
17
|
+
const key = `${kind}:${uri}`
|
|
18
|
+
if (!uri.startsWith("file:") || dependencies.has(key)) return
|
|
19
|
+
dependencies.add(key)
|
|
20
|
+
port.postMessage({ dependency: { uri, kind } })
|
|
21
|
+
}
|
|
22
|
+
// Comline owns loading; hooks only observe dependencies, including failed relative imports.
|
|
23
|
+
registerHooks({
|
|
24
|
+
resolve(specifier, context, next) {
|
|
25
|
+
if (
|
|
26
|
+
context.parentURL &&
|
|
27
|
+
(specifier.startsWith(".") || specifier.startsWith("file:"))
|
|
28
|
+
)
|
|
29
|
+
dependency(new URL(specifier, context.parentURL).href, "module")
|
|
30
|
+
const result = next(specifier, context)
|
|
31
|
+
dependency(result.url, "module")
|
|
32
|
+
return result
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
port.on(
|
|
36
|
+
"message",
|
|
37
|
+
(message: {
|
|
38
|
+
id: number
|
|
39
|
+
method: string
|
|
40
|
+
params: Record<string, unknown>
|
|
41
|
+
}) => {
|
|
42
|
+
void (async () => {
|
|
43
|
+
const p = message.params
|
|
44
|
+
if (message.method === "dispose") {
|
|
45
|
+
controller.abort()
|
|
46
|
+
await engine?.dispose()
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
if (message.method === "init") {
|
|
50
|
+
const buffers = new Map(p.buffers as [string, string][])
|
|
51
|
+
const project = await loadProject(p.configPath as string)
|
|
52
|
+
engine = new Engine(project, {
|
|
53
|
+
signal: controller.signal,
|
|
54
|
+
read: (uri) =>
|
|
55
|
+
buffers.has(uri)
|
|
56
|
+
? Promise.resolve(buffers.get(uri)!)
|
|
57
|
+
: readText(uri),
|
|
58
|
+
...(p.offline === undefined ? {} : { offline: p.offline as boolean }),
|
|
59
|
+
onDependency: (uri) => dependency(uri, "resource"),
|
|
60
|
+
})
|
|
61
|
+
await engine.prepare()
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
if (!engine) throw new Error("Project is not initialized")
|
|
65
|
+
if (message.method === "validate")
|
|
66
|
+
return engine.validate(p.file as string, p.text as string)
|
|
67
|
+
if (message.method === "check") {
|
|
68
|
+
const sources: [string, string][] = []
|
|
69
|
+
const report = await checkProject(engine, {
|
|
70
|
+
cwd: p.cwd as string,
|
|
71
|
+
...(p.files ? { files: p.files as string[] } : {}),
|
|
72
|
+
...(p.sources
|
|
73
|
+
? {
|
|
74
|
+
onRead: (file: string, text: string) => {
|
|
75
|
+
sources.push([file, text])
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
: {}),
|
|
79
|
+
})
|
|
80
|
+
return { report, sources }
|
|
81
|
+
}
|
|
82
|
+
const document = TextDocument.create(
|
|
83
|
+
p.uri as string,
|
|
84
|
+
p.language as string,
|
|
85
|
+
p.version as number,
|
|
86
|
+
p.text as string,
|
|
87
|
+
)
|
|
88
|
+
if (message.method === "complete")
|
|
89
|
+
return hints.complete(engine, document, p.position as Position)
|
|
90
|
+
if (message.method === "hover")
|
|
91
|
+
return hints.hover(engine, document, p.position as Position)
|
|
92
|
+
throw new Error(`Unknown project operation: ${message.method}`)
|
|
93
|
+
})().then(
|
|
94
|
+
(value) => port.postMessage({ id: message.id, value }),
|
|
95
|
+
(error: unknown) =>
|
|
96
|
+
port.postMessage({ id: message.id, error: failure(error) }),
|
|
97
|
+
)
|
|
98
|
+
},
|
|
99
|
+
)
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Ajv,
|
|
3
|
+
type ErrorObject,
|
|
4
|
+
type ValidateFunction,
|
|
5
|
+
type SchemaObject,
|
|
6
|
+
} from "ajv"
|
|
7
|
+
import { Ajv2020 } from "ajv/dist/2020.js"
|
|
8
|
+
import addFormats from "ajv-formats"
|
|
9
|
+
import { schemaUri } from "../core/config.ts"
|
|
10
|
+
import { diagnostic, pointer, type ParsedDocument } from "../core/parse.ts"
|
|
11
|
+
import { DIALECTS, SchemaStore } from "../core/schemas.ts"
|
|
12
|
+
import { validationContexts } from "../core/diagnostics.ts"
|
|
13
|
+
import {
|
|
14
|
+
knownExtensions,
|
|
15
|
+
installExtensions,
|
|
16
|
+
assertFormats,
|
|
17
|
+
type AjvExtension,
|
|
18
|
+
} from "../core/extensions.ts"
|
|
19
|
+
import {
|
|
20
|
+
CorrectlyError,
|
|
21
|
+
isCorrectlyError,
|
|
22
|
+
type Diagnostic,
|
|
23
|
+
} from "../core/types.ts"
|
|
24
|
+
import type { Validator, ValidationContext } from "../core/adapters.ts"
|
|
25
|
+
|
|
26
|
+
const ANNOTATIONS = [
|
|
27
|
+
"markdownDescription",
|
|
28
|
+
"enumDescriptions",
|
|
29
|
+
"markdownEnumDescriptions",
|
|
30
|
+
"defaultSnippets",
|
|
31
|
+
"errorMessage",
|
|
32
|
+
"patternErrorMessage",
|
|
33
|
+
"deprecationMessage",
|
|
34
|
+
"suggestSortText",
|
|
35
|
+
"doNotSuggest",
|
|
36
|
+
"allowComments",
|
|
37
|
+
"allowTrailingCommas",
|
|
38
|
+
"deprecated",
|
|
39
|
+
"$vocabulary",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
function registerRootAnchors(ajv: Ajv, schema: unknown, uri: string) {
|
|
43
|
+
if (typeof schema !== "object" || schema === null) return
|
|
44
|
+
const object = schema as SchemaObject
|
|
45
|
+
for (const anchor of [object.$anchor, object.$dynamicAnchor]) {
|
|
46
|
+
if (typeof anchor === "string")
|
|
47
|
+
ajv.refs[new URL(`#${anchor}`, object.$id ?? uri).href] =
|
|
48
|
+
object.$id ?? uri
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function validationMessage(error: ErrorObject): string {
|
|
53
|
+
if (error.keyword === "anyOf")
|
|
54
|
+
return "must match at least one alternative; none matched"
|
|
55
|
+
if (
|
|
56
|
+
error.keyword === "if" &&
|
|
57
|
+
["then", "else"].includes(error.params.failingKeyword as string)
|
|
58
|
+
)
|
|
59
|
+
return `must satisfy the ${error.params.failingKeyword} branch of the conditional schema`
|
|
60
|
+
if (error.keyword === "uniqueItems") {
|
|
61
|
+
const { i, j } = error.params
|
|
62
|
+
if (Number.isInteger(i) && Number.isInteger(j))
|
|
63
|
+
return `duplicates item at ${error.instancePath}${pointer([Math.min(i, j)])}; array items must be unique`
|
|
64
|
+
}
|
|
65
|
+
if (error.keyword === "enum" && Array.isArray(error.params.allowedValues))
|
|
66
|
+
return `must be one of: ${error.params.allowedValues.map((value: unknown) => JSON.stringify(value)).join(", ")}`
|
|
67
|
+
if (error.keyword === "const" && Object.hasOwn(error.params, "allowedValue"))
|
|
68
|
+
return `must equal ${JSON.stringify(error.params.allowedValue)}`
|
|
69
|
+
if (error.keyword === "oneOf") {
|
|
70
|
+
if (error.params.passingSchemas === null)
|
|
71
|
+
return "must match exactly one alternative; none matched"
|
|
72
|
+
if (Array.isArray(error.params.passingSchemas))
|
|
73
|
+
return `must match exactly one alternative; multiple matched (alternatives ${error.params.passingSchemas.map((index: number) => index + 1).join(", ")})`
|
|
74
|
+
}
|
|
75
|
+
return error.message ?? "Schema violation"
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function validationDiagnostic(
|
|
79
|
+
text: string,
|
|
80
|
+
parsed: ParsedDocument,
|
|
81
|
+
error: ErrorObject,
|
|
82
|
+
): Diagnostic {
|
|
83
|
+
let jsonPointer = error.instancePath
|
|
84
|
+
if (
|
|
85
|
+
error.keyword === "uniqueItems" &&
|
|
86
|
+
Number.isInteger(error.params.i) &&
|
|
87
|
+
Number.isInteger(error.params.j)
|
|
88
|
+
)
|
|
89
|
+
jsonPointer += pointer([Math.max(error.params.i, error.params.j)])
|
|
90
|
+
const property: unknown =
|
|
91
|
+
error.params.additionalProperty ??
|
|
92
|
+
error.params.unevaluatedProperty ??
|
|
93
|
+
error.params.missingProperty ??
|
|
94
|
+
error.params.propertyName ??
|
|
95
|
+
error.propertyName
|
|
96
|
+
if (typeof property === "string") jsonPointer += pointer([property])
|
|
97
|
+
const node = parsed.locate(
|
|
98
|
+
jsonPointer,
|
|
99
|
+
error.keyword === "additionalProperties" ||
|
|
100
|
+
error.keyword === "unevaluatedProperties" ||
|
|
101
|
+
error.keyword === "propertyNames" ||
|
|
102
|
+
typeof error.propertyName === "string",
|
|
103
|
+
)
|
|
104
|
+
const rangeNode =
|
|
105
|
+
error.keyword === "required" && error.propertyName === undefined
|
|
106
|
+
? parsed.locate(error.instancePath)
|
|
107
|
+
: node
|
|
108
|
+
const length =
|
|
109
|
+
error.keyword === "required" && error.propertyName === undefined
|
|
110
|
+
? 1
|
|
111
|
+
: rangeNode?.length
|
|
112
|
+
return diagnostic(
|
|
113
|
+
text,
|
|
114
|
+
`schema/${error.keyword}`,
|
|
115
|
+
`${jsonPointer || "/"}: ${validationMessage(error)}`,
|
|
116
|
+
jsonPointer,
|
|
117
|
+
rangeNode?.offset ?? 0,
|
|
118
|
+
length ?? 1,
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function compile(
|
|
123
|
+
store: SchemaStore,
|
|
124
|
+
uri: string,
|
|
125
|
+
extensions: readonly AjvExtension[],
|
|
126
|
+
): Promise<ValidateFunction> {
|
|
127
|
+
try {
|
|
128
|
+
const resource = await store.load(uri)
|
|
129
|
+
const options = {
|
|
130
|
+
allErrors: true,
|
|
131
|
+
strictSchema: true,
|
|
132
|
+
strictTypes: false,
|
|
133
|
+
strictTuples: false,
|
|
134
|
+
strictRequired: false,
|
|
135
|
+
coerceTypes: false,
|
|
136
|
+
useDefaults: false,
|
|
137
|
+
removeAdditional: false,
|
|
138
|
+
validateSchema: true,
|
|
139
|
+
loadSchema: async (ref: string) => {
|
|
140
|
+
const loaded = await store.load(ref, resource.dialect)
|
|
141
|
+
if (loaded.dialect !== resource.dialect)
|
|
142
|
+
throw new CorrectlyError(
|
|
143
|
+
"unsupported-dialect",
|
|
144
|
+
`Mixed schema dialects: ${uri} references ${ref}`,
|
|
145
|
+
)
|
|
146
|
+
assertFormats(
|
|
147
|
+
ajv,
|
|
148
|
+
loaded.schema,
|
|
149
|
+
loaded.uri,
|
|
150
|
+
knownExtensions,
|
|
151
|
+
loaded.pointer,
|
|
152
|
+
)
|
|
153
|
+
registerRootAnchors(ajv, loaded.schema, loaded.uri)
|
|
154
|
+
return loaded.schema as SchemaObject
|
|
155
|
+
},
|
|
156
|
+
}
|
|
157
|
+
const ajv =
|
|
158
|
+
resource.dialect === "2020-12" ? new Ajv2020(options) : new Ajv(options)
|
|
159
|
+
// CommonJS package exports retain a callable default at runtime.
|
|
160
|
+
const formats = addFormats as unknown as (instance: Ajv) => void
|
|
161
|
+
formats(ajv)
|
|
162
|
+
// ajv-formats also ships OpenAPI numeric names. Their width semantics
|
|
163
|
+
// belong to an explicitly selected extension, not the baseline.
|
|
164
|
+
for (const name of ["int32", "int64", "float", "double"])
|
|
165
|
+
delete ajv.formats[name]
|
|
166
|
+
for (const keyword of ANNOTATIONS)
|
|
167
|
+
if (!ajv.RULES.keywords[keyword]) ajv.addKeyword({ keyword, valid: true })
|
|
168
|
+
// Ajv indexes plain anchors during reference resolution, but does not
|
|
169
|
+
// register the annotation keyword in its strict vocabulary.
|
|
170
|
+
if (resource.dialect === "2020-12")
|
|
171
|
+
ajv.addKeyword({
|
|
172
|
+
keyword: "$anchor",
|
|
173
|
+
schemaType: "string",
|
|
174
|
+
valid: true,
|
|
175
|
+
})
|
|
176
|
+
installExtensions(ajv, extensions)
|
|
177
|
+
assertFormats(
|
|
178
|
+
ajv,
|
|
179
|
+
resource.schema,
|
|
180
|
+
resource.uri,
|
|
181
|
+
knownExtensions,
|
|
182
|
+
resource.pointer,
|
|
183
|
+
)
|
|
184
|
+
ajv.addSchema(resource.schema, resource.uri)
|
|
185
|
+
registerRootAnchors(ajv, resource.schema, resource.uri)
|
|
186
|
+
const validate = await ajv.compileAsync({
|
|
187
|
+
$schema: DIALECTS[resource.dialect],
|
|
188
|
+
$ref: uri,
|
|
189
|
+
})
|
|
190
|
+
return validate as ValidateFunction
|
|
191
|
+
} catch (error) {
|
|
192
|
+
if (isCorrectlyError(error)) throw error
|
|
193
|
+
throw new CorrectlyError(
|
|
194
|
+
"schema",
|
|
195
|
+
`Cannot compile schema ${uri}: ${error instanceof Error ? error.message : String(error)}`,
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const storeKey = Symbol.for("correctly/ajv/schema-store@1")
|
|
201
|
+
function schemaStore(context: ValidationContext): SchemaStore {
|
|
202
|
+
let store = context.services.get(storeKey) as SchemaStore | undefined
|
|
203
|
+
if (!store) {
|
|
204
|
+
store = new SchemaStore(
|
|
205
|
+
{
|
|
206
|
+
root: context.root,
|
|
207
|
+
config: context.remote ? { remote: context.remote } : {},
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
read: context.read,
|
|
211
|
+
...(context.fetch ? { fetch: context.fetch } : {}),
|
|
212
|
+
...(context.signal ? { signal: context.signal } : {}),
|
|
213
|
+
},
|
|
214
|
+
)
|
|
215
|
+
context.services.set(storeKey, store)
|
|
216
|
+
}
|
|
217
|
+
return store
|
|
218
|
+
}
|
|
219
|
+
export type AjvOptions = {
|
|
220
|
+
schema: string
|
|
221
|
+
extensions?: readonly AjvExtension[]
|
|
222
|
+
}
|
|
223
|
+
export function ajv(options: AjvOptions): Validator {
|
|
224
|
+
const extensions = [...(options.extensions ?? [])]
|
|
225
|
+
return {
|
|
226
|
+
id: "ajv",
|
|
227
|
+
accepts: ["json"],
|
|
228
|
+
schema: options.schema,
|
|
229
|
+
extensions,
|
|
230
|
+
register: async (context) => {
|
|
231
|
+
await schemaStore(context).load(schemaUri(options.schema, context.root))
|
|
232
|
+
},
|
|
233
|
+
prepare: async (context) => {
|
|
234
|
+
const store = schemaStore(context)
|
|
235
|
+
const uri = schemaUri(options.schema, context.root)
|
|
236
|
+
const validate = await compile(store, uri, extensions)
|
|
237
|
+
return {
|
|
238
|
+
validate: ({ text, parsed }) =>
|
|
239
|
+
validate(parsed.value)
|
|
240
|
+
? []
|
|
241
|
+
: validationContexts(
|
|
242
|
+
validate.errors ?? [],
|
|
243
|
+
(validate.errors ?? []).map((error) =>
|
|
244
|
+
validationDiagnostic(text, parsed, error),
|
|
245
|
+
),
|
|
246
|
+
),
|
|
247
|
+
editor: {
|
|
248
|
+
kind: "json-schema",
|
|
249
|
+
uri,
|
|
250
|
+
readSchema: async (uri) =>
|
|
251
|
+
JSON.stringify((await store.load(uri)).schema),
|
|
252
|
+
},
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
export type { AjvExtension } from "../core/extensions.ts"
|
package/src/vscode/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Correctly for VS Code
|
|
2
2
|
|
|
3
|
-
Install the VSIX, add `correctly.config.
|
|
3
|
+
Install Correctly and any imported adapters in the project, trust the workspace, install the VSIX, add `correctly.config.ts` to each workspace root, and open JSON or JSONC files. Correctly uses that same external configuration for validation, completion, and hover. It reads unsaved data and schema buffers. Executable configuration and imported modules reload only after saving. The extension is disabled in untrusted workspaces.
|
|
4
4
|
|
|
5
5
|
The client and server are bundled; no npm install or separate schema map is needed. Run **Correctly: Restart Server** to restart the language server. JSON formatting remains the responsibility of your formatter.
|
|
6
6
|
|
package/src/vscode/extension.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { LanguageClient, TransportKind } from "vscode-languageclient/node"
|
|
|
3
3
|
|
|
4
4
|
let client: LanguageClient | undefined
|
|
5
5
|
export async function activate(context: vscode.ExtensionContext) {
|
|
6
|
+
if (!vscode.workspace.isTrusted) return
|
|
6
7
|
const watcher = vscode.workspace.createFileSystemWatcher("**/*")
|
|
7
8
|
context.subscriptions.push(watcher)
|
|
8
9
|
client = new LanguageClient(
|
|
@@ -13,10 +14,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|
|
13
14
|
transport: TransportKind.stdio,
|
|
14
15
|
},
|
|
15
16
|
{
|
|
16
|
-
documentSelector: [
|
|
17
|
-
{ scheme: "file", language: "json" },
|
|
18
|
-
{ scheme: "file", language: "jsonc" },
|
|
19
|
-
],
|
|
17
|
+
documentSelector: [{ scheme: "file" }],
|
|
20
18
|
synchronize: { fileEvents: watcher },
|
|
21
19
|
},
|
|
22
20
|
)
|
package/src/vscode/package.json
CHANGED
|
@@ -32,10 +32,17 @@
|
|
|
32
32
|
},
|
|
33
33
|
"activationEvents": [
|
|
34
34
|
"onLanguage:json",
|
|
35
|
-
"onLanguage:jsonc"
|
|
35
|
+
"onLanguage:jsonc",
|
|
36
|
+
"workspaceContains:**/correctly.config.ts"
|
|
36
37
|
],
|
|
37
38
|
"engines": {
|
|
38
|
-
"vscode": "^1.
|
|
39
|
+
"vscode": "^1.105.0"
|
|
40
|
+
},
|
|
41
|
+
"capabilities": {
|
|
42
|
+
"untrustedWorkspaces": {
|
|
43
|
+
"supported": false,
|
|
44
|
+
"description": "Correctly evaluates the project TypeScript configuration and its imported parser, validator, and extension code."
|
|
45
|
+
}
|
|
39
46
|
},
|
|
40
47
|
"extensionKind": [
|
|
41
48
|
"workspace"
|