deep-slop 1.4.1 → 1.6.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/dist/{ast-slop-BGdr58wZ.js → ast-slop-B6Y39w1U.js} +1 -1
- package/dist/{dead-flow-DHRkyxZT.js → dead-flow-BgowgQ-_.js} +1 -1
- package/dist/deep-slop-bundled.js +1251 -1006
- package/dist/{import-intelligence-SK4F7XpL.js → import-intelligence-B7R90PWJ.js} +1 -1
- package/dist/index.js +5 -3
- package/dist/mcp.js +191 -113
- package/dist/{tree-sitter-CM-cP0nl.js → tree-sitter-CBpekmYc.js} +99 -26
- package/package.json +1 -1
|
@@ -3899,636 +3899,192 @@ var init_file_cache = __esm({
|
|
|
3899
3899
|
}
|
|
3900
3900
|
});
|
|
3901
3901
|
|
|
3902
|
-
// src/
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3902
|
+
// src/utils/tree-sitter.ts
|
|
3903
|
+
function clearParseCache() {
|
|
3904
|
+
parseCache.clear();
|
|
3905
|
+
}
|
|
3906
|
+
async function initParser() {
|
|
3907
|
+
if (initDone) return initOk;
|
|
3908
|
+
if (initPromise) return initPromise;
|
|
3909
|
+
initPromise = (async () => {
|
|
3910
|
+
try {
|
|
3911
|
+
const wt = await import("web-tree-sitter");
|
|
3912
|
+
const { dirname: dirname9 } = await import("node:path");
|
|
3913
|
+
const wasmDir = dirname9(
|
|
3914
|
+
__require.resolve("web-tree-sitter/tree-sitter.wasm")
|
|
3915
|
+
);
|
|
3916
|
+
await wt.Parser.init({
|
|
3917
|
+
locateFile: (name) => `${wasmDir}/${name}`
|
|
3918
|
+
});
|
|
3919
|
+
const parser = new wt.Parser();
|
|
3920
|
+
parserInstance = parser;
|
|
3921
|
+
const tsWasm = __require.resolve(
|
|
3922
|
+
"tree-sitter-typescript/tree-sitter-typescript.wasm"
|
|
3923
|
+
);
|
|
3924
|
+
tsLang = await wt.Language.load(tsWasm);
|
|
3925
|
+
const tsxWasm = __require.resolve(
|
|
3926
|
+
"tree-sitter-typescript/tree-sitter-tsx.wasm"
|
|
3927
|
+
);
|
|
3928
|
+
tsxLang = await wt.Language.load(tsxWasm);
|
|
3929
|
+
initDone = true;
|
|
3930
|
+
initOk = true;
|
|
3931
|
+
return true;
|
|
3932
|
+
} catch (err) {
|
|
3933
|
+
initDone = true;
|
|
3934
|
+
initOk = false;
|
|
3935
|
+
return false;
|
|
3909
3936
|
}
|
|
3910
|
-
|
|
3911
|
-
|
|
3937
|
+
})();
|
|
3938
|
+
return initPromise;
|
|
3939
|
+
}
|
|
3940
|
+
async function initPythonParser() {
|
|
3941
|
+
if (pyInitDone) return pyInitOk;
|
|
3942
|
+
if (!initOk) {
|
|
3943
|
+
const baseOk = await initParser();
|
|
3944
|
+
if (!baseOk) {
|
|
3945
|
+
pyInitDone = true;
|
|
3946
|
+
pyInitOk = false;
|
|
3947
|
+
return false;
|
|
3912
3948
|
}
|
|
3913
|
-
|
|
3949
|
+
}
|
|
3950
|
+
try {
|
|
3951
|
+
const pyWasm = __require.resolve(
|
|
3952
|
+
"tree-sitter-python/python.wasm"
|
|
3953
|
+
);
|
|
3954
|
+
const wt = await import("web-tree-sitter");
|
|
3955
|
+
pyLang = await wt.Language.load(pyWasm);
|
|
3956
|
+
pyInitDone = true;
|
|
3957
|
+
pyInitOk = true;
|
|
3958
|
+
return true;
|
|
3914
3959
|
} catch {
|
|
3915
|
-
|
|
3960
|
+
pyInitDone = true;
|
|
3961
|
+
pyInitOk = false;
|
|
3962
|
+
return false;
|
|
3916
3963
|
}
|
|
3917
3964
|
}
|
|
3918
|
-
async function
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3965
|
+
async function initGoParser() {
|
|
3966
|
+
if (goInitDone) return goInitOk;
|
|
3967
|
+
if (!initOk) {
|
|
3968
|
+
const baseOk = await initParser();
|
|
3969
|
+
if (!baseOk) {
|
|
3970
|
+
goInitDone = true;
|
|
3971
|
+
goInitOk = false;
|
|
3972
|
+
return false;
|
|
3926
3973
|
}
|
|
3927
3974
|
}
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3975
|
+
try {
|
|
3976
|
+
const goWasm = __require.resolve(
|
|
3977
|
+
"tree-sitter-go/go.wasm"
|
|
3978
|
+
);
|
|
3979
|
+
const wt = await import("web-tree-sitter");
|
|
3980
|
+
goLang = await wt.Language.load(goWasm);
|
|
3981
|
+
goInitDone = true;
|
|
3982
|
+
goInitOk = true;
|
|
3983
|
+
return true;
|
|
3984
|
+
} catch {
|
|
3985
|
+
goInitDone = true;
|
|
3986
|
+
goInitOk = false;
|
|
3987
|
+
return false;
|
|
3933
3988
|
}
|
|
3934
|
-
});
|
|
3935
|
-
|
|
3936
|
-
// src/plugins/registry.ts
|
|
3937
|
-
var registry_exports = {};
|
|
3938
|
-
__export(registry_exports, {
|
|
3939
|
-
PLUGIN_DIR: () => PLUGIN_DIR,
|
|
3940
|
-
discoverAndLoadPlugins: () => discoverAndLoadPlugins,
|
|
3941
|
-
getPluginDir: () => getPluginDir,
|
|
3942
|
-
pluginRegistry: () => pluginRegistry
|
|
3943
|
-
});
|
|
3944
|
-
import { join as join2 } from "node:path";
|
|
3945
|
-
import { readdir } from "node:fs/promises";
|
|
3946
|
-
import { existsSync as existsSync2 } from "node:fs";
|
|
3947
|
-
function getPluginDir(rootDir) {
|
|
3948
|
-
return join2(rootDir, PLUGIN_DIR);
|
|
3949
3989
|
}
|
|
3950
|
-
async function
|
|
3951
|
-
if (
|
|
3952
|
-
|
|
3990
|
+
async function initRustParser() {
|
|
3991
|
+
if (rustInitDone) return rustInitOk;
|
|
3992
|
+
if (!initOk) {
|
|
3993
|
+
const baseOk = await initParser();
|
|
3994
|
+
if (!baseOk) {
|
|
3995
|
+
rustInitDone = true;
|
|
3996
|
+
rustInitOk = false;
|
|
3997
|
+
return false;
|
|
3998
|
+
}
|
|
3953
3999
|
}
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
4000
|
+
try {
|
|
4001
|
+
const rustWasm = __require.resolve(
|
|
4002
|
+
"tree-sitter-rust/rust.wasm"
|
|
4003
|
+
);
|
|
4004
|
+
const wt = await import("web-tree-sitter");
|
|
4005
|
+
rustLang = await wt.Language.load(rustWasm);
|
|
4006
|
+
rustInitDone = true;
|
|
4007
|
+
rustInitOk = true;
|
|
4008
|
+
return true;
|
|
4009
|
+
} catch {
|
|
4010
|
+
rustInitDone = true;
|
|
4011
|
+
rustInitOk = false;
|
|
4012
|
+
return false;
|
|
4013
|
+
}
|
|
4014
|
+
}
|
|
4015
|
+
async function initPhpParser() {
|
|
4016
|
+
if (phpInitDone) return phpInitOk;
|
|
4017
|
+
if (!initOk) {
|
|
4018
|
+
const baseOk = await initParser();
|
|
4019
|
+
if (!baseOk) {
|
|
4020
|
+
phpInitDone = true;
|
|
4021
|
+
phpInitOk = false;
|
|
4022
|
+
return false;
|
|
4023
|
+
}
|
|
3958
4024
|
}
|
|
3959
4025
|
try {
|
|
3960
|
-
const
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
4026
|
+
const phpWasm = __require.resolve(
|
|
4027
|
+
"tree-sitter-php/php.wasm"
|
|
4028
|
+
);
|
|
4029
|
+
const wt = await import("web-tree-sitter");
|
|
4030
|
+
phpLang = await wt.Language.load(phpWasm);
|
|
4031
|
+
phpInitDone = true;
|
|
4032
|
+
phpInitOk = true;
|
|
4033
|
+
return true;
|
|
4034
|
+
} catch {
|
|
4035
|
+
phpInitDone = true;
|
|
4036
|
+
phpInitOk = false;
|
|
4037
|
+
return false;
|
|
4038
|
+
}
|
|
4039
|
+
}
|
|
4040
|
+
async function initCsharpParser() {
|
|
4041
|
+
if (csharpInitDone) return csharpInitOk;
|
|
4042
|
+
if (!initOk) {
|
|
4043
|
+
const baseOk = await initParser();
|
|
4044
|
+
if (!baseOk) {
|
|
4045
|
+
csharpInitDone = true;
|
|
4046
|
+
csharpInitOk = false;
|
|
4047
|
+
return false;
|
|
3971
4048
|
}
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
4049
|
+
}
|
|
4050
|
+
try {
|
|
4051
|
+
const csharpWasm = __require.resolve(
|
|
4052
|
+
"tree-sitter-c-sharp/c_sharp.wasm"
|
|
4053
|
+
);
|
|
4054
|
+
const wt = await import("web-tree-sitter");
|
|
4055
|
+
csharpLang = await wt.Language.load(csharpWasm);
|
|
4056
|
+
csharpInitDone = true;
|
|
4057
|
+
csharpInitOk = true;
|
|
4058
|
+
return true;
|
|
4059
|
+
} catch {
|
|
4060
|
+
csharpInitDone = true;
|
|
4061
|
+
csharpInitOk = false;
|
|
4062
|
+
return false;
|
|
4063
|
+
}
|
|
4064
|
+
}
|
|
4065
|
+
async function initSwiftParser() {
|
|
4066
|
+
if (swiftInitDone) return swiftInitOk;
|
|
4067
|
+
if (!initOk) {
|
|
4068
|
+
const baseOk = await initParser();
|
|
4069
|
+
if (!baseOk) {
|
|
4070
|
+
swiftInitDone = true;
|
|
4071
|
+
swiftInitOk = false;
|
|
4072
|
+
return false;
|
|
3987
4073
|
}
|
|
3988
|
-
|
|
3989
|
-
|
|
4074
|
+
}
|
|
4075
|
+
try {
|
|
4076
|
+
const swiftWasm = __require.resolve(
|
|
4077
|
+
"tree-sitter-swift/swift.wasm"
|
|
4078
|
+
);
|
|
4079
|
+
const wt = await import("web-tree-sitter");
|
|
4080
|
+
swiftLang = await wt.Language.load(swiftWasm);
|
|
4081
|
+
swiftInitDone = true;
|
|
4082
|
+
swiftInitOk = true;
|
|
4083
|
+
return true;
|
|
3990
4084
|
} catch {
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
}
|
|
3995
|
-
var PluginRegistry, pluginRegistry, PLUGIN_DIR;
|
|
3996
|
-
var init_registry = __esm({
|
|
3997
|
-
"src/plugins/registry.ts"() {
|
|
3998
|
-
"use strict";
|
|
3999
|
-
init_loader();
|
|
4000
|
-
PluginRegistry = class {
|
|
4001
|
-
entries = /* @__PURE__ */ new Map();
|
|
4002
|
-
loaded = false;
|
|
4003
|
-
/** Get all registered plugins */
|
|
4004
|
-
getAll() {
|
|
4005
|
-
return [...this.entries.values()];
|
|
4006
|
-
}
|
|
4007
|
-
/** Get all successfully loaded engines */
|
|
4008
|
-
getEngines() {
|
|
4009
|
-
return [...this.entries.values()].filter((e) => e.loaded).map((e) => e.engine);
|
|
4010
|
-
}
|
|
4011
|
-
/** Get a specific plugin by id */
|
|
4012
|
-
get(id) {
|
|
4013
|
-
return this.entries.get(id);
|
|
4014
|
-
}
|
|
4015
|
-
/** Get a loaded engine by name */
|
|
4016
|
-
getEngine(name) {
|
|
4017
|
-
const entry = this.entries.get(name);
|
|
4018
|
-
return entry?.loaded ? entry.engine : void 0;
|
|
4019
|
-
}
|
|
4020
|
-
/** Register a plugin entry */
|
|
4021
|
-
register(entry) {
|
|
4022
|
-
this.entries.set(entry.id, entry);
|
|
4023
|
-
}
|
|
4024
|
-
/** Remove a plugin by id */
|
|
4025
|
-
remove(id) {
|
|
4026
|
-
return this.entries.delete(id);
|
|
4027
|
-
}
|
|
4028
|
-
/** Check if a plugin is registered */
|
|
4029
|
-
has(id) {
|
|
4030
|
-
return this.entries.has(id);
|
|
4031
|
-
}
|
|
4032
|
-
/** Number of registered plugins */
|
|
4033
|
-
get size() {
|
|
4034
|
-
return this.entries.size;
|
|
4035
|
-
}
|
|
4036
|
-
/** Whether the registry has been loaded from disk */
|
|
4037
|
-
get isLoaded() {
|
|
4038
|
-
return this.loaded;
|
|
4039
|
-
}
|
|
4040
|
-
/** Mark the registry as loaded */
|
|
4041
|
-
setLoaded(loaded) {
|
|
4042
|
-
this.loaded = loaded;
|
|
4043
|
-
}
|
|
4044
|
-
/** Clear all entries */
|
|
4045
|
-
clear() {
|
|
4046
|
-
this.entries.clear();
|
|
4047
|
-
this.loaded = false;
|
|
4048
|
-
}
|
|
4049
|
-
};
|
|
4050
|
-
pluginRegistry = new PluginRegistry();
|
|
4051
|
-
PLUGIN_DIR = ".deep-slop/plugins";
|
|
4052
|
-
}
|
|
4053
|
-
});
|
|
4054
|
-
|
|
4055
|
-
// src/utils/suppress.ts
|
|
4056
|
-
import { join as join3 } from "node:path";
|
|
4057
|
-
import { readFileSync as readFileSync2 } from "node:fs";
|
|
4058
|
-
function parseSuppressDirectives(content) {
|
|
4059
|
-
const entries = [];
|
|
4060
|
-
const lines = content.split("\n");
|
|
4061
|
-
for (let i = 0; i < lines.length; i++) {
|
|
4062
|
-
const line = lines[i].trim();
|
|
4063
|
-
const lineNum = i + 1;
|
|
4064
|
-
const ignoreNextMatch = line.match(
|
|
4065
|
-
/\/\/\s*deep-slop-ignore-next(?:\s+(.+))?$/
|
|
4066
|
-
);
|
|
4067
|
-
if (ignoreNextMatch) {
|
|
4068
|
-
entries.push({
|
|
4069
|
-
directiveLine: lineNum,
|
|
4070
|
-
targetLine: lineNum + 1,
|
|
4071
|
-
rules: parseRuleList(ignoreNextMatch[1]),
|
|
4072
|
-
type: "next-line"
|
|
4073
|
-
});
|
|
4074
|
-
continue;
|
|
4075
|
-
}
|
|
4076
|
-
const ignoreLineMatch = line.match(
|
|
4077
|
-
/\/\/\s*deep-slop-ignore-line(?:\s+(.+))?$/
|
|
4078
|
-
);
|
|
4079
|
-
if (ignoreLineMatch) {
|
|
4080
|
-
entries.push({
|
|
4081
|
-
directiveLine: lineNum,
|
|
4082
|
-
targetLine: lineNum,
|
|
4083
|
-
rules: parseRuleList(ignoreLineMatch[1]),
|
|
4084
|
-
type: "line"
|
|
4085
|
-
});
|
|
4086
|
-
continue;
|
|
4087
|
-
}
|
|
4088
|
-
const ignoreRuleMatch = line.match(
|
|
4089
|
-
/\/\/\s*deep-slop-ignore(?:\s+(.+))?$/
|
|
4090
|
-
);
|
|
4091
|
-
if (ignoreRuleMatch) {
|
|
4092
|
-
const rulePart = ignoreRuleMatch[1];
|
|
4093
|
-
if (rulePart !== "start" && rulePart !== "end") {
|
|
4094
|
-
entries.push({
|
|
4095
|
-
directiveLine: lineNum,
|
|
4096
|
-
targetLine: lineNum + 1,
|
|
4097
|
-
rules: parseRuleList(rulePart),
|
|
4098
|
-
type: "next-line"
|
|
4099
|
-
});
|
|
4100
|
-
continue;
|
|
4101
|
-
}
|
|
4102
|
-
}
|
|
4103
|
-
const ignoreStartMatch = line.match(
|
|
4104
|
-
/\/\/\s*deep-slop-ignore-start(?:\s+(.+))?$/
|
|
4105
|
-
);
|
|
4106
|
-
if (ignoreStartMatch) {
|
|
4107
|
-
entries.push({
|
|
4108
|
-
directiveLine: lineNum,
|
|
4109
|
-
targetLine: lineNum,
|
|
4110
|
-
rules: parseRuleList(ignoreStartMatch[1]),
|
|
4111
|
-
type: "block-start"
|
|
4112
|
-
});
|
|
4113
|
-
continue;
|
|
4114
|
-
}
|
|
4115
|
-
const ignoreEndMatch = line.match(
|
|
4116
|
-
/\/\/\s*deep-slop-ignore-end/
|
|
4117
|
-
);
|
|
4118
|
-
if (ignoreEndMatch) {
|
|
4119
|
-
entries.push({
|
|
4120
|
-
directiveLine: lineNum,
|
|
4121
|
-
targetLine: lineNum,
|
|
4122
|
-
rules: /* @__PURE__ */ new Set(),
|
|
4123
|
-
type: "block-end"
|
|
4124
|
-
});
|
|
4125
|
-
continue;
|
|
4126
|
-
}
|
|
4127
|
-
const nextLineMatch = line.match(
|
|
4128
|
-
/\/\/\s*deep-slop-disable-next-line(?:\s+(.+))?$/
|
|
4129
|
-
);
|
|
4130
|
-
if (nextLineMatch) {
|
|
4131
|
-
entries.push({
|
|
4132
|
-
directiveLine: lineNum,
|
|
4133
|
-
targetLine: lineNum + 1,
|
|
4134
|
-
rules: parseRuleList(nextLineMatch[1]),
|
|
4135
|
-
type: "next-line"
|
|
4136
|
-
});
|
|
4137
|
-
continue;
|
|
4138
|
-
}
|
|
4139
|
-
const lineMatch = line.match(
|
|
4140
|
-
/\/\/\s*deep-slop-disable-line(?:\s+(.+))?$/
|
|
4141
|
-
);
|
|
4142
|
-
if (lineMatch) {
|
|
4143
|
-
entries.push({
|
|
4144
|
-
directiveLine: lineNum,
|
|
4145
|
-
targetLine: lineNum,
|
|
4146
|
-
rules: parseRuleList(lineMatch[1]),
|
|
4147
|
-
type: "line"
|
|
4148
|
-
});
|
|
4149
|
-
continue;
|
|
4150
|
-
}
|
|
4151
|
-
const blockStart = line.match(
|
|
4152
|
-
/\/\*\s*deep-slop-disable(?:\s+(.+))?\s*\//
|
|
4153
|
-
);
|
|
4154
|
-
if (blockStart) {
|
|
4155
|
-
entries.push({
|
|
4156
|
-
directiveLine: lineNum,
|
|
4157
|
-
targetLine: lineNum,
|
|
4158
|
-
rules: parseRuleList(blockStart[1]),
|
|
4159
|
-
type: "block-start"
|
|
4160
|
-
});
|
|
4161
|
-
continue;
|
|
4162
|
-
}
|
|
4163
|
-
const blockEnd = line.match(/\/\*\s*deep-slop-enable\s*\//);
|
|
4164
|
-
if (blockEnd) {
|
|
4165
|
-
entries.push({
|
|
4166
|
-
directiveLine: lineNum,
|
|
4167
|
-
targetLine: lineNum,
|
|
4168
|
-
rules: /* @__PURE__ */ new Set(),
|
|
4169
|
-
type: "block-end"
|
|
4170
|
-
});
|
|
4171
|
-
}
|
|
4172
|
-
}
|
|
4173
|
-
return entries;
|
|
4174
|
-
}
|
|
4175
|
-
function parseRuleList(rulesStr) {
|
|
4176
|
-
if (!rulesStr) return /* @__PURE__ */ new Set();
|
|
4177
|
-
const rules = rulesStr.split(/[,\\s]+/).map((r) => r.trim()).filter(Boolean);
|
|
4178
|
-
return new Set(rules);
|
|
4179
|
-
}
|
|
4180
|
-
function buildSuppressChecker(entries) {
|
|
4181
|
-
const blockRanges = [];
|
|
4182
|
-
let currentStart = null;
|
|
4183
|
-
for (const entry of entries) {
|
|
4184
|
-
if (entry.type === "block-start") {
|
|
4185
|
-
currentStart = { line: entry.directiveLine, rules: entry.rules };
|
|
4186
|
-
} else if (entry.type === "block-end" && currentStart) {
|
|
4187
|
-
blockRanges.push({
|
|
4188
|
-
startLine: currentStart.line,
|
|
4189
|
-
endLine: entry.directiveLine,
|
|
4190
|
-
rules: currentStart.rules
|
|
4191
|
-
});
|
|
4192
|
-
currentStart = null;
|
|
4193
|
-
}
|
|
4194
|
-
}
|
|
4195
|
-
if (currentStart) {
|
|
4196
|
-
blockRanges.push({
|
|
4197
|
-
startLine: currentStart.line,
|
|
4198
|
-
endLine: 999999,
|
|
4199
|
-
rules: currentStart.rules
|
|
4200
|
-
});
|
|
4201
|
-
}
|
|
4202
|
-
return (line, rule) => {
|
|
4203
|
-
for (const entry of entries) {
|
|
4204
|
-
if (entry.type === "next-line" || entry.type === "line") {
|
|
4205
|
-
if (entry.targetLine === line) {
|
|
4206
|
-
if (entry.rules.size === 0 || entry.rules.has(rule)) {
|
|
4207
|
-
return true;
|
|
4208
|
-
}
|
|
4209
|
-
}
|
|
4210
|
-
}
|
|
4211
|
-
}
|
|
4212
|
-
for (const range2 of blockRanges) {
|
|
4213
|
-
if (line >= range2.startLine && line <= range2.endLine) {
|
|
4214
|
-
if (range2.rules.size === 0 || range2.rules.has(rule)) {
|
|
4215
|
-
return true;
|
|
4216
|
-
}
|
|
4217
|
-
}
|
|
4218
|
-
}
|
|
4219
|
-
return false;
|
|
4220
|
-
};
|
|
4221
|
-
}
|
|
4222
|
-
function buildSuppressMap(content) {
|
|
4223
|
-
const entries = parseSuppressDirectives(content);
|
|
4224
|
-
const isSuppressed = buildSuppressChecker(entries);
|
|
4225
|
-
return { entries, isSuppressed };
|
|
4226
|
-
}
|
|
4227
|
-
function loadIgnoreFile(rootDir) {
|
|
4228
|
-
const ignorePath = join3(rootDir, ".deep-slop", ".deep-slop-ignore");
|
|
4229
|
-
try {
|
|
4230
|
-
const content = readFileSync2(ignorePath, "utf-8");
|
|
4231
|
-
return content.split("\n").map((line) => line.split("#")[0].trim()).filter((line) => line && !line.startsWith("file:"));
|
|
4232
|
-
} catch {
|
|
4233
|
-
return [];
|
|
4234
|
-
}
|
|
4235
|
-
}
|
|
4236
|
-
function applySuppressDirectives(diagnostics, fileContents, globallySuppressed = /* @__PURE__ */ new Set()) {
|
|
4237
|
-
const suppressMaps = /* @__PURE__ */ new Map();
|
|
4238
|
-
for (const [filePath, content] of fileContents) {
|
|
4239
|
-
suppressMaps.set(filePath, buildSuppressMap(content));
|
|
4240
|
-
}
|
|
4241
|
-
const filtered = [];
|
|
4242
|
-
let suppressedCount = 0;
|
|
4243
|
-
for (const diag8 of diagnostics) {
|
|
4244
|
-
if (globallySuppressed.has(diag8.rule)) {
|
|
4245
|
-
suppressedCount++;
|
|
4246
|
-
continue;
|
|
4247
|
-
}
|
|
4248
|
-
const map = suppressMaps.get(diag8.filePath);
|
|
4249
|
-
if (map && map.isSuppressed(diag8.line, diag8.rule)) {
|
|
4250
|
-
suppressedCount++;
|
|
4251
|
-
} else {
|
|
4252
|
-
filtered.push(diag8);
|
|
4253
|
-
}
|
|
4254
|
-
}
|
|
4255
|
-
return { filtered, suppressedCount };
|
|
4256
|
-
}
|
|
4257
|
-
var init_suppress = __esm({
|
|
4258
|
-
"src/utils/suppress.ts"() {
|
|
4259
|
-
"use strict";
|
|
4260
|
-
}
|
|
4261
|
-
});
|
|
4262
|
-
|
|
4263
|
-
// src/utils/file-utils.ts
|
|
4264
|
-
import { readFile as readFile2 } from "node:fs/promises";
|
|
4265
|
-
async function readFileContent(filePath) {
|
|
4266
|
-
const buffer = await readFile2(filePath);
|
|
4267
|
-
let content = buffer.toString("utf-8");
|
|
4268
|
-
if (content.charCodeAt(0) === 65279) {
|
|
4269
|
-
content = content.slice(1);
|
|
4270
|
-
}
|
|
4271
|
-
return content;
|
|
4272
|
-
}
|
|
4273
|
-
function detectEncodingAnomalies(content) {
|
|
4274
|
-
const hasBom = content.charCodeAt(0) === 65279;
|
|
4275
|
-
const hasCrlf = content.includes("\r\n");
|
|
4276
|
-
const hasZwnbsp = content.includes("\uFEFF");
|
|
4277
|
-
const lfOnly = (content.match(/(?<!\r)\n/g) ?? []).length;
|
|
4278
|
-
const crlfCount = (content.match(/\r\n/g) ?? []).length;
|
|
4279
|
-
const lineEnding = crlfCount > 0 && lfOnly > crlfCount ? "mixed" : crlfCount > 0 ? "crlf" : "lf";
|
|
4280
|
-
return { hasBom, hasCrlf, hasZwnbsp, lineEnding };
|
|
4281
|
-
}
|
|
4282
|
-
function toLines(content) {
|
|
4283
|
-
return content.split("\n").map((text, i) => ({ num: i + 1, text }));
|
|
4284
|
-
}
|
|
4285
|
-
function extractImports(content, language) {
|
|
4286
|
-
const imports = [];
|
|
4287
|
-
const lines = toLines(content);
|
|
4288
|
-
for (const { num, text } of lines) {
|
|
4289
|
-
const trimmed = text.trim();
|
|
4290
|
-
if (language === "typescript" || language === "javascript") {
|
|
4291
|
-
const jsMatch = trimmed.match(
|
|
4292
|
-
/^import\s+(?:type\s+)?(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s+from\s+['"]([^'"]+)['"]/
|
|
4293
|
-
);
|
|
4294
|
-
if (jsMatch) {
|
|
4295
|
-
imports.push({
|
|
4296
|
-
line: num,
|
|
4297
|
-
source: jsMatch[1],
|
|
4298
|
-
raw: trimmed,
|
|
4299
|
-
isTypeOnly: trimmed.includes("import type"),
|
|
4300
|
-
isDefault: !trimmed.includes("{")
|
|
4301
|
-
});
|
|
4302
|
-
}
|
|
4303
|
-
const dynMatch = trimmed.match(/import\s*\(\s*['"]([^'"]+)['"]\s*\)/);
|
|
4304
|
-
if (dynMatch) {
|
|
4305
|
-
imports.push({
|
|
4306
|
-
line: num,
|
|
4307
|
-
source: dynMatch[1],
|
|
4308
|
-
raw: trimmed,
|
|
4309
|
-
isTypeOnly: false,
|
|
4310
|
-
isDynamic: true
|
|
4311
|
-
});
|
|
4312
|
-
}
|
|
4313
|
-
const reqMatch = trimmed.match(/(?:const|let|var)\s+[^=]*=\s*require\s*\(\s*['"]([^'"]+)['"]\s*\)/);
|
|
4314
|
-
if (reqMatch) {
|
|
4315
|
-
imports.push({
|
|
4316
|
-
line: num,
|
|
4317
|
-
source: reqMatch[1],
|
|
4318
|
-
raw: trimmed,
|
|
4319
|
-
isTypeOnly: false,
|
|
4320
|
-
isRequire: true
|
|
4321
|
-
});
|
|
4322
|
-
}
|
|
4323
|
-
}
|
|
4324
|
-
if (language === "python") {
|
|
4325
|
-
const pyMatch = trimmed.match(/^from\s+([^\s]+)\s+import/);
|
|
4326
|
-
if (pyMatch) {
|
|
4327
|
-
imports.push({ line: num, source: pyMatch[1], raw: trimmed, isTypeOnly: false });
|
|
4328
|
-
}
|
|
4329
|
-
const pyImport = trimmed.match(/^import\s+([^\s]+)/);
|
|
4330
|
-
if (pyImport) {
|
|
4331
|
-
imports.push({ line: num, source: pyImport[1], raw: trimmed, isTypeOnly: false });
|
|
4332
|
-
}
|
|
4333
|
-
}
|
|
4334
|
-
if (language === "go") {
|
|
4335
|
-
const goMatch = trimmed.match(/"([^"]+)"/);
|
|
4336
|
-
if (trimmed.startsWith("import") && goMatch) {
|
|
4337
|
-
imports.push({ line: num, source: goMatch[1], raw: trimmed, isTypeOnly: false });
|
|
4338
|
-
}
|
|
4339
|
-
}
|
|
4340
|
-
}
|
|
4341
|
-
return imports;
|
|
4342
|
-
}
|
|
4343
|
-
var init_file_utils = __esm({
|
|
4344
|
-
"src/utils/file-utils.ts"() {
|
|
4345
|
-
"use strict";
|
|
4346
|
-
}
|
|
4347
|
-
});
|
|
4348
|
-
|
|
4349
|
-
// src/utils/tree-sitter.ts
|
|
4350
|
-
async function initParser() {
|
|
4351
|
-
if (initDone) return initOk;
|
|
4352
|
-
if (initPromise) return initPromise;
|
|
4353
|
-
initPromise = (async () => {
|
|
4354
|
-
try {
|
|
4355
|
-
const wt = await import("web-tree-sitter");
|
|
4356
|
-
const { dirname: dirname9 } = await import("node:path");
|
|
4357
|
-
const wasmDir = dirname9(
|
|
4358
|
-
__require.resolve("web-tree-sitter/tree-sitter.wasm")
|
|
4359
|
-
);
|
|
4360
|
-
await wt.Parser.init({
|
|
4361
|
-
locateFile: (name) => `${wasmDir}/${name}`
|
|
4362
|
-
});
|
|
4363
|
-
const parser = new wt.Parser();
|
|
4364
|
-
parserInstance = parser;
|
|
4365
|
-
const tsWasm = __require.resolve(
|
|
4366
|
-
"tree-sitter-typescript/tree-sitter-typescript.wasm"
|
|
4367
|
-
);
|
|
4368
|
-
tsLang = await wt.Language.load(tsWasm);
|
|
4369
|
-
const tsxWasm = __require.resolve(
|
|
4370
|
-
"tree-sitter-typescript/tree-sitter-tsx.wasm"
|
|
4371
|
-
);
|
|
4372
|
-
tsxLang = await wt.Language.load(tsxWasm);
|
|
4373
|
-
initDone = true;
|
|
4374
|
-
initOk = true;
|
|
4375
|
-
return true;
|
|
4376
|
-
} catch (err) {
|
|
4377
|
-
initDone = true;
|
|
4378
|
-
initOk = false;
|
|
4379
|
-
return false;
|
|
4380
|
-
}
|
|
4381
|
-
})();
|
|
4382
|
-
return initPromise;
|
|
4383
|
-
}
|
|
4384
|
-
async function initPythonParser() {
|
|
4385
|
-
if (pyInitDone) return pyInitOk;
|
|
4386
|
-
if (!initOk) {
|
|
4387
|
-
const baseOk = await initParser();
|
|
4388
|
-
if (!baseOk) {
|
|
4389
|
-
pyInitDone = true;
|
|
4390
|
-
pyInitOk = false;
|
|
4391
|
-
return false;
|
|
4392
|
-
}
|
|
4393
|
-
}
|
|
4394
|
-
try {
|
|
4395
|
-
const pyWasm = __require.resolve(
|
|
4396
|
-
"tree-sitter-python/python.wasm"
|
|
4397
|
-
);
|
|
4398
|
-
const wt = await import("web-tree-sitter");
|
|
4399
|
-
pyLang = await wt.Language.load(pyWasm);
|
|
4400
|
-
pyInitDone = true;
|
|
4401
|
-
pyInitOk = true;
|
|
4402
|
-
return true;
|
|
4403
|
-
} catch {
|
|
4404
|
-
pyInitDone = true;
|
|
4405
|
-
pyInitOk = false;
|
|
4406
|
-
return false;
|
|
4407
|
-
}
|
|
4408
|
-
}
|
|
4409
|
-
async function initGoParser() {
|
|
4410
|
-
if (goInitDone) return goInitOk;
|
|
4411
|
-
if (!initOk) {
|
|
4412
|
-
const baseOk = await initParser();
|
|
4413
|
-
if (!baseOk) {
|
|
4414
|
-
goInitDone = true;
|
|
4415
|
-
goInitOk = false;
|
|
4416
|
-
return false;
|
|
4417
|
-
}
|
|
4418
|
-
}
|
|
4419
|
-
try {
|
|
4420
|
-
const goWasm = __require.resolve(
|
|
4421
|
-
"tree-sitter-go/go.wasm"
|
|
4422
|
-
);
|
|
4423
|
-
const wt = await import("web-tree-sitter");
|
|
4424
|
-
goLang = await wt.Language.load(goWasm);
|
|
4425
|
-
goInitDone = true;
|
|
4426
|
-
goInitOk = true;
|
|
4427
|
-
return true;
|
|
4428
|
-
} catch {
|
|
4429
|
-
goInitDone = true;
|
|
4430
|
-
goInitOk = false;
|
|
4431
|
-
return false;
|
|
4432
|
-
}
|
|
4433
|
-
}
|
|
4434
|
-
async function initRustParser() {
|
|
4435
|
-
if (rustInitDone) return rustInitOk;
|
|
4436
|
-
if (!initOk) {
|
|
4437
|
-
const baseOk = await initParser();
|
|
4438
|
-
if (!baseOk) {
|
|
4439
|
-
rustInitDone = true;
|
|
4440
|
-
rustInitOk = false;
|
|
4441
|
-
return false;
|
|
4442
|
-
}
|
|
4443
|
-
}
|
|
4444
|
-
try {
|
|
4445
|
-
const rustWasm = __require.resolve(
|
|
4446
|
-
"tree-sitter-rust/rust.wasm"
|
|
4447
|
-
);
|
|
4448
|
-
const wt = await import("web-tree-sitter");
|
|
4449
|
-
rustLang = await wt.Language.load(rustWasm);
|
|
4450
|
-
rustInitDone = true;
|
|
4451
|
-
rustInitOk = true;
|
|
4452
|
-
return true;
|
|
4453
|
-
} catch {
|
|
4454
|
-
rustInitDone = true;
|
|
4455
|
-
rustInitOk = false;
|
|
4456
|
-
return false;
|
|
4457
|
-
}
|
|
4458
|
-
}
|
|
4459
|
-
async function initPhpParser() {
|
|
4460
|
-
if (phpInitDone) return phpInitOk;
|
|
4461
|
-
if (!initOk) {
|
|
4462
|
-
const baseOk = await initParser();
|
|
4463
|
-
if (!baseOk) {
|
|
4464
|
-
phpInitDone = true;
|
|
4465
|
-
phpInitOk = false;
|
|
4466
|
-
return false;
|
|
4467
|
-
}
|
|
4468
|
-
}
|
|
4469
|
-
try {
|
|
4470
|
-
const phpWasm = __require.resolve(
|
|
4471
|
-
"tree-sitter-php/php.wasm"
|
|
4472
|
-
);
|
|
4473
|
-
const wt = await import("web-tree-sitter");
|
|
4474
|
-
phpLang = await wt.Language.load(phpWasm);
|
|
4475
|
-
phpInitDone = true;
|
|
4476
|
-
phpInitOk = true;
|
|
4477
|
-
return true;
|
|
4478
|
-
} catch {
|
|
4479
|
-
phpInitDone = true;
|
|
4480
|
-
phpInitOk = false;
|
|
4481
|
-
return false;
|
|
4482
|
-
}
|
|
4483
|
-
}
|
|
4484
|
-
async function initCsharpParser() {
|
|
4485
|
-
if (csharpInitDone) return csharpInitOk;
|
|
4486
|
-
if (!initOk) {
|
|
4487
|
-
const baseOk = await initParser();
|
|
4488
|
-
if (!baseOk) {
|
|
4489
|
-
csharpInitDone = true;
|
|
4490
|
-
csharpInitOk = false;
|
|
4491
|
-
return false;
|
|
4492
|
-
}
|
|
4493
|
-
}
|
|
4494
|
-
try {
|
|
4495
|
-
const csharpWasm = __require.resolve(
|
|
4496
|
-
"tree-sitter-c-sharp/c_sharp.wasm"
|
|
4497
|
-
);
|
|
4498
|
-
const wt = await import("web-tree-sitter");
|
|
4499
|
-
csharpLang = await wt.Language.load(csharpWasm);
|
|
4500
|
-
csharpInitDone = true;
|
|
4501
|
-
csharpInitOk = true;
|
|
4502
|
-
return true;
|
|
4503
|
-
} catch {
|
|
4504
|
-
csharpInitDone = true;
|
|
4505
|
-
csharpInitOk = false;
|
|
4506
|
-
return false;
|
|
4507
|
-
}
|
|
4508
|
-
}
|
|
4509
|
-
async function initSwiftParser() {
|
|
4510
|
-
if (swiftInitDone) return swiftInitOk;
|
|
4511
|
-
if (!initOk) {
|
|
4512
|
-
const baseOk = await initParser();
|
|
4513
|
-
if (!baseOk) {
|
|
4514
|
-
swiftInitDone = true;
|
|
4515
|
-
swiftInitOk = false;
|
|
4516
|
-
return false;
|
|
4517
|
-
}
|
|
4518
|
-
}
|
|
4519
|
-
try {
|
|
4520
|
-
const swiftWasm = __require.resolve(
|
|
4521
|
-
"tree-sitter-swift/swift.wasm"
|
|
4522
|
-
);
|
|
4523
|
-
const wt = await import("web-tree-sitter");
|
|
4524
|
-
swiftLang = await wt.Language.load(swiftWasm);
|
|
4525
|
-
swiftInitDone = true;
|
|
4526
|
-
swiftInitOk = true;
|
|
4527
|
-
return true;
|
|
4528
|
-
} catch {
|
|
4529
|
-
swiftInitDone = true;
|
|
4530
|
-
swiftInitOk = false;
|
|
4531
|
-
return false;
|
|
4085
|
+
swiftInitDone = true;
|
|
4086
|
+
swiftInitOk = false;
|
|
4087
|
+
return false;
|
|
4532
4088
|
}
|
|
4533
4089
|
}
|
|
4534
4090
|
function isAvailable() {
|
|
@@ -4538,14 +4094,19 @@ function isPythonAvailable() {
|
|
|
4538
4094
|
return pyInitOk && pyLang !== null;
|
|
4539
4095
|
}
|
|
4540
4096
|
async function parseFile(content, isTsx = false, filePath) {
|
|
4097
|
+
if (filePath) {
|
|
4098
|
+
const cacheKey = `${filePath}:${isTsx ? "tsx" : "ts"}`;
|
|
4099
|
+
const cached = parseCache.get(cacheKey);
|
|
4100
|
+
if (cached !== void 0) return cached;
|
|
4101
|
+
}
|
|
4541
4102
|
if (filePath) {
|
|
4542
4103
|
const ext2 = filePath.toLowerCase();
|
|
4543
|
-
if (ext2.endsWith(".go")) return parseGoFile(content);
|
|
4544
|
-
if (ext2.endsWith(".rs")) return parseRustFile(content);
|
|
4545
|
-
if (ext2.endsWith(".php")) return parsePhpFile(content);
|
|
4546
|
-
if (ext2.endsWith(".cs")) return parseCsharpFile(content);
|
|
4547
|
-
if (ext2.endsWith(".swift")) return parseSwiftFile(content);
|
|
4548
|
-
if (ext2.endsWith(".py")) return parsePython(content);
|
|
4104
|
+
if (ext2.endsWith(".go")) return parseGoFile(content, filePath);
|
|
4105
|
+
if (ext2.endsWith(".rs")) return parseRustFile(content, filePath);
|
|
4106
|
+
if (ext2.endsWith(".php")) return parsePhpFile(content, filePath);
|
|
4107
|
+
if (ext2.endsWith(".cs")) return parseCsharpFile(content, filePath);
|
|
4108
|
+
if (ext2.endsWith(".swift")) return parseSwiftFile(content, filePath);
|
|
4109
|
+
if (ext2.endsWith(".py")) return parsePython(content, filePath);
|
|
4549
4110
|
}
|
|
4550
4111
|
if (!parserInstance || !tsLang && !tsxLang) {
|
|
4551
4112
|
const ok = await initParser();
|
|
@@ -4556,12 +4117,21 @@ async function parseFile(content, isTsx = false, filePath) {
|
|
|
4556
4117
|
parserInstance.setLanguage(lang);
|
|
4557
4118
|
const tree = parserInstance.parse(content);
|
|
4558
4119
|
if (!tree) return null;
|
|
4559
|
-
|
|
4120
|
+
const result = convertNode(tree.rootNode, null);
|
|
4121
|
+
if (filePath) {
|
|
4122
|
+
parseCache.set(`${filePath}:${isTsx ? "tsx" : "ts"}`, result);
|
|
4123
|
+
}
|
|
4124
|
+
return result;
|
|
4560
4125
|
} catch {
|
|
4126
|
+
if (filePath) parseCache.set(`${filePath}:${isTsx ? "tsx" : "ts"}`, null);
|
|
4561
4127
|
return null;
|
|
4562
4128
|
}
|
|
4563
4129
|
}
|
|
4564
|
-
async function parsePython(content) {
|
|
4130
|
+
async function parsePython(content, filePath) {
|
|
4131
|
+
if (filePath) {
|
|
4132
|
+
const cached = parseCache.get(`py:${filePath}`);
|
|
4133
|
+
if (cached !== void 0) return cached;
|
|
4134
|
+
}
|
|
4565
4135
|
if (!pyLang) {
|
|
4566
4136
|
const ok = await initPythonParser();
|
|
4567
4137
|
if (!ok) return null;
|
|
@@ -4573,13 +4143,23 @@ async function parsePython(content) {
|
|
|
4573
4143
|
try {
|
|
4574
4144
|
parserInstance.setLanguage(pyLang);
|
|
4575
4145
|
const tree = parserInstance.parse(content);
|
|
4576
|
-
if (!tree)
|
|
4577
|
-
|
|
4146
|
+
if (!tree) {
|
|
4147
|
+
if (filePath) parseCache.set(`py:${filePath}`, null);
|
|
4148
|
+
return null;
|
|
4149
|
+
}
|
|
4150
|
+
const result = convertNode(tree.rootNode, null);
|
|
4151
|
+
if (filePath) parseCache.set(`py:${filePath}`, result);
|
|
4152
|
+
return result;
|
|
4578
4153
|
} catch {
|
|
4154
|
+
if (filePath) parseCache.set(`py:${filePath}`, null);
|
|
4579
4155
|
return null;
|
|
4580
4156
|
}
|
|
4581
4157
|
}
|
|
4582
|
-
async function parseGoFile(content) {
|
|
4158
|
+
async function parseGoFile(content, filePath) {
|
|
4159
|
+
if (filePath) {
|
|
4160
|
+
const cached = parseCache.get(`go:${filePath}`);
|
|
4161
|
+
if (cached !== void 0) return cached;
|
|
4162
|
+
}
|
|
4583
4163
|
if (!goLang) {
|
|
4584
4164
|
const ok = await initGoParser();
|
|
4585
4165
|
if (!ok) return null;
|
|
@@ -4591,13 +4171,23 @@ async function parseGoFile(content) {
|
|
|
4591
4171
|
try {
|
|
4592
4172
|
parserInstance.setLanguage(goLang);
|
|
4593
4173
|
const tree = parserInstance.parse(content);
|
|
4594
|
-
if (!tree)
|
|
4595
|
-
|
|
4174
|
+
if (!tree) {
|
|
4175
|
+
if (filePath) parseCache.set(`go:${filePath}`, null);
|
|
4176
|
+
return null;
|
|
4177
|
+
}
|
|
4178
|
+
const result = convertNode(tree.rootNode, null);
|
|
4179
|
+
if (filePath) parseCache.set(`go:${filePath}`, result);
|
|
4180
|
+
return result;
|
|
4596
4181
|
} catch {
|
|
4182
|
+
if (filePath) parseCache.set(`go:${filePath}`, null);
|
|
4597
4183
|
return null;
|
|
4598
4184
|
}
|
|
4599
4185
|
}
|
|
4600
|
-
async function parseRustFile(content) {
|
|
4186
|
+
async function parseRustFile(content, filePath) {
|
|
4187
|
+
if (filePath) {
|
|
4188
|
+
const cached = parseCache.get(`rs:${filePath}`);
|
|
4189
|
+
if (cached !== void 0) return cached;
|
|
4190
|
+
}
|
|
4601
4191
|
if (!rustLang) {
|
|
4602
4192
|
const ok = await initRustParser();
|
|
4603
4193
|
if (!ok) return null;
|
|
@@ -4609,444 +4199,928 @@ async function parseRustFile(content) {
|
|
|
4609
4199
|
try {
|
|
4610
4200
|
parserInstance.setLanguage(rustLang);
|
|
4611
4201
|
const tree = parserInstance.parse(content);
|
|
4612
|
-
if (!tree)
|
|
4613
|
-
|
|
4202
|
+
if (!tree) {
|
|
4203
|
+
if (filePath) parseCache.set(`rs:${filePath}`, null);
|
|
4204
|
+
return null;
|
|
4205
|
+
}
|
|
4206
|
+
const result = convertNode(tree.rootNode, null);
|
|
4207
|
+
if (filePath) parseCache.set(`rs:${filePath}`, result);
|
|
4208
|
+
return result;
|
|
4614
4209
|
} catch {
|
|
4210
|
+
if (filePath) parseCache.set(`rs:${filePath}`, null);
|
|
4615
4211
|
return null;
|
|
4616
4212
|
}
|
|
4617
4213
|
}
|
|
4618
|
-
async function parsePhpFile(content) {
|
|
4214
|
+
async function parsePhpFile(content, filePath) {
|
|
4215
|
+
if (filePath) {
|
|
4216
|
+
const cached = parseCache.get(`php:${filePath}`);
|
|
4217
|
+
if (cached !== void 0) return cached;
|
|
4218
|
+
}
|
|
4619
4219
|
if (!phpLang) {
|
|
4620
4220
|
const ok = await initPhpParser();
|
|
4621
4221
|
if (!ok) return null;
|
|
4622
4222
|
}
|
|
4623
|
-
if (!parserInstance) {
|
|
4624
|
-
const ok = await initParser();
|
|
4625
|
-
if (!ok) return null;
|
|
4223
|
+
if (!parserInstance) {
|
|
4224
|
+
const ok = await initParser();
|
|
4225
|
+
if (!ok) return null;
|
|
4226
|
+
}
|
|
4227
|
+
try {
|
|
4228
|
+
parserInstance.setLanguage(phpLang);
|
|
4229
|
+
const tree = parserInstance.parse(content);
|
|
4230
|
+
if (!tree) {
|
|
4231
|
+
if (filePath) parseCache.set(`php:${filePath}`, null);
|
|
4232
|
+
return null;
|
|
4233
|
+
}
|
|
4234
|
+
const result = convertNode(tree.rootNode, null);
|
|
4235
|
+
if (filePath) parseCache.set(`php:${filePath}`, result);
|
|
4236
|
+
return result;
|
|
4237
|
+
} catch {
|
|
4238
|
+
if (filePath) parseCache.set(`php:${filePath}`, null);
|
|
4239
|
+
return null;
|
|
4240
|
+
}
|
|
4241
|
+
}
|
|
4242
|
+
async function parseCsharpFile(content, filePath) {
|
|
4243
|
+
if (filePath) {
|
|
4244
|
+
const cached = parseCache.get(`cs:${filePath}`);
|
|
4245
|
+
if (cached !== void 0) return cached;
|
|
4246
|
+
}
|
|
4247
|
+
if (!csharpLang) {
|
|
4248
|
+
const ok = await initCsharpParser();
|
|
4249
|
+
if (!ok) return null;
|
|
4250
|
+
}
|
|
4251
|
+
if (!parserInstance) {
|
|
4252
|
+
const ok = await initParser();
|
|
4253
|
+
if (!ok) return null;
|
|
4254
|
+
}
|
|
4255
|
+
try {
|
|
4256
|
+
parserInstance.setLanguage(csharpLang);
|
|
4257
|
+
const tree = parserInstance.parse(content);
|
|
4258
|
+
if (!tree) {
|
|
4259
|
+
if (filePath) parseCache.set(`cs:${filePath}`, null);
|
|
4260
|
+
return null;
|
|
4261
|
+
}
|
|
4262
|
+
const result = convertNode(tree.rootNode, null);
|
|
4263
|
+
if (filePath) parseCache.set(`cs:${filePath}`, result);
|
|
4264
|
+
return result;
|
|
4265
|
+
} catch {
|
|
4266
|
+
if (filePath) parseCache.set(`cs:${filePath}`, null);
|
|
4267
|
+
return null;
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
async function parseSwiftFile(content, filePath) {
|
|
4271
|
+
if (filePath) {
|
|
4272
|
+
const cached = parseCache.get(`swift:${filePath}`);
|
|
4273
|
+
if (cached !== void 0) return cached;
|
|
4274
|
+
}
|
|
4275
|
+
if (!swiftLang) {
|
|
4276
|
+
const ok = await initSwiftParser();
|
|
4277
|
+
if (!ok) return null;
|
|
4278
|
+
}
|
|
4279
|
+
if (!parserInstance) {
|
|
4280
|
+
const ok = await initParser();
|
|
4281
|
+
if (!ok) return null;
|
|
4282
|
+
}
|
|
4283
|
+
try {
|
|
4284
|
+
parserInstance.setLanguage(swiftLang);
|
|
4285
|
+
const tree = parserInstance.parse(content);
|
|
4286
|
+
if (!tree) {
|
|
4287
|
+
if (filePath) parseCache.set(`swift:${filePath}`, null);
|
|
4288
|
+
return null;
|
|
4289
|
+
}
|
|
4290
|
+
const result = convertNode(tree.rootNode, null);
|
|
4291
|
+
if (filePath) parseCache.set(`swift:${filePath}`, result);
|
|
4292
|
+
return result;
|
|
4293
|
+
} catch {
|
|
4294
|
+
if (filePath) parseCache.set(`swift:${filePath}`, null);
|
|
4295
|
+
return null;
|
|
4296
|
+
}
|
|
4297
|
+
}
|
|
4298
|
+
function findNodesOfType(root, type) {
|
|
4299
|
+
const results = [];
|
|
4300
|
+
function walk(node) {
|
|
4301
|
+
if (node.type === type) results.push(node);
|
|
4302
|
+
for (const child of node.children) walk(child);
|
|
4303
|
+
}
|
|
4304
|
+
walk(root);
|
|
4305
|
+
return results;
|
|
4306
|
+
}
|
|
4307
|
+
function findNodesOfTypes(root, types3) {
|
|
4308
|
+
const typeSet = new Set(types3);
|
|
4309
|
+
const results = [];
|
|
4310
|
+
function walk(node) {
|
|
4311
|
+
if (typeSet.has(node.type)) results.push(node);
|
|
4312
|
+
for (const child of node.children) walk(child);
|
|
4313
|
+
}
|
|
4314
|
+
walk(root);
|
|
4315
|
+
return results;
|
|
4316
|
+
}
|
|
4317
|
+
function walkAST(root, visitor) {
|
|
4318
|
+
function walk(node) {
|
|
4319
|
+
const result = visitor(node);
|
|
4320
|
+
if (result !== false) {
|
|
4321
|
+
for (const child of node.children) walk(child);
|
|
4322
|
+
}
|
|
4323
|
+
}
|
|
4324
|
+
walk(root);
|
|
4325
|
+
}
|
|
4326
|
+
function findAncestor(node, predicate) {
|
|
4327
|
+
let current = node.parent;
|
|
4328
|
+
while (current) {
|
|
4329
|
+
if (predicate(current)) return current;
|
|
4330
|
+
current = current.parent;
|
|
4331
|
+
}
|
|
4332
|
+
return null;
|
|
4333
|
+
}
|
|
4334
|
+
function isInsideCatch(node) {
|
|
4335
|
+
return findAncestor(node, (n) => n.type === "catch_clause") !== null;
|
|
4336
|
+
}
|
|
4337
|
+
function findAncestorOfType(node, type) {
|
|
4338
|
+
return findAncestor(node, (n) => n.type === type);
|
|
4339
|
+
}
|
|
4340
|
+
function isCatchBodyEmpty(catchNode) {
|
|
4341
|
+
if (catchNode.type !== "catch_clause") return false;
|
|
4342
|
+
const body = catchNode.children.find(
|
|
4343
|
+
(c) => c.type === "statement_block" || c.type === "block"
|
|
4344
|
+
);
|
|
4345
|
+
if (!body) return true;
|
|
4346
|
+
const nonTrivial = body.children.filter(
|
|
4347
|
+
(c) => c.type !== "comment" && c.type !== "//" && c.type !== "/*" && c.type !== "{" && c.type !== "}" && c.text.trim() !== ""
|
|
4348
|
+
);
|
|
4349
|
+
return nonTrivial.length === 0;
|
|
4350
|
+
}
|
|
4351
|
+
function getAsExpressionType(node) {
|
|
4352
|
+
if (node.type !== "as_expression") return null;
|
|
4353
|
+
const typeChild = node.children.find((c) => c.fieldName === "type");
|
|
4354
|
+
return typeChild?.text ?? null;
|
|
4355
|
+
}
|
|
4356
|
+
function getAsExpressionContext(node) {
|
|
4357
|
+
if (isInsideCatch(node)) return "catch";
|
|
4358
|
+
const funcAncestor = findAncestor(
|
|
4359
|
+
node,
|
|
4360
|
+
(n) => ["function_declaration", "arrow_function", "method_definition"].includes(n.type)
|
|
4361
|
+
);
|
|
4362
|
+
if (funcAncestor) {
|
|
4363
|
+
const text = funcAncestor.text.toLowerCase();
|
|
4364
|
+
if (/prisma|drizzle|sequelize|mongoose|typeorm|knex|supabase/.test(text))
|
|
4365
|
+
return "orm";
|
|
4366
|
+
if (/json\.parse|parse\(/.test(text)) return "json";
|
|
4367
|
+
}
|
|
4368
|
+
return "unknown";
|
|
4369
|
+
}
|
|
4370
|
+
function extractImportFromNode(node) {
|
|
4371
|
+
if (node.type !== "import_statement" && node.type !== "import_declaration")
|
|
4372
|
+
return null;
|
|
4373
|
+
const sourceNode = node.children.find(
|
|
4374
|
+
(c) => c.type === "string" || c.fieldName === "source"
|
|
4375
|
+
);
|
|
4376
|
+
if (!sourceNode) return null;
|
|
4377
|
+
const source = sourceNode.text.replace(/^['"]|['"]$/g, "");
|
|
4378
|
+
const isTypeOnly = node.text.includes("import type ");
|
|
4379
|
+
const symbols = [];
|
|
4380
|
+
const namedImport = node.children.find(
|
|
4381
|
+
(c) => c.type === "named_imports" || c.type === "import_clause"
|
|
4382
|
+
);
|
|
4383
|
+
if (namedImport) {
|
|
4384
|
+
for (const child of namedImport.children) {
|
|
4385
|
+
if (child.type === "identifier" || child.type === "type_identifier" || child.type === "import_specifier") {
|
|
4386
|
+
symbols.push(child.text);
|
|
4387
|
+
}
|
|
4388
|
+
}
|
|
4389
|
+
}
|
|
4390
|
+
return { source, symbols, line: node.startRow + 1, isTypeOnly };
|
|
4391
|
+
}
|
|
4392
|
+
function findPythonFunctions(root) {
|
|
4393
|
+
const funcNodes = findNodesOfTypes(root, [
|
|
4394
|
+
"function_definition",
|
|
4395
|
+
"decorated_definition"
|
|
4396
|
+
]);
|
|
4397
|
+
const results = [];
|
|
4398
|
+
for (const node of funcNodes) {
|
|
4399
|
+
if (node.type === "decorated_definition") {
|
|
4400
|
+
const inner = node.children.find(
|
|
4401
|
+
(c) => c.type === "function_definition"
|
|
4402
|
+
);
|
|
4403
|
+
if (inner) {
|
|
4404
|
+
results.push(extractPythonFunctionInfo(inner, node));
|
|
4405
|
+
}
|
|
4406
|
+
} else {
|
|
4407
|
+
results.push(extractPythonFunctionInfo(node));
|
|
4408
|
+
}
|
|
4409
|
+
}
|
|
4410
|
+
return results;
|
|
4411
|
+
}
|
|
4412
|
+
function findPythonClasses(root) {
|
|
4413
|
+
const classNodes = findNodesOfTypes(root, [
|
|
4414
|
+
"class_definition",
|
|
4415
|
+
"decorated_definition"
|
|
4416
|
+
]);
|
|
4417
|
+
const results = [];
|
|
4418
|
+
for (const node of classNodes) {
|
|
4419
|
+
if (node.type === "decorated_definition") {
|
|
4420
|
+
const inner = node.children.find(
|
|
4421
|
+
(c) => c.type === "class_definition"
|
|
4422
|
+
);
|
|
4423
|
+
if (inner) {
|
|
4424
|
+
results.push(extractPythonClassInfo(inner, node));
|
|
4425
|
+
}
|
|
4426
|
+
} else {
|
|
4427
|
+
results.push(extractPythonClassInfo(node));
|
|
4428
|
+
}
|
|
4429
|
+
}
|
|
4430
|
+
return results;
|
|
4431
|
+
}
|
|
4432
|
+
function findPythonImports(root) {
|
|
4433
|
+
const importNodes = findNodesOfTypes(root, [
|
|
4434
|
+
"import_statement",
|
|
4435
|
+
"import_from_statement"
|
|
4436
|
+
]);
|
|
4437
|
+
return importNodes.map(extractPythonImportInfo);
|
|
4438
|
+
}
|
|
4439
|
+
function isPythonFunctionStub(funcInfo) {
|
|
4440
|
+
const text = funcInfo.text;
|
|
4441
|
+
const bodyLines = text.split("\n").slice(1).join("\n").trim();
|
|
4442
|
+
if (/^(\s*(pass|\.\.\.)\s*)$/.test(bodyLines)) return true;
|
|
4443
|
+
const docstringOnly = bodyLines.replace(/"""[\s\S]*?"""/g, "").replace(/'''[\s\S]*?'''/g, "").trim();
|
|
4444
|
+
if (docstringOnly === "" || docstringOnly === "pass" || docstringOnly === "...") {
|
|
4445
|
+
return true;
|
|
4446
|
+
}
|
|
4447
|
+
return false;
|
|
4448
|
+
}
|
|
4449
|
+
function detectPythonAIPatterns(root) {
|
|
4450
|
+
const findings = [];
|
|
4451
|
+
const functions = findPythonFunctions(root);
|
|
4452
|
+
for (const fn of functions) {
|
|
4453
|
+
if (isPythonFunctionStub(fn)) {
|
|
4454
|
+
findings.push({
|
|
4455
|
+
type: "python-stub-function",
|
|
4456
|
+
message: `Function '${fn.name}' is a stub (only pass/ellipsis)`,
|
|
4457
|
+
line: fn.line
|
|
4458
|
+
});
|
|
4459
|
+
}
|
|
4460
|
+
}
|
|
4461
|
+
const tryNodes = findNodesOfType(root, "try_statement");
|
|
4462
|
+
for (const tryNode of tryNodes) {
|
|
4463
|
+
const exceptNodes = tryNode.children.filter(
|
|
4464
|
+
(c) => c.type === "except_clause"
|
|
4465
|
+
);
|
|
4466
|
+
for (const exceptNode of exceptNodes) {
|
|
4467
|
+
const hasSpecificType = exceptNode.children.some(
|
|
4468
|
+
(c) => c.type === "identifier" || c.type === "tuple"
|
|
4469
|
+
);
|
|
4470
|
+
if (!hasSpecificType) {
|
|
4471
|
+
const bareExcept = exceptNode.children.find(
|
|
4472
|
+
(c) => c.text && c.text.includes("except")
|
|
4473
|
+
);
|
|
4474
|
+
findings.push({
|
|
4475
|
+
type: "python-bare-except",
|
|
4476
|
+
message: "Bare except clause catches all exceptions",
|
|
4477
|
+
line: exceptNode.startRow + 1
|
|
4478
|
+
});
|
|
4479
|
+
}
|
|
4480
|
+
}
|
|
4481
|
+
}
|
|
4482
|
+
const commentNodes = findNodesOfType(root, "comment");
|
|
4483
|
+
for (const comment of commentNodes) {
|
|
4484
|
+
const text = comment.text.toLowerCase();
|
|
4485
|
+
if (/todo|fixme|hack|xxx/.test(text)) {
|
|
4486
|
+
findings.push({
|
|
4487
|
+
type: "python-todo-stub",
|
|
4488
|
+
message: `TODO/FIXME comment: ${comment.text.trim()}`,
|
|
4489
|
+
line: comment.startRow + 1
|
|
4490
|
+
});
|
|
4491
|
+
}
|
|
4626
4492
|
}
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
const
|
|
4630
|
-
if (
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4493
|
+
const callNodes = findNodesOfType(root, "call");
|
|
4494
|
+
for (const call of callNodes) {
|
|
4495
|
+
const func = call.children[0];
|
|
4496
|
+
if (func && func.text === "print") {
|
|
4497
|
+
findings.push({
|
|
4498
|
+
type: "python-print-leftover",
|
|
4499
|
+
message: "print() statement \u2014 likely debug leftover",
|
|
4500
|
+
line: call.startRow + 1
|
|
4501
|
+
});
|
|
4502
|
+
}
|
|
4634
4503
|
}
|
|
4504
|
+
return findings;
|
|
4635
4505
|
}
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4506
|
+
function extractPythonFunctionInfo(funcNode, decoratedParent) {
|
|
4507
|
+
const nameNode = funcNode.children.find((c) => c.fieldName === "name") ?? funcNode.children.find((c) => c.type === "identifier");
|
|
4508
|
+
const name = nameNode?.text ?? "(anonymous)";
|
|
4509
|
+
const params = funcNode.children.find(
|
|
4510
|
+
(c) => c.type === "parameters"
|
|
4511
|
+
);
|
|
4512
|
+
const parameters = params ? params.children.filter((c) => c.type === "identifier" || c.type === "typed_parameter" || c.type === "default_parameter").map((c) => c.children[0]?.text ?? c.text) : [];
|
|
4513
|
+
const isAsync = funcNode.children.some(
|
|
4514
|
+
(c) => c.type === "async"
|
|
4515
|
+
);
|
|
4516
|
+
const decorators = [];
|
|
4517
|
+
if (decoratedParent) {
|
|
4518
|
+
for (const child of decoratedParent.children) {
|
|
4519
|
+
if (child.type === "decorator") {
|
|
4520
|
+
decorators.push(child.text.replace("@", ""));
|
|
4521
|
+
}
|
|
4522
|
+
}
|
|
4652
4523
|
}
|
|
4524
|
+
return {
|
|
4525
|
+
name,
|
|
4526
|
+
decorators,
|
|
4527
|
+
parameters,
|
|
4528
|
+
isAsync,
|
|
4529
|
+
line: funcNode.startRow + 1,
|
|
4530
|
+
endLine: funcNode.endRow + 1,
|
|
4531
|
+
text: funcNode.text
|
|
4532
|
+
};
|
|
4653
4533
|
}
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4534
|
+
function extractPythonClassInfo(classNode, decoratedParent) {
|
|
4535
|
+
const nameNode = classNode.children.find((c) => c.fieldName === "name") ?? classNode.children.find((c) => c.type === "identifier");
|
|
4536
|
+
const name = nameNode?.text ?? "(anonymous)";
|
|
4537
|
+
const argList = classNode.children.find(
|
|
4538
|
+
(c) => c.type === "argument_list"
|
|
4539
|
+
);
|
|
4540
|
+
const bases = argList ? argList.children.filter((c) => c.type === "identifier" || c.type === "attribute").map((c) => c.text) : [];
|
|
4541
|
+
const decorators = [];
|
|
4542
|
+
if (decoratedParent) {
|
|
4543
|
+
for (const child of decoratedParent.children) {
|
|
4544
|
+
if (child.type === "decorator") {
|
|
4545
|
+
decorators.push(child.text.replace("@", ""));
|
|
4546
|
+
}
|
|
4547
|
+
}
|
|
4658
4548
|
}
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4549
|
+
const body = classNode.children.find(
|
|
4550
|
+
(c) => c.type === "block"
|
|
4551
|
+
);
|
|
4552
|
+
const methods = [];
|
|
4553
|
+
if (body) {
|
|
4554
|
+
for (const child of body.children) {
|
|
4555
|
+
if (child.type === "function_definition") {
|
|
4556
|
+
methods.push(extractPythonFunctionInfo(child));
|
|
4557
|
+
} else if (child.type === "decorated_definition") {
|
|
4558
|
+
const inner = child.children.find(
|
|
4559
|
+
(c) => c.type === "function_definition"
|
|
4560
|
+
);
|
|
4561
|
+
if (inner) {
|
|
4562
|
+
methods.push(extractPythonFunctionInfo(inner, child));
|
|
4563
|
+
}
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4662
4566
|
}
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4567
|
+
return {
|
|
4568
|
+
name,
|
|
4569
|
+
bases,
|
|
4570
|
+
decorators,
|
|
4571
|
+
methods,
|
|
4572
|
+
line: classNode.startRow + 1,
|
|
4573
|
+
endLine: classNode.endRow + 1,
|
|
4574
|
+
text: classNode.text
|
|
4575
|
+
};
|
|
4576
|
+
}
|
|
4577
|
+
function extractPythonImportInfo(importNode) {
|
|
4578
|
+
const isFromImport = importNode.type === "import_from_statement";
|
|
4579
|
+
let module = "";
|
|
4580
|
+
const symbols = [];
|
|
4581
|
+
if (isFromImport) {
|
|
4582
|
+
const moduleNode = importNode.children.find(
|
|
4583
|
+
(c) => c.fieldName === "module_name" || c.type === "dotted_name" && c.fieldName !== "name" || c.type === "identifier" && c.fieldName !== "name"
|
|
4584
|
+
);
|
|
4585
|
+
module = moduleNode?.text ?? "";
|
|
4586
|
+
const nameList = importNode.children.find(
|
|
4587
|
+
(c) => c.type === "dotted_name" && c !== moduleNode
|
|
4588
|
+
);
|
|
4589
|
+
const identifierChildren = importNode.children.filter(
|
|
4590
|
+
(c) => c.type === "identifier" && c !== moduleNode
|
|
4591
|
+
);
|
|
4592
|
+
if (nameList) {
|
|
4593
|
+
symbols.push(nameList.text);
|
|
4594
|
+
}
|
|
4595
|
+
for (const id of identifierChildren) {
|
|
4596
|
+
if (id.text !== "from" && id.text !== "import" && id.text !== module) {
|
|
4597
|
+
symbols.push(id.text);
|
|
4598
|
+
}
|
|
4599
|
+
}
|
|
4600
|
+
} else {
|
|
4601
|
+
const dottedNames = importNode.children.filter(
|
|
4602
|
+
(c) => c.type === "dotted_name"
|
|
4603
|
+
);
|
|
4604
|
+
const identifiers = importNode.children.filter(
|
|
4605
|
+
(c) => c.type === "identifier"
|
|
4606
|
+
);
|
|
4607
|
+
for (const dn of dottedNames) {
|
|
4608
|
+
symbols.push(dn.text);
|
|
4609
|
+
}
|
|
4610
|
+
for (const id of identifiers) {
|
|
4611
|
+
if (id.text !== "import") {
|
|
4612
|
+
symbols.push(id.text);
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
module = symbols[0] ?? "";
|
|
4670
4616
|
}
|
|
4617
|
+
return {
|
|
4618
|
+
module,
|
|
4619
|
+
symbols,
|
|
4620
|
+
isFromImport,
|
|
4621
|
+
line: importNode.startRow + 1,
|
|
4622
|
+
text: importNode.text
|
|
4623
|
+
};
|
|
4671
4624
|
}
|
|
4672
|
-
function
|
|
4673
|
-
const
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4625
|
+
function convertNode(node, parent) {
|
|
4626
|
+
const children = [];
|
|
4627
|
+
const astNode = {
|
|
4628
|
+
type: node.type,
|
|
4629
|
+
text: node.text,
|
|
4630
|
+
startRow: node.startPosition.row,
|
|
4631
|
+
startCol: node.startPosition.column,
|
|
4632
|
+
endRow: node.endPosition.row,
|
|
4633
|
+
endCol: node.endPosition.column,
|
|
4634
|
+
children,
|
|
4635
|
+
parent,
|
|
4636
|
+
fieldName: null
|
|
4637
|
+
};
|
|
4638
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
4639
|
+
const child = node.child(i);
|
|
4640
|
+
if (child) {
|
|
4641
|
+
const converted = convertNode(child, astNode);
|
|
4642
|
+
converted.fieldName = node.fieldNameForChild(i) ?? null;
|
|
4643
|
+
children.push(converted);
|
|
4644
|
+
}
|
|
4677
4645
|
}
|
|
4678
|
-
|
|
4679
|
-
return results;
|
|
4646
|
+
return astNode;
|
|
4680
4647
|
}
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4648
|
+
var parseCache, parserInstance, tsLang, tsxLang, initPromise, initDone, initOk, pyLang, pyInitDone, pyInitOk, goLang, goInitDone, goInitOk, rustLang, rustInitDone, rustInitOk, phpLang, phpInitDone, phpInitOk, csharpLang, csharpInitDone, csharpInitOk, swiftLang, swiftInitDone, swiftInitOk;
|
|
4649
|
+
var init_tree_sitter = __esm({
|
|
4650
|
+
"src/utils/tree-sitter.ts"() {
|
|
4651
|
+
"use strict";
|
|
4652
|
+
parseCache = /* @__PURE__ */ new Map();
|
|
4653
|
+
parserInstance = null;
|
|
4654
|
+
tsLang = null;
|
|
4655
|
+
tsxLang = null;
|
|
4656
|
+
initPromise = null;
|
|
4657
|
+
initDone = false;
|
|
4658
|
+
initOk = false;
|
|
4659
|
+
pyLang = null;
|
|
4660
|
+
pyInitDone = false;
|
|
4661
|
+
pyInitOk = false;
|
|
4662
|
+
goLang = null;
|
|
4663
|
+
goInitDone = false;
|
|
4664
|
+
goInitOk = false;
|
|
4665
|
+
rustLang = null;
|
|
4666
|
+
rustInitDone = false;
|
|
4667
|
+
rustInitOk = false;
|
|
4668
|
+
phpLang = null;
|
|
4669
|
+
phpInitDone = false;
|
|
4670
|
+
phpInitOk = false;
|
|
4671
|
+
csharpLang = null;
|
|
4672
|
+
csharpInitDone = false;
|
|
4673
|
+
csharpInitOk = false;
|
|
4674
|
+
swiftLang = null;
|
|
4675
|
+
swiftInitDone = false;
|
|
4676
|
+
swiftInitOk = false;
|
|
4677
|
+
}
|
|
4678
|
+
});
|
|
4679
|
+
|
|
4680
|
+
// src/plugins/loader.ts
|
|
4681
|
+
async function loadPlugin(pluginPath) {
|
|
4682
|
+
try {
|
|
4683
|
+
const mod = await import(pluginPath);
|
|
4684
|
+
const engine = mod.default;
|
|
4685
|
+
if (!engine || typeof engine !== "object") {
|
|
4686
|
+
return null;
|
|
4687
|
+
}
|
|
4688
|
+
if (typeof engine.name === "string" && typeof engine.description === "string" && Array.isArray(engine.supportedLanguages) && typeof engine.run === "function") {
|
|
4689
|
+
return engine;
|
|
4690
|
+
}
|
|
4691
|
+
return null;
|
|
4692
|
+
} catch {
|
|
4693
|
+
return null;
|
|
4687
4694
|
}
|
|
4688
|
-
walk(root);
|
|
4689
|
-
return results;
|
|
4690
4695
|
}
|
|
4691
|
-
function
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
+
async function loadPlugins(paths) {
|
|
4697
|
+
const results = await Promise.allSettled(
|
|
4698
|
+
paths.map((p) => loadPlugin(p))
|
|
4699
|
+
);
|
|
4700
|
+
const engines = [];
|
|
4701
|
+
for (const r of results) {
|
|
4702
|
+
if (r.status === "fulfilled" && r.value !== null) {
|
|
4703
|
+
engines.push(r.value);
|
|
4696
4704
|
}
|
|
4697
4705
|
}
|
|
4698
|
-
|
|
4706
|
+
return engines;
|
|
4699
4707
|
}
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
if (predicate(current)) return current;
|
|
4704
|
-
current = current.parent;
|
|
4708
|
+
var init_loader = __esm({
|
|
4709
|
+
"src/plugins/loader.ts"() {
|
|
4710
|
+
"use strict";
|
|
4705
4711
|
}
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
(c) => c.type !== "comment" && c.type !== "//" && c.type !== "/*" && c.type !== "{" && c.type !== "}" && c.text.trim() !== ""
|
|
4722
|
-
);
|
|
4723
|
-
return nonTrivial.length === 0;
|
|
4724
|
-
}
|
|
4725
|
-
function getAsExpressionType(node) {
|
|
4726
|
-
if (node.type !== "as_expression") return null;
|
|
4727
|
-
const typeChild = node.children.find((c) => c.fieldName === "type");
|
|
4728
|
-
return typeChild?.text ?? null;
|
|
4712
|
+
});
|
|
4713
|
+
|
|
4714
|
+
// src/plugins/registry.ts
|
|
4715
|
+
var registry_exports = {};
|
|
4716
|
+
__export(registry_exports, {
|
|
4717
|
+
PLUGIN_DIR: () => PLUGIN_DIR,
|
|
4718
|
+
discoverAndLoadPlugins: () => discoverAndLoadPlugins,
|
|
4719
|
+
getPluginDir: () => getPluginDir,
|
|
4720
|
+
pluginRegistry: () => pluginRegistry
|
|
4721
|
+
});
|
|
4722
|
+
import { join as join2 } from "node:path";
|
|
4723
|
+
import { readdir } from "node:fs/promises";
|
|
4724
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
4725
|
+
function getPluginDir(rootDir) {
|
|
4726
|
+
return join2(rootDir, PLUGIN_DIR);
|
|
4729
4727
|
}
|
|
4730
|
-
function
|
|
4731
|
-
if (
|
|
4732
|
-
|
|
4733
|
-
node,
|
|
4734
|
-
(n) => ["function_declaration", "arrow_function", "method_definition"].includes(n.type)
|
|
4735
|
-
);
|
|
4736
|
-
if (funcAncestor) {
|
|
4737
|
-
const text = funcAncestor.text.toLowerCase();
|
|
4738
|
-
if (/prisma|drizzle|sequelize|mongoose|typeorm|knex|supabase/.test(text))
|
|
4739
|
-
return "orm";
|
|
4740
|
-
if (/json\.parse|parse\(/.test(text)) return "json";
|
|
4728
|
+
async function discoverAndLoadPlugins(rootDir) {
|
|
4729
|
+
if (pluginRegistry.isLoaded) {
|
|
4730
|
+
return pluginRegistry.getEngines();
|
|
4741
4731
|
}
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
return null;
|
|
4747
|
-
const sourceNode = node.children.find(
|
|
4748
|
-
(c) => c.type === "string" || c.fieldName === "source"
|
|
4749
|
-
);
|
|
4750
|
-
if (!sourceNode) return null;
|
|
4751
|
-
const source = sourceNode.text.replace(/^['"]|['"]$/g, "");
|
|
4752
|
-
const isTypeOnly = node.text.includes("import type ");
|
|
4753
|
-
const symbols = [];
|
|
4754
|
-
const namedImport = node.children.find(
|
|
4755
|
-
(c) => c.type === "named_imports" || c.type === "import_clause"
|
|
4756
|
-
);
|
|
4757
|
-
if (namedImport) {
|
|
4758
|
-
for (const child of namedImport.children) {
|
|
4759
|
-
if (child.type === "identifier" || child.type === "type_identifier" || child.type === "import_specifier") {
|
|
4760
|
-
symbols.push(child.text);
|
|
4761
|
-
}
|
|
4762
|
-
}
|
|
4732
|
+
const pluginDir = getPluginDir(rootDir);
|
|
4733
|
+
if (!existsSync2(pluginDir)) {
|
|
4734
|
+
pluginRegistry.setLoaded(true);
|
|
4735
|
+
return [];
|
|
4763
4736
|
}
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
);
|
|
4777
|
-
if (inner) {
|
|
4778
|
-
results.push(extractPythonFunctionInfo(inner, node));
|
|
4779
|
-
}
|
|
4780
|
-
} else {
|
|
4781
|
-
results.push(extractPythonFunctionInfo(node));
|
|
4737
|
+
try {
|
|
4738
|
+
const files = await readdir(pluginDir);
|
|
4739
|
+
const pluginPaths = files.filter((f) => f.endsWith(".js") || f.endsWith(".mjs")).map((f) => join2(pluginDir, f));
|
|
4740
|
+
const engines = await loadPlugins(pluginPaths);
|
|
4741
|
+
for (let i = 0; i < engines.length; i++) {
|
|
4742
|
+
const engine = engines[i];
|
|
4743
|
+
pluginRegistry.register({
|
|
4744
|
+
id: engine.name,
|
|
4745
|
+
path: pluginPaths[i],
|
|
4746
|
+
engine,
|
|
4747
|
+
loaded: true
|
|
4748
|
+
});
|
|
4782
4749
|
}
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
if (inner) {
|
|
4798
|
-
results.push(extractPythonClassInfo(inner, node));
|
|
4750
|
+
for (let i = 0; i < pluginPaths.length; i++) {
|
|
4751
|
+
const path2 = pluginPaths[i];
|
|
4752
|
+
const engine = engines.find((e) => {
|
|
4753
|
+
const entry = pluginRegistry.getAll().find((ent) => ent.path === path2);
|
|
4754
|
+
return entry?.engine;
|
|
4755
|
+
});
|
|
4756
|
+
if (!engine && !pluginRegistry.has(path2)) {
|
|
4757
|
+
pluginRegistry.register({
|
|
4758
|
+
id: `plugin-${i}`,
|
|
4759
|
+
path: path2,
|
|
4760
|
+
engine: null,
|
|
4761
|
+
loaded: false,
|
|
4762
|
+
error: "Failed to load plugin module"
|
|
4763
|
+
});
|
|
4799
4764
|
}
|
|
4800
|
-
} else {
|
|
4801
|
-
results.push(extractPythonClassInfo(node));
|
|
4802
4765
|
}
|
|
4766
|
+
pluginRegistry.setLoaded(true);
|
|
4767
|
+
return engines;
|
|
4768
|
+
} catch {
|
|
4769
|
+
pluginRegistry.setLoaded(true);
|
|
4770
|
+
return [];
|
|
4803
4771
|
}
|
|
4804
|
-
return results;
|
|
4805
|
-
}
|
|
4806
|
-
function findPythonImports(root) {
|
|
4807
|
-
const importNodes = findNodesOfTypes(root, [
|
|
4808
|
-
"import_statement",
|
|
4809
|
-
"import_from_statement"
|
|
4810
|
-
]);
|
|
4811
|
-
return importNodes.map(extractPythonImportInfo);
|
|
4812
4772
|
}
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4773
|
+
var PluginRegistry, pluginRegistry, PLUGIN_DIR;
|
|
4774
|
+
var init_registry = __esm({
|
|
4775
|
+
"src/plugins/registry.ts"() {
|
|
4776
|
+
"use strict";
|
|
4777
|
+
init_loader();
|
|
4778
|
+
PluginRegistry = class {
|
|
4779
|
+
entries = /* @__PURE__ */ new Map();
|
|
4780
|
+
loaded = false;
|
|
4781
|
+
/** Get all registered plugins */
|
|
4782
|
+
getAll() {
|
|
4783
|
+
return [...this.entries.values()];
|
|
4784
|
+
}
|
|
4785
|
+
/** Get all successfully loaded engines */
|
|
4786
|
+
getEngines() {
|
|
4787
|
+
return [...this.entries.values()].filter((e) => e.loaded).map((e) => e.engine);
|
|
4788
|
+
}
|
|
4789
|
+
/** Get a specific plugin by id */
|
|
4790
|
+
get(id) {
|
|
4791
|
+
return this.entries.get(id);
|
|
4792
|
+
}
|
|
4793
|
+
/** Get a loaded engine by name */
|
|
4794
|
+
getEngine(name) {
|
|
4795
|
+
const entry = this.entries.get(name);
|
|
4796
|
+
return entry?.loaded ? entry.engine : void 0;
|
|
4797
|
+
}
|
|
4798
|
+
/** Register a plugin entry */
|
|
4799
|
+
register(entry) {
|
|
4800
|
+
this.entries.set(entry.id, entry);
|
|
4801
|
+
}
|
|
4802
|
+
/** Remove a plugin by id */
|
|
4803
|
+
remove(id) {
|
|
4804
|
+
return this.entries.delete(id);
|
|
4805
|
+
}
|
|
4806
|
+
/** Check if a plugin is registered */
|
|
4807
|
+
has(id) {
|
|
4808
|
+
return this.entries.has(id);
|
|
4809
|
+
}
|
|
4810
|
+
/** Number of registered plugins */
|
|
4811
|
+
get size() {
|
|
4812
|
+
return this.entries.size;
|
|
4813
|
+
}
|
|
4814
|
+
/** Whether the registry has been loaded from disk */
|
|
4815
|
+
get isLoaded() {
|
|
4816
|
+
return this.loaded;
|
|
4817
|
+
}
|
|
4818
|
+
/** Mark the registry as loaded */
|
|
4819
|
+
setLoaded(loaded) {
|
|
4820
|
+
this.loaded = loaded;
|
|
4821
|
+
}
|
|
4822
|
+
/** Clear all entries */
|
|
4823
|
+
clear() {
|
|
4824
|
+
this.entries.clear();
|
|
4825
|
+
this.loaded = false;
|
|
4826
|
+
}
|
|
4827
|
+
};
|
|
4828
|
+
pluginRegistry = new PluginRegistry();
|
|
4829
|
+
PLUGIN_DIR = ".deep-slop/plugins";
|
|
4820
4830
|
}
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4831
|
+
});
|
|
4832
|
+
|
|
4833
|
+
// src/utils/suppress.ts
|
|
4834
|
+
import { join as join3 } from "node:path";
|
|
4835
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
4836
|
+
function parseSuppressDirectives(content) {
|
|
4837
|
+
const entries = [];
|
|
4838
|
+
const lines = content.split("\n");
|
|
4839
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4840
|
+
const line = lines[i].trim();
|
|
4841
|
+
const lineNum = i + 1;
|
|
4842
|
+
const ignoreNextMatch = line.match(
|
|
4843
|
+
/\/\/\s*deep-slop-ignore-next(?:\s+(.+))?$/
|
|
4844
|
+
);
|
|
4845
|
+
if (ignoreNextMatch) {
|
|
4846
|
+
entries.push({
|
|
4847
|
+
directiveLine: lineNum,
|
|
4848
|
+
targetLine: lineNum + 1,
|
|
4849
|
+
rules: parseRuleList(ignoreNextMatch[1]),
|
|
4850
|
+
type: "next-line"
|
|
4832
4851
|
});
|
|
4852
|
+
continue;
|
|
4833
4853
|
}
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
for (const tryNode of tryNodes) {
|
|
4837
|
-
const exceptNodes = tryNode.children.filter(
|
|
4838
|
-
(c) => c.type === "except_clause"
|
|
4854
|
+
const ignoreLineMatch = line.match(
|
|
4855
|
+
/\/\/\s*deep-slop-ignore-line(?:\s+(.+))?$/
|
|
4839
4856
|
);
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4857
|
+
if (ignoreLineMatch) {
|
|
4858
|
+
entries.push({
|
|
4859
|
+
directiveLine: lineNum,
|
|
4860
|
+
targetLine: lineNum,
|
|
4861
|
+
rules: parseRuleList(ignoreLineMatch[1]),
|
|
4862
|
+
type: "line"
|
|
4863
|
+
});
|
|
4864
|
+
continue;
|
|
4865
|
+
}
|
|
4866
|
+
const ignoreRuleMatch = line.match(
|
|
4867
|
+
/\/\/\s*deep-slop-ignore(?:\s+(.+))?$/
|
|
4868
|
+
);
|
|
4869
|
+
if (ignoreRuleMatch) {
|
|
4870
|
+
const rulePart = ignoreRuleMatch[1];
|
|
4871
|
+
if (rulePart !== "start" && rulePart !== "end") {
|
|
4872
|
+
entries.push({
|
|
4873
|
+
directiveLine: lineNum,
|
|
4874
|
+
targetLine: lineNum + 1,
|
|
4875
|
+
rules: parseRuleList(rulePart),
|
|
4876
|
+
type: "next-line"
|
|
4852
4877
|
});
|
|
4878
|
+
continue;
|
|
4853
4879
|
}
|
|
4854
4880
|
}
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4881
|
+
const ignoreStartMatch = line.match(
|
|
4882
|
+
/\/\/\s*deep-slop-ignore-start(?:\s+(.+))?$/
|
|
4883
|
+
);
|
|
4884
|
+
if (ignoreStartMatch) {
|
|
4885
|
+
entries.push({
|
|
4886
|
+
directiveLine: lineNum,
|
|
4887
|
+
targetLine: lineNum,
|
|
4888
|
+
rules: parseRuleList(ignoreStartMatch[1]),
|
|
4889
|
+
type: "block-start"
|
|
4864
4890
|
});
|
|
4891
|
+
continue;
|
|
4865
4892
|
}
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4893
|
+
const ignoreEndMatch = line.match(
|
|
4894
|
+
/\/\/\s*deep-slop-ignore-end/
|
|
4895
|
+
);
|
|
4896
|
+
if (ignoreEndMatch) {
|
|
4897
|
+
entries.push({
|
|
4898
|
+
directiveLine: lineNum,
|
|
4899
|
+
targetLine: lineNum,
|
|
4900
|
+
rules: /* @__PURE__ */ new Set(),
|
|
4901
|
+
type: "block-end"
|
|
4902
|
+
});
|
|
4903
|
+
continue;
|
|
4904
|
+
}
|
|
4905
|
+
const nextLineMatch = line.match(
|
|
4906
|
+
/\/\/\s*deep-slop-disable-next-line(?:\s+(.+))?$/
|
|
4907
|
+
);
|
|
4908
|
+
if (nextLineMatch) {
|
|
4909
|
+
entries.push({
|
|
4910
|
+
directiveLine: lineNum,
|
|
4911
|
+
targetLine: lineNum + 1,
|
|
4912
|
+
rules: parseRuleList(nextLineMatch[1]),
|
|
4913
|
+
type: "next-line"
|
|
4914
|
+
});
|
|
4915
|
+
continue;
|
|
4916
|
+
}
|
|
4917
|
+
const lineMatch = line.match(
|
|
4918
|
+
/\/\/\s*deep-slop-disable-line(?:\s+(.+))?$/
|
|
4919
|
+
);
|
|
4920
|
+
if (lineMatch) {
|
|
4921
|
+
entries.push({
|
|
4922
|
+
directiveLine: lineNum,
|
|
4923
|
+
targetLine: lineNum,
|
|
4924
|
+
rules: parseRuleList(lineMatch[1]),
|
|
4925
|
+
type: "line"
|
|
4926
|
+
});
|
|
4927
|
+
continue;
|
|
4928
|
+
}
|
|
4929
|
+
const blockStart = line.match(
|
|
4930
|
+
/\/\*\s*deep-slop-disable(?:\s+(.+))?\s*\//
|
|
4931
|
+
);
|
|
4932
|
+
if (blockStart) {
|
|
4933
|
+
entries.push({
|
|
4934
|
+
directiveLine: lineNum,
|
|
4935
|
+
targetLine: lineNum,
|
|
4936
|
+
rules: parseRuleList(blockStart[1]),
|
|
4937
|
+
type: "block-start"
|
|
4938
|
+
});
|
|
4939
|
+
continue;
|
|
4940
|
+
}
|
|
4941
|
+
const blockEnd = line.match(/\/\*\s*deep-slop-enable\s*\//);
|
|
4942
|
+
if (blockEnd) {
|
|
4943
|
+
entries.push({
|
|
4944
|
+
directiveLine: lineNum,
|
|
4945
|
+
targetLine: lineNum,
|
|
4946
|
+
rules: /* @__PURE__ */ new Set(),
|
|
4947
|
+
type: "block-end"
|
|
4875
4948
|
});
|
|
4876
4949
|
}
|
|
4877
4950
|
}
|
|
4878
|
-
return
|
|
4951
|
+
return entries;
|
|
4879
4952
|
}
|
|
4880
|
-
function
|
|
4881
|
-
|
|
4882
|
-
const
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
const
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4953
|
+
function parseRuleList(rulesStr) {
|
|
4954
|
+
if (!rulesStr) return /* @__PURE__ */ new Set();
|
|
4955
|
+
const rules = rulesStr.split(/[,\\s]+/).map((r) => r.trim()).filter(Boolean);
|
|
4956
|
+
return new Set(rules);
|
|
4957
|
+
}
|
|
4958
|
+
function buildSuppressChecker(entries) {
|
|
4959
|
+
const blockRanges = [];
|
|
4960
|
+
let currentStart = null;
|
|
4961
|
+
for (const entry of entries) {
|
|
4962
|
+
if (entry.type === "block-start") {
|
|
4963
|
+
currentStart = { line: entry.directiveLine, rules: entry.rules };
|
|
4964
|
+
} else if (entry.type === "block-end" && currentStart) {
|
|
4965
|
+
blockRanges.push({
|
|
4966
|
+
startLine: currentStart.line,
|
|
4967
|
+
endLine: entry.directiveLine,
|
|
4968
|
+
rules: currentStart.rules
|
|
4969
|
+
});
|
|
4970
|
+
currentStart = null;
|
|
4896
4971
|
}
|
|
4897
4972
|
}
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4973
|
+
if (currentStart) {
|
|
4974
|
+
blockRanges.push({
|
|
4975
|
+
startLine: currentStart.line,
|
|
4976
|
+
endLine: 999999,
|
|
4977
|
+
rules: currentStart.rules
|
|
4978
|
+
});
|
|
4979
|
+
}
|
|
4980
|
+
return (line, rule) => {
|
|
4981
|
+
for (const entry of entries) {
|
|
4982
|
+
if (entry.type === "next-line" || entry.type === "line") {
|
|
4983
|
+
if (entry.targetLine === line) {
|
|
4984
|
+
if (entry.rules.size === 0 || entry.rules.has(rule)) {
|
|
4985
|
+
return true;
|
|
4986
|
+
}
|
|
4987
|
+
}
|
|
4988
|
+
}
|
|
4989
|
+
}
|
|
4990
|
+
for (const range2 of blockRanges) {
|
|
4991
|
+
if (line >= range2.startLine && line <= range2.endLine) {
|
|
4992
|
+
if (range2.rules.size === 0 || range2.rules.has(rule)) {
|
|
4993
|
+
return true;
|
|
4994
|
+
}
|
|
4995
|
+
}
|
|
4996
|
+
}
|
|
4997
|
+
return false;
|
|
4906
4998
|
};
|
|
4907
4999
|
}
|
|
4908
|
-
function
|
|
4909
|
-
const
|
|
4910
|
-
const
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
const
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
5000
|
+
function buildSuppressMap(content) {
|
|
5001
|
+
const entries = parseSuppressDirectives(content);
|
|
5002
|
+
const isSuppressed = buildSuppressChecker(entries);
|
|
5003
|
+
return { entries, isSuppressed };
|
|
5004
|
+
}
|
|
5005
|
+
function loadIgnoreFile(rootDir) {
|
|
5006
|
+
const ignorePath = join3(rootDir, ".deep-slop", ".deep-slop-ignore");
|
|
5007
|
+
try {
|
|
5008
|
+
const content = readFileSync2(ignorePath, "utf-8");
|
|
5009
|
+
return content.split("\n").map((line) => line.split("#")[0].trim()).filter((line) => line && !line.startsWith("file:"));
|
|
5010
|
+
} catch {
|
|
5011
|
+
return [];
|
|
5012
|
+
}
|
|
5013
|
+
}
|
|
5014
|
+
function applySuppressDirectives(diagnostics, fileContents, globallySuppressed = /* @__PURE__ */ new Set()) {
|
|
5015
|
+
const suppressMaps = /* @__PURE__ */ new Map();
|
|
5016
|
+
for (const [filePath, content] of fileContents) {
|
|
5017
|
+
suppressMaps.set(filePath, buildSuppressMap(content));
|
|
5018
|
+
}
|
|
5019
|
+
const filtered = [];
|
|
5020
|
+
let suppressedCount = 0;
|
|
5021
|
+
for (const diag8 of diagnostics) {
|
|
5022
|
+
if (globallySuppressed.has(diag8.rule)) {
|
|
5023
|
+
suppressedCount++;
|
|
5024
|
+
continue;
|
|
5025
|
+
}
|
|
5026
|
+
const map = suppressMaps.get(diag8.filePath);
|
|
5027
|
+
if (map && map.isSuppressed(diag8.line, diag8.rule)) {
|
|
5028
|
+
suppressedCount++;
|
|
5029
|
+
} else {
|
|
5030
|
+
filtered.push(diag8);
|
|
4921
5031
|
}
|
|
4922
5032
|
}
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
for (const child of body.children) {
|
|
4929
|
-
if (child.type === "function_definition") {
|
|
4930
|
-
methods.push(extractPythonFunctionInfo(child));
|
|
4931
|
-
} else if (child.type === "decorated_definition") {
|
|
4932
|
-
const inner = child.children.find(
|
|
4933
|
-
(c) => c.type === "function_definition"
|
|
4934
|
-
);
|
|
4935
|
-
if (inner) {
|
|
4936
|
-
methods.push(extractPythonFunctionInfo(inner, child));
|
|
4937
|
-
}
|
|
4938
|
-
}
|
|
4939
|
-
}
|
|
5033
|
+
return { filtered, suppressedCount };
|
|
5034
|
+
}
|
|
5035
|
+
var init_suppress = __esm({
|
|
5036
|
+
"src/utils/suppress.ts"() {
|
|
5037
|
+
"use strict";
|
|
4940
5038
|
}
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
5039
|
+
});
|
|
5040
|
+
|
|
5041
|
+
// src/utils/file-utils.ts
|
|
5042
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
5043
|
+
async function readFileContent(filePath) {
|
|
5044
|
+
const buffer = await readFile2(filePath);
|
|
5045
|
+
let content = buffer.toString("utf-8");
|
|
5046
|
+
if (content.charCodeAt(0) === 65279) {
|
|
5047
|
+
content = content.slice(1);
|
|
5048
|
+
}
|
|
5049
|
+
return content;
|
|
4950
5050
|
}
|
|
4951
|
-
function
|
|
4952
|
-
const
|
|
4953
|
-
|
|
4954
|
-
const
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
5051
|
+
function detectEncodingAnomalies(content) {
|
|
5052
|
+
const hasBom = content.charCodeAt(0) === 65279;
|
|
5053
|
+
const hasCrlf = content.includes("\r\n");
|
|
5054
|
+
const hasZwnbsp = content.includes("\uFEFF");
|
|
5055
|
+
const lfOnly = (content.match(/(?<!\r)\n/g) ?? []).length;
|
|
5056
|
+
const crlfCount = (content.match(/\r\n/g) ?? []).length;
|
|
5057
|
+
const lineEnding = crlfCount > 0 && lfOnly > crlfCount ? "mixed" : crlfCount > 0 ? "crlf" : "lf";
|
|
5058
|
+
return { hasBom, hasCrlf, hasZwnbsp, lineEnding };
|
|
5059
|
+
}
|
|
5060
|
+
function toLines(content) {
|
|
5061
|
+
return content.split("\n").map((text, i) => ({ num: i + 1, text }));
|
|
5062
|
+
}
|
|
5063
|
+
function extractImports(content, language) {
|
|
5064
|
+
const imports = [];
|
|
5065
|
+
const lines = toLines(content);
|
|
5066
|
+
for (const { num, text } of lines) {
|
|
5067
|
+
const trimmed = text.trim();
|
|
5068
|
+
if (language === "typescript" || language === "javascript") {
|
|
5069
|
+
const jsMatch = trimmed.match(
|
|
5070
|
+
/^import\s+(?:type\s+)?(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s+from\s+['"]([^'"]+)['"]/
|
|
5071
|
+
);
|
|
5072
|
+
if (jsMatch) {
|
|
5073
|
+
imports.push({
|
|
5074
|
+
line: num,
|
|
5075
|
+
source: jsMatch[1],
|
|
5076
|
+
raw: trimmed,
|
|
5077
|
+
isTypeOnly: trimmed.includes("import type"),
|
|
5078
|
+
isDefault: !trimmed.includes("{")
|
|
5079
|
+
});
|
|
5080
|
+
}
|
|
5081
|
+
const dynMatch = trimmed.match(/import\s*\(\s*['"]([^'"]+)['"]\s*\)/);
|
|
5082
|
+
if (dynMatch) {
|
|
5083
|
+
imports.push({
|
|
5084
|
+
line: num,
|
|
5085
|
+
source: dynMatch[1],
|
|
5086
|
+
raw: trimmed,
|
|
5087
|
+
isTypeOnly: false,
|
|
5088
|
+
isDynamic: true
|
|
5089
|
+
});
|
|
5090
|
+
}
|
|
5091
|
+
const reqMatch = trimmed.match(/(?:const|let|var)\s+[^=]*=\s*require\s*\(\s*['"]([^'"]+)['"]\s*\)/);
|
|
5092
|
+
if (reqMatch) {
|
|
5093
|
+
imports.push({
|
|
5094
|
+
line: num,
|
|
5095
|
+
source: reqMatch[1],
|
|
5096
|
+
raw: trimmed,
|
|
5097
|
+
isTypeOnly: false,
|
|
5098
|
+
isRequire: true
|
|
5099
|
+
});
|
|
4972
5100
|
}
|
|
4973
5101
|
}
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
(
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
symbols.push(dn.text);
|
|
4983
|
-
}
|
|
4984
|
-
for (const id of identifiers) {
|
|
4985
|
-
if (id.text !== "import") {
|
|
4986
|
-
symbols.push(id.text);
|
|
5102
|
+
if (language === "python") {
|
|
5103
|
+
const pyMatch = trimmed.match(/^from\s+([^\s]+)\s+import/);
|
|
5104
|
+
if (pyMatch) {
|
|
5105
|
+
imports.push({ line: num, source: pyMatch[1], raw: trimmed, isTypeOnly: false });
|
|
5106
|
+
}
|
|
5107
|
+
const pyImport = trimmed.match(/^import\s+([^\s]+)/);
|
|
5108
|
+
if (pyImport) {
|
|
5109
|
+
imports.push({ line: num, source: pyImport[1], raw: trimmed, isTypeOnly: false });
|
|
4987
5110
|
}
|
|
4988
5111
|
}
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
isFromImport,
|
|
4995
|
-
line: importNode.startRow + 1,
|
|
4996
|
-
text: importNode.text
|
|
4997
|
-
};
|
|
4998
|
-
}
|
|
4999
|
-
function convertNode(node, parent) {
|
|
5000
|
-
const children = [];
|
|
5001
|
-
const astNode = {
|
|
5002
|
-
type: node.type,
|
|
5003
|
-
text: node.text,
|
|
5004
|
-
startRow: node.startPosition.row,
|
|
5005
|
-
startCol: node.startPosition.column,
|
|
5006
|
-
endRow: node.endPosition.row,
|
|
5007
|
-
endCol: node.endPosition.column,
|
|
5008
|
-
children,
|
|
5009
|
-
parent,
|
|
5010
|
-
fieldName: null
|
|
5011
|
-
};
|
|
5012
|
-
for (let i = 0; i < node.childCount; i++) {
|
|
5013
|
-
const child = node.child(i);
|
|
5014
|
-
if (child) {
|
|
5015
|
-
const converted = convertNode(child, astNode);
|
|
5016
|
-
converted.fieldName = node.fieldNameForChild(i) ?? null;
|
|
5017
|
-
children.push(converted);
|
|
5112
|
+
if (language === "go") {
|
|
5113
|
+
const goMatch = trimmed.match(/"([^"]+)"/);
|
|
5114
|
+
if (trimmed.startsWith("import") && goMatch) {
|
|
5115
|
+
imports.push({ line: num, source: goMatch[1], raw: trimmed, isTypeOnly: false });
|
|
5116
|
+
}
|
|
5018
5117
|
}
|
|
5019
5118
|
}
|
|
5020
|
-
return
|
|
5119
|
+
return imports;
|
|
5021
5120
|
}
|
|
5022
|
-
var
|
|
5023
|
-
|
|
5024
|
-
"src/utils/tree-sitter.ts"() {
|
|
5121
|
+
var init_file_utils = __esm({
|
|
5122
|
+
"src/utils/file-utils.ts"() {
|
|
5025
5123
|
"use strict";
|
|
5026
|
-
parserInstance = null;
|
|
5027
|
-
tsLang = null;
|
|
5028
|
-
tsxLang = null;
|
|
5029
|
-
initPromise = null;
|
|
5030
|
-
initDone = false;
|
|
5031
|
-
initOk = false;
|
|
5032
|
-
pyLang = null;
|
|
5033
|
-
pyInitDone = false;
|
|
5034
|
-
pyInitOk = false;
|
|
5035
|
-
goLang = null;
|
|
5036
|
-
goInitDone = false;
|
|
5037
|
-
goInitOk = false;
|
|
5038
|
-
rustLang = null;
|
|
5039
|
-
rustInitDone = false;
|
|
5040
|
-
rustInitOk = false;
|
|
5041
|
-
phpLang = null;
|
|
5042
|
-
phpInitDone = false;
|
|
5043
|
-
phpInitOk = false;
|
|
5044
|
-
csharpLang = null;
|
|
5045
|
-
csharpInitDone = false;
|
|
5046
|
-
csharpInitOk = false;
|
|
5047
|
-
swiftLang = null;
|
|
5048
|
-
swiftInitDone = false;
|
|
5049
|
-
swiftInitOk = false;
|
|
5050
5124
|
}
|
|
5051
5125
|
});
|
|
5052
5126
|
|
|
@@ -25862,6 +25936,7 @@ import { performance as performance3 } from "node:perf_hooks";
|
|
|
25862
25936
|
async function runScan(context, callbacks) {
|
|
25863
25937
|
const startTotal = performance3.now();
|
|
25864
25938
|
clearFileCache();
|
|
25939
|
+
clearParseCache();
|
|
25865
25940
|
if (context.files?.length) {
|
|
25866
25941
|
await preloadFiles(context.files);
|
|
25867
25942
|
}
|
|
@@ -26039,6 +26114,7 @@ var init_orchestrator = __esm({
|
|
|
26039
26114
|
init_rule_overrides();
|
|
26040
26115
|
init_store();
|
|
26041
26116
|
init_file_cache();
|
|
26117
|
+
init_tree_sitter();
|
|
26042
26118
|
init_registry();
|
|
26043
26119
|
init_suppress();
|
|
26044
26120
|
EXT_TO_LANG = {
|
|
@@ -29579,6 +29655,161 @@ var init_list = __esm({
|
|
|
29579
29655
|
}
|
|
29580
29656
|
});
|
|
29581
29657
|
|
|
29658
|
+
// src/config/json-schema.ts
|
|
29659
|
+
var json_schema_exports = {};
|
|
29660
|
+
__export(json_schema_exports, {
|
|
29661
|
+
generateJsonSchema: () => generateJsonSchema
|
|
29662
|
+
});
|
|
29663
|
+
function generateJsonSchema() {
|
|
29664
|
+
return {
|
|
29665
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
29666
|
+
title: "DeepSlopConfig",
|
|
29667
|
+
description: "Configuration for deep-slop \u2014 deep AI slop detection with 18 AST-powered engines",
|
|
29668
|
+
type: "object",
|
|
29669
|
+
properties: {
|
|
29670
|
+
engines: {
|
|
29671
|
+
type: "object",
|
|
29672
|
+
description: "Enable/disable individual analysis engines",
|
|
29673
|
+
additionalProperties: { type: "boolean" },
|
|
29674
|
+
properties: {
|
|
29675
|
+
"ast-slop": { type: "boolean", description: "AI slop pattern detection" },
|
|
29676
|
+
"import-intelligence": { type: "boolean", description: "Import optimization and barrel analysis" },
|
|
29677
|
+
"dead-flow": { type: "boolean", description: "Dead code and unreachable branch detection" },
|
|
29678
|
+
"type-safety": { type: "boolean", description: "TypeScript type safety analysis" },
|
|
29679
|
+
"syntax-deep": { type: "boolean", description: "Syntax anomaly detection" },
|
|
29680
|
+
"security-deep": { type: "boolean", description: "Security vulnerability scanning" },
|
|
29681
|
+
"arch-constraints": { type: "boolean", description: "Architecture constraint analysis" },
|
|
29682
|
+
"dup-detect": { type: "boolean", description: "Duplicate code detection" },
|
|
29683
|
+
"perf-hints": { type: "boolean", description: "Performance hints" },
|
|
29684
|
+
"i18n-lint": { type: "boolean", description: "Internationalization linting" },
|
|
29685
|
+
"config-lint": { type: "boolean", description: "Configuration validation" },
|
|
29686
|
+
"meta-quality": { type: "boolean", description: "Meta quality scoring and trend analysis" },
|
|
29687
|
+
"lint-external": { type: "boolean", description: "External linter integration (ruff, golangci-lint, clippy)" },
|
|
29688
|
+
"arch-rules": { type: "boolean", description: "User-defined architecture rules" },
|
|
29689
|
+
knip: { type: "boolean", description: "Unused dependency/export detection" },
|
|
29690
|
+
"format-lint": { type: "boolean", description: "Formatting consistency" },
|
|
29691
|
+
"framework-lint": { type: "boolean", description: "Framework-specific rules (Next.js, Tailwind)" },
|
|
29692
|
+
"markup-lint": { type: "boolean", description: "Markup & config quality (JSON, YAML, CSS, HTML, Markdown)" }
|
|
29693
|
+
}
|
|
29694
|
+
},
|
|
29695
|
+
exclude: {
|
|
29696
|
+
type: "array",
|
|
29697
|
+
items: { type: "string" },
|
|
29698
|
+
description: "Glob patterns to exclude from scanning",
|
|
29699
|
+
default: ["node_modules", "dist", "coverage", ".git"]
|
|
29700
|
+
},
|
|
29701
|
+
quality: {
|
|
29702
|
+
type: "object",
|
|
29703
|
+
description: "Quality thresholds",
|
|
29704
|
+
properties: {
|
|
29705
|
+
maxFunctionLoc: { type: "number", default: 50, description: "Max lines per function" },
|
|
29706
|
+
maxFileLoc: { type: "number", default: 300, description: "Max lines per file" },
|
|
29707
|
+
maxNesting: { type: "number", default: 4, description: "Max nesting depth" },
|
|
29708
|
+
maxParams: { type: "number", default: 5, description: "Max function parameters" },
|
|
29709
|
+
maxCyclomatic: { type: "number", default: 10, description: "Max cyclomatic complexity" },
|
|
29710
|
+
maxCoupling: { type: "number", default: 7, description: "Max coupling between modules" }
|
|
29711
|
+
},
|
|
29712
|
+
additionalProperties: true
|
|
29713
|
+
},
|
|
29714
|
+
security: {
|
|
29715
|
+
type: "object",
|
|
29716
|
+
description: "Security engine settings",
|
|
29717
|
+
properties: {
|
|
29718
|
+
audit: { type: "boolean", default: true, description: "Run npm audit" },
|
|
29719
|
+
auditTimeout: { type: "number", default: 3e4, description: "Audit timeout in ms" },
|
|
29720
|
+
owasp: { type: "boolean", default: true, description: "Enable OWASP checks" }
|
|
29721
|
+
},
|
|
29722
|
+
additionalProperties: true
|
|
29723
|
+
},
|
|
29724
|
+
imports: {
|
|
29725
|
+
type: "object",
|
|
29726
|
+
description: "Import intelligence settings",
|
|
29727
|
+
properties: {
|
|
29728
|
+
suggestAlternatives: { type: "boolean", default: true },
|
|
29729
|
+
optimizeBarrels: { type: "boolean", default: true },
|
|
29730
|
+
validateAliases: { type: "boolean", default: true },
|
|
29731
|
+
buildGraph: { type: "boolean", default: true },
|
|
29732
|
+
maxCircularDepth: { type: "number", default: 5 }
|
|
29733
|
+
},
|
|
29734
|
+
additionalProperties: true
|
|
29735
|
+
},
|
|
29736
|
+
types: {
|
|
29737
|
+
type: "object",
|
|
29738
|
+
description: "Type safety settings",
|
|
29739
|
+
properties: {
|
|
29740
|
+
flagAsAny: { type: "boolean", default: true },
|
|
29741
|
+
suggestTypes: { type: "boolean", default: true },
|
|
29742
|
+
flagDoubleAssertion: { type: "boolean", default: true }
|
|
29743
|
+
},
|
|
29744
|
+
additionalProperties: true
|
|
29745
|
+
},
|
|
29746
|
+
deadCode: {
|
|
29747
|
+
type: "object",
|
|
29748
|
+
description: "Dead code detection settings",
|
|
29749
|
+
properties: {
|
|
29750
|
+
unreachableBranches: { type: "boolean", default: true },
|
|
29751
|
+
unusedExports: { type: "boolean", default: true },
|
|
29752
|
+
unusedVariables: { type: "boolean", default: true }
|
|
29753
|
+
},
|
|
29754
|
+
additionalProperties: true
|
|
29755
|
+
},
|
|
29756
|
+
i18n: {
|
|
29757
|
+
type: "object",
|
|
29758
|
+
description: "Internationalization settings",
|
|
29759
|
+
properties: {
|
|
29760
|
+
hardcodedStrings: { type: "boolean", default: true },
|
|
29761
|
+
validateKeys: { type: "boolean", default: true }
|
|
29762
|
+
},
|
|
29763
|
+
additionalProperties: true
|
|
29764
|
+
},
|
|
29765
|
+
scoring: {
|
|
29766
|
+
type: "object",
|
|
29767
|
+
description: "Scoring configuration",
|
|
29768
|
+
properties: {
|
|
29769
|
+
mode: { type: "string", enum: ["logarithmic", "linear"], default: "logarithmic" },
|
|
29770
|
+
smoothing: { type: "number", default: 20 },
|
|
29771
|
+
maxPerRule: { type: "number", default: 40 }
|
|
29772
|
+
}
|
|
29773
|
+
},
|
|
29774
|
+
telemetry: {
|
|
29775
|
+
type: "object",
|
|
29776
|
+
description: "Telemetry settings",
|
|
29777
|
+
properties: {
|
|
29778
|
+
enabled: { type: "boolean", default: false }
|
|
29779
|
+
}
|
|
29780
|
+
},
|
|
29781
|
+
ci: {
|
|
29782
|
+
type: "object",
|
|
29783
|
+
description: "CI quality gate settings",
|
|
29784
|
+
properties: {
|
|
29785
|
+
failBelow: { type: "number", default: 70, description: "Minimum score to pass CI" },
|
|
29786
|
+
format: { type: "string", enum: ["json", "human", "sarif"], default: "json" },
|
|
29787
|
+
failOnErrors: { type: "boolean", default: true }
|
|
29788
|
+
}
|
|
29789
|
+
},
|
|
29790
|
+
rules: {
|
|
29791
|
+
type: "object",
|
|
29792
|
+
description: "Per-rule severity overrides (e.g. ast-slop/narrative-comment: off)",
|
|
29793
|
+
additionalProperties: {
|
|
29794
|
+
type: "string",
|
|
29795
|
+
enum: ["off", "info", "suggestion", "warning", "error"]
|
|
29796
|
+
}
|
|
29797
|
+
},
|
|
29798
|
+
extends: {
|
|
29799
|
+
type: "string",
|
|
29800
|
+
description: "Preset to extend (recommended, strict, minimal)",
|
|
29801
|
+
enum: ["recommended", "strict", "minimal"]
|
|
29802
|
+
}
|
|
29803
|
+
},
|
|
29804
|
+
additionalProperties: false
|
|
29805
|
+
};
|
|
29806
|
+
}
|
|
29807
|
+
var init_json_schema = __esm({
|
|
29808
|
+
"src/config/json-schema.ts"() {
|
|
29809
|
+
"use strict";
|
|
29810
|
+
}
|
|
29811
|
+
});
|
|
29812
|
+
|
|
29582
29813
|
// node_modules/.pnpm/commander@14.0.3/node_modules/commander/esm.mjs
|
|
29583
29814
|
var import_index = __toESM(require_commander(), 1);
|
|
29584
29815
|
var {
|
|
@@ -29676,7 +29907,7 @@ function computeExitCode(options) {
|
|
|
29676
29907
|
init_formatter();
|
|
29677
29908
|
|
|
29678
29909
|
// src/version.ts
|
|
29679
|
-
var APP_VERSION = "1.
|
|
29910
|
+
var APP_VERSION = "1.6.0";
|
|
29680
29911
|
|
|
29681
29912
|
// src/output/sarif.ts
|
|
29682
29913
|
function mapSeverity4(sev) {
|
|
@@ -32989,6 +33220,20 @@ program2.command("badge").description("Generate a shields.io badge for your deep
|
|
|
32989
33220
|
console.log("");
|
|
32990
33221
|
}
|
|
32991
33222
|
});
|
|
33223
|
+
program2.command("schema").description("Output JSON Schema for .deep-slop/config.yml (for IDE autocomplete)").option("--output <path>", "Write schema to file instead of stdout").action(async (opts) => {
|
|
33224
|
+
const { generateJsonSchema: generateJsonSchema2 } = await Promise.resolve().then(() => (init_json_schema(), json_schema_exports));
|
|
33225
|
+
const schema = generateJsonSchema2();
|
|
33226
|
+
if (opts.output) {
|
|
33227
|
+
const { writeFileSync: writeFileSync11 } = await import("node:fs");
|
|
33228
|
+
const { resolve: resolvePath } = await import("node:path");
|
|
33229
|
+
const outPath = resolvePath(opts.output);
|
|
33230
|
+
writeFileSync11(outPath, JSON.stringify(schema, null, 2) + "\n");
|
|
33231
|
+
process.stderr.write(` \u2714 Schema written to ${outPath}
|
|
33232
|
+
`);
|
|
33233
|
+
} else {
|
|
33234
|
+
console.log(JSON.stringify(schema, null, 2));
|
|
33235
|
+
}
|
|
33236
|
+
});
|
|
32992
33237
|
program2.command("discover").description("Analyze project: languages, frameworks, package manager, linters, tests, CI").argument("[path]", "project directory", ".").option("--json", "Output as JSON").action(async (path2, opts) => {
|
|
32993
33238
|
const rootDir = resolve13(path2);
|
|
32994
33239
|
process.stderr.write(`
|