@iris-code/core 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.
Files changed (94) hide show
  1. package/README.md +38 -0
  2. package/dist/config.d.ts +147 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +550 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/csharp/analyser.d.ts +14 -0
  7. package/dist/csharp/analyser.d.ts.map +1 -0
  8. package/dist/csharp/analyser.js +436 -0
  9. package/dist/csharp/analyser.js.map +1 -0
  10. package/dist/csharp/lexer.d.ts +29 -0
  11. package/dist/csharp/lexer.d.ts.map +1 -0
  12. package/dist/csharp/lexer.js +182 -0
  13. package/dist/csharp/lexer.js.map +1 -0
  14. package/dist/duplicates.d.ts +53 -0
  15. package/dist/duplicates.d.ts.map +1 -0
  16. package/dist/duplicates.js +491 -0
  17. package/dist/duplicates.js.map +1 -0
  18. package/dist/fileAnalyser.d.ts +4 -0
  19. package/dist/fileAnalyser.d.ts.map +1 -0
  20. package/dist/fileAnalyser.js +8 -0
  21. package/dist/fileAnalyser.js.map +1 -0
  22. package/dist/fileNaming.d.ts +68 -0
  23. package/dist/fileNaming.d.ts.map +1 -0
  24. package/dist/fileNaming.js +343 -0
  25. package/dist/fileNaming.js.map +1 -0
  26. package/dist/gate.d.ts +49 -0
  27. package/dist/gate.d.ts.map +1 -0
  28. package/dist/gate.js +242 -0
  29. package/dist/gate.js.map +1 -0
  30. package/dist/go/analyser.d.ts +5 -0
  31. package/dist/go/analyser.d.ts.map +1 -0
  32. package/dist/go/analyser.js +576 -0
  33. package/dist/go/analyser.js.map +1 -0
  34. package/dist/guards.d.ts +16 -0
  35. package/dist/guards.d.ts.map +1 -0
  36. package/dist/guards.js +355 -0
  37. package/dist/guards.js.map +1 -0
  38. package/dist/index.d.ts +22 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +110 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/languages.d.ts +46 -0
  43. package/dist/languages.d.ts.map +1 -0
  44. package/dist/languages.js +155 -0
  45. package/dist/languages.js.map +1 -0
  46. package/dist/lines.d.ts +9 -0
  47. package/dist/lines.d.ts.map +1 -0
  48. package/dist/lines.js +58 -0
  49. package/dist/lines.js.map +1 -0
  50. package/dist/python/analyser.d.ts +5 -0
  51. package/dist/python/analyser.d.ts.map +1 -0
  52. package/dist/python/analyser.js +630 -0
  53. package/dist/python/analyser.js.map +1 -0
  54. package/dist/qualitySignals.d.ts +30 -0
  55. package/dist/qualitySignals.d.ts.map +1 -0
  56. package/dist/qualitySignals.js +101 -0
  57. package/dist/qualitySignals.js.map +1 -0
  58. package/dist/ruby/analyser.d.ts +5 -0
  59. package/dist/ruby/analyser.d.ts.map +1 -0
  60. package/dist/ruby/analyser.js +450 -0
  61. package/dist/ruby/analyser.js.map +1 -0
  62. package/dist/scoring.d.ts +4 -0
  63. package/dist/scoring.d.ts.map +1 -0
  64. package/dist/scoring.js +37 -0
  65. package/dist/scoring.js.map +1 -0
  66. package/dist/secrets.d.ts +5 -0
  67. package/dist/secrets.d.ts.map +1 -0
  68. package/dist/secrets.js +245 -0
  69. package/dist/secrets.js.map +1 -0
  70. package/dist/securityContext.d.ts +2 -0
  71. package/dist/securityContext.d.ts.map +1 -0
  72. package/dist/securityContext.js +16 -0
  73. package/dist/securityContext.js.map +1 -0
  74. package/dist/sfc.d.ts +32 -0
  75. package/dist/sfc.d.ts.map +1 -0
  76. package/dist/sfc.js +228 -0
  77. package/dist/sfc.js.map +1 -0
  78. package/dist/slop.d.ts +37 -0
  79. package/dist/slop.d.ts.map +1 -0
  80. package/dist/slop.js +81 -0
  81. package/dist/slop.js.map +1 -0
  82. package/dist/suppressions.d.ts +19 -0
  83. package/dist/suppressions.d.ts.map +1 -0
  84. package/dist/suppressions.js +152 -0
  85. package/dist/suppressions.js.map +1 -0
  86. package/dist/ts/analyser.d.ts +4 -0
  87. package/dist/ts/analyser.d.ts.map +1 -0
  88. package/dist/ts/analyser.js +769 -0
  89. package/dist/ts/analyser.js.map +1 -0
  90. package/dist/types.d.ts +139 -0
  91. package/dist/types.d.ts.map +1 -0
  92. package/dist/types.js +46 -0
  93. package/dist/types.js.map +1 -0
  94. package/package.json +43 -0
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LANGUAGE_OVERRIDE_KEYS = exports.LANGUAGE_OVERRIDE_OBJECT_KEYS = exports.LANGUAGE_OVERRIDE_NUMBER_KEYS = exports.LANGUAGE_KEYS = exports.ANALYSABLE_EXTS = exports.ANALYSABLE_FILENAMES = exports.ANALYSABLE_EXTENSIONS = exports.SFC_EXTENSIONS = exports.LANGUAGE_REGISTRY = exports.RUBY_SPECIAL_FILENAMES = void 0;
4
+ exports.fileExtension = fileExtension;
5
+ exports.isAnalysableFile = isAnalysableFile;
6
+ exports.isLanguageKey = isLanguageKey;
7
+ exports.languageLabel = languageLabel;
8
+ exports.languageKeyForFile = languageKeyForFile;
9
+ exports.isLanguageOverrideKey = isLanguageOverrideKey;
10
+ exports.resolveLanguageOverride = resolveLanguageOverride;
11
+ exports.resolveConfigForFile = resolveConfigForFile;
12
+ exports.resolveLanguageGateCaps = resolveLanguageGateCaps;
13
+ const sfc_1 = require("./sfc");
14
+ exports.RUBY_SPECIAL_FILENAMES = [
15
+ 'appfile', 'berksfile', 'brewfile', 'capfile', 'dangerfile', 'deliverfile',
16
+ 'fastfile', 'gemfile', 'guardfile', 'gymfile', 'matchfile', 'podfile',
17
+ 'pluginfile', 'puppetfile', 'rakefile', 'scanfile', 'snapfile', 'thorfile',
18
+ 'vagrantfile', '.irbrc', '.pryrc',
19
+ ];
20
+ exports.LANGUAGE_REGISTRY = [
21
+ { key: 'typescript', label: 'TypeScript', extensions: ['.ts', '.tsx', '.mts', '.cts'] },
22
+ { key: 'javascript', label: 'JavaScript', extensions: ['.js', '.jsx', '.mjs', '.cjs'] },
23
+ { key: 'go', label: 'Go', extensions: ['.go'] },
24
+ { key: 'python', label: 'Python', extensions: ['.py', '.pyw'] },
25
+ {
26
+ key: 'ruby',
27
+ label: 'Ruby',
28
+ extensions: ['.rb', '.rbw', '.rake', '.gemspec', '.ru', '.thor', '.builder', '.jbuilder', '.rabl', '.arb', '.podspec', '.erb', '.rhtml'],
29
+ fileNames: [...exports.RUBY_SPECIAL_FILENAMES],
30
+ },
31
+ { key: 'csharp', label: 'C#', extensions: ['.cs', '.csproj'] },
32
+ ];
33
+ exports.SFC_EXTENSIONS = ['.vue', '.svelte'];
34
+ exports.ANALYSABLE_EXTENSIONS = [
35
+ ...exports.LANGUAGE_REGISTRY.flatMap(entry => entry.extensions),
36
+ ...exports.SFC_EXTENSIONS,
37
+ ];
38
+ exports.ANALYSABLE_FILENAMES = exports.LANGUAGE_REGISTRY.flatMap(entry => entry.fileNames ?? []);
39
+ exports.ANALYSABLE_EXTS = new Set(exports.ANALYSABLE_EXTENSIONS);
40
+ function fileExtension(filePath) {
41
+ const base = filePath.replace(/\\/g, '/').slice(filePath.replace(/\\/g, '/').lastIndexOf('/') + 1);
42
+ const dot = base.lastIndexOf('.');
43
+ return dot === -1 ? '' : base.slice(dot).toLowerCase();
44
+ }
45
+ function isAnalysableFile(filePath) {
46
+ const lower = filePath.toLowerCase();
47
+ if (/\.d\.(?:ts|mts|cts)$/.test(lower))
48
+ return false;
49
+ const base = lower.replace(/\\/g, '/').split('/').pop() ?? lower;
50
+ return exports.ANALYSABLE_EXTS.has(fileExtension(lower)) ||
51
+ exports.LANGUAGE_REGISTRY.some(entry => entry.fileNames?.includes(base));
52
+ }
53
+ exports.LANGUAGE_KEYS = exports.LANGUAGE_REGISTRY.map(entry => entry.key);
54
+ function isLanguageKey(value) {
55
+ return exports.LANGUAGE_KEYS.includes(value);
56
+ }
57
+ function languageLabel(key) {
58
+ return exports.LANGUAGE_REGISTRY.find(entry => entry.key === key)?.label ?? key;
59
+ }
60
+ // Mirrors detectLanguage in guards.ts (unknown extensions fall back to
61
+ // typescript there too) so override resolution and analysis can never disagree
62
+ // about which language a file belongs to.
63
+ function languageKeyForFile(filePath, source) {
64
+ const lower = filePath.toLowerCase();
65
+ if (lower.endsWith('.vue') || lower.endsWith('.svelte')) {
66
+ return source ? (0, sfc_1.extractSfcScripts)(source, filePath).language : 'javascript';
67
+ }
68
+ const base = lower.replace(/\\/g, '/').split('/').pop() ?? lower;
69
+ for (const entry of exports.LANGUAGE_REGISTRY) {
70
+ if (entry.extensions.some(ext => lower.endsWith(ext)) || entry.fileNames?.includes(base))
71
+ return entry.key;
72
+ }
73
+ return 'typescript';
74
+ }
75
+ exports.LANGUAGE_OVERRIDE_NUMBER_KEYS = [
76
+ 'functionLengthThreshold',
77
+ 'fileLengthThreshold',
78
+ 'maxFunctionsPerFile',
79
+ 'maxImportsPerFile',
80
+ 'maxParameterCount',
81
+ 'complexityThreshold',
82
+ 'gateMaxSmellsPerFile',
83
+ 'gateMaxSuppressions',
84
+ ];
85
+ exports.LANGUAGE_OVERRIDE_OBJECT_KEYS = ['healthScoreWeights', 'severityOverrides', 'fileNaming'];
86
+ exports.LANGUAGE_OVERRIDE_KEYS = [
87
+ ...exports.LANGUAGE_OVERRIDE_NUMBER_KEYS,
88
+ ...exports.LANGUAGE_OVERRIDE_OBJECT_KEYS,
89
+ ];
90
+ function isLanguageOverrideKey(key) {
91
+ return exports.LANGUAGE_OVERRIDE_KEYS.includes(key);
92
+ }
93
+ function resolveLanguageOverride(filePath, languages, source) {
94
+ if (!languages)
95
+ return undefined;
96
+ const override = languages[languageKeyForFile(filePath, source)];
97
+ if (!override || Object.keys(override).length === 0)
98
+ return undefined;
99
+ return override;
100
+ }
101
+ // The single resolve-for-file implementation (Phase 5.10). Both the extension
102
+ // and the CLI analyse through core's analyseFile, which calls this - so the
103
+ // sidebar, gate, hooks, and CI can never disagree on which threshold applied.
104
+ // Resolution order: language override > base (project config > VS Code
105
+ // settings > defaults, already merged by the caller's config resolver).
106
+ function resolveConfigForFile(filePath, base, source) {
107
+ const override = resolveLanguageOverride(filePath, base.languages, source);
108
+ if (!override)
109
+ return base;
110
+ const { healthScoreWeights, severityOverrides, fileNaming, gateMaxSmellsPerFile, gateMaxSuppressions, ...thresholds } = override;
111
+ void gateMaxSmellsPerFile;
112
+ void gateMaxSuppressions;
113
+ return {
114
+ ...base,
115
+ ...thresholds,
116
+ fileNaming: mergeFileNamingPolicies(base.fileNaming, fileNaming),
117
+ healthScoreWeights: {
118
+ ...base.healthScoreWeights,
119
+ ...(healthScoreWeights ?? {}),
120
+ },
121
+ severityOverrides: {
122
+ ...base.severityOverrides,
123
+ ...(severityOverrides ?? {}),
124
+ },
125
+ };
126
+ }
127
+ /**
128
+ * Preserve top-level path overrides when a legacy language policy is selected.
129
+ * Workspace ignores are absolute exclusions, while language ignores remain
130
+ * additive for backwards compatibility with existing language blocks.
131
+ */
132
+ function mergeFileNamingPolicies(workspace, language) {
133
+ if (!language)
134
+ return workspace;
135
+ return {
136
+ ...language,
137
+ ignore: [...new Set([...(workspace?.ignore ?? []), ...(language.ignore ?? [])])],
138
+ ...(workspace?.overrides ? { overrides: workspace.overrides } : {}),
139
+ };
140
+ }
141
+ // Per-file gate caps from a language block. Consumed by scan orchestrators
142
+ // when building GateFileEntry lists so evaluateGate can apply the cap that
143
+ // actually governs each file.
144
+ function resolveLanguageGateCaps(filePath, languages, source) {
145
+ const override = resolveLanguageOverride(filePath, languages, source);
146
+ if (!override)
147
+ return undefined;
148
+ const caps = {};
149
+ if (override.gateMaxSmellsPerFile !== undefined)
150
+ caps.maxSmellsPerFile = override.gateMaxSmellsPerFile;
151
+ if (override.gateMaxSuppressions !== undefined)
152
+ caps.maxSuppressions = override.gateMaxSuppressions;
153
+ return Object.keys(caps).length > 0 ? caps : undefined;
154
+ }
155
+ //# sourceMappingURL=languages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"languages.js","sourceRoot":"","sources":["../src/languages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 1-based line number containing `index`.
3
+ *
4
+ * Matches the byte-scan it replaces exactly, including the edge cases: a negative
5
+ * or zero index is line 1, and an index past the end reports the last line rather
6
+ * than throwing.
7
+ */
8
+ export declare function lineOf(source: string, index: number): number;
9
+ //# sourceMappingURL=lines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../src/lines.ts"],"names":[],"mappings":"AAuCA;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAY5D"}
package/dist/lines.js ADDED
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ // Offset -> line-number resolution, shared by every analyser.
3
+ //
4
+ // Each analyser previously carried its own `lineOf(source, index)` that counted
5
+ // newlines from position 0 on every call. That is O(n) per finding, so a file with
6
+ // F findings costs O(n x F) - quadratic, and the analyser runs on files from repos
7
+ // we did not write. Measured 2026-08-10: a 40k-line Ruby file with 8k findings took
8
+ // 103 SECONDS, and a 48k-line TypeScript file spent 95% of its 12s in this one
9
+ // function. It is the same availability class as the 2026-08-04 METHOD_RE finding,
10
+ // reached through a different path - counting rather than backtracking.
11
+ //
12
+ // The index is built once per source string and cached, so repeated calls are a
13
+ // binary search instead of a scan.
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.lineOf = lineOf;
16
+ // Analysers process one file at a time, so a single-entry cache hits on every call
17
+ // after the first. The `===` guard is pointer-fast when the same string reference
18
+ // comes back, and a miss costs one O(n) rebuild - never worse than the per-call
19
+ // scan this replaces.
20
+ let cached = null;
21
+ function buildLineIndex(source) {
22
+ const offsets = [0];
23
+ for (let i = 0; i < source.length; i++) {
24
+ if (source[i] === '\n')
25
+ offsets.push(i + 1);
26
+ }
27
+ return { source, offsets };
28
+ }
29
+ function indexFor(source) {
30
+ if (cached !== null && cached.source === source)
31
+ return cached;
32
+ cached = buildLineIndex(source);
33
+ return cached;
34
+ }
35
+ /**
36
+ * 1-based line number containing `index`.
37
+ *
38
+ * Matches the byte-scan it replaces exactly, including the edge cases: a negative
39
+ * or zero index is line 1, and an index past the end reports the last line rather
40
+ * than throwing.
41
+ */
42
+ function lineOf(source, index) {
43
+ if (index <= 0)
44
+ return 1;
45
+ const { offsets } = indexFor(source);
46
+ // Largest line whose start offset is <= index.
47
+ let low = 0;
48
+ let high = offsets.length - 1;
49
+ while (low < high) {
50
+ const mid = (low + high + 1) >> 1;
51
+ if (offsets[mid] <= index)
52
+ low = mid;
53
+ else
54
+ high = mid - 1;
55
+ }
56
+ return low + 1;
57
+ }
58
+ //# sourceMappingURL=lines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lines.js","sourceRoot":"","sources":["../src/lines.ts"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,EAAE;AACF,gFAAgF;AAChF,mFAAmF;AACnF,mFAAmF;AACnF,oFAAoF;AACpF,+EAA+E;AAC/E,mFAAmF;AACnF,wEAAwE;AACxE,EAAE;AACF,gFAAgF;AAChF,mCAAmC;;AAmCnC,wBAYC;AAvCD,mFAAmF;AACnF,kFAAkF;AAClF,gFAAgF;AAChF,sBAAsB;AACtB,IAAI,MAAM,GAAqB,IAAI,CAAA;AAEnC,SAAS,cAAc,CAAC,MAAc;IACpC,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,CAAA;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAC7C,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;AAC5B,CAAC;AAED,SAAS,QAAQ,CAAC,MAAc;IAC9B,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,MAAM,CAAA;IAC9D,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAA;IAC/B,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,MAAM,CAAC,MAAc,EAAE,KAAa;IAClD,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IACxB,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IACpC,+CAA+C;IAC/C,IAAI,GAAG,GAAG,CAAC,CAAA;IACX,IAAI,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAA;IAC7B,OAAO,GAAG,GAAG,IAAI,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK;YAAE,GAAG,GAAG,GAAG,CAAA;;YAC/B,IAAI,GAAG,GAAG,GAAG,CAAC,CAAA;IACrB,CAAC;IACD,OAAO,GAAG,GAAG,CAAC,CAAA;AAChB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { IrisConfig } from '../config';
2
+ import { LanguageAnalysis } from '../types';
3
+ export declare function extractPyThirdPartyImports(source: string): string[];
4
+ export declare function analysePython(source: string, config: IrisConfig, filePath?: string): LanguageAnalysis;
5
+ //# sourceMappingURL=analyser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyser.d.ts","sourceRoot":"","sources":["../../src/python/analyser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAGtC,OAAO,EAML,gBAAgB,EACjB,MAAM,UAAU,CAAA;AAoOjB,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BnE;AA2XD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,SAAK,GAAG,gBAAgB,CAqCjG"}