pi-lens 1.3.7 → 1.3.8
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.
|
@@ -238,6 +238,7 @@ function long(): number {
|
|
|
238
238
|
maintainabilityIndex: 75,
|
|
239
239
|
linesOfCode: 100,
|
|
240
240
|
commentLines: 10,
|
|
241
|
+
codeEntropy: 0.5,
|
|
241
242
|
};
|
|
242
243
|
|
|
243
244
|
const formatted = client.formatMetrics(metrics);
|
|
@@ -259,6 +260,7 @@ function long(): number {
|
|
|
259
260
|
maintainabilityIndex: 25,
|
|
260
261
|
linesOfCode: 500,
|
|
261
262
|
commentLines: 10,
|
|
263
|
+
codeEntropy: 0.5,
|
|
262
264
|
};
|
|
263
265
|
|
|
264
266
|
const formatted = client.formatMetrics(metrics);
|
|
@@ -34,6 +34,7 @@ export interface FileComplexity {
|
|
|
34
34
|
maintainabilityIndex: number; // 0-100
|
|
35
35
|
linesOfCode: number;
|
|
36
36
|
commentLines: number;
|
|
37
|
+
codeEntropy: number; // Shannon entropy (0-1, lower = more predictable)
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export interface FunctionMetrics {
|
|
@@ -195,6 +196,9 @@ export class ComplexityClient {
|
|
|
195
196
|
commentLines
|
|
196
197
|
);
|
|
197
198
|
|
|
199
|
+
// Code Entropy (Shannon entropy of code tokens)
|
|
200
|
+
const codeEntropy = this.calculateCodeEntropy(content);
|
|
201
|
+
|
|
198
202
|
return {
|
|
199
203
|
filePath: path.relative(process.cwd(), absolutePath),
|
|
200
204
|
maxNestingDepth,
|
|
@@ -208,6 +212,7 @@ export class ComplexityClient {
|
|
|
208
212
|
maintainabilityIndex: Math.round(maintainabilityIndex * 10) / 10,
|
|
209
213
|
linesOfCode: codeLines,
|
|
210
214
|
commentLines,
|
|
215
|
+
codeEntropy: Math.round(codeEntropy * 1000) / 1000,
|
|
211
216
|
};
|
|
212
217
|
} catch (err: any) {
|
|
213
218
|
this.log(`Analysis error for ${filePath}: ${err.message}`);
|
|
@@ -242,6 +247,13 @@ export class ComplexityClient {
|
|
|
242
247
|
parts.push(` Max nesting: ${metrics.maxNestingDepth} levels (consider extracting)`);
|
|
243
248
|
}
|
|
244
249
|
|
|
250
|
+
// Code entropy (0-1, lower = more predictable)
|
|
251
|
+
if (metrics.codeEntropy > 0.8) {
|
|
252
|
+
parts.push(` Entropy: ${metrics.codeEntropy} (high — code may be unpredictable/AI-generated)`);
|
|
253
|
+
} else if (metrics.codeEntropy < 0.3) {
|
|
254
|
+
parts.push(` Entropy: ${metrics.codeEntropy} (low — repetitive patterns detected)`);
|
|
255
|
+
}
|
|
256
|
+
|
|
245
257
|
// Function length
|
|
246
258
|
if (metrics.maxFunctionLength > 50) {
|
|
247
259
|
parts.push(` Longest function: ${metrics.maxFunctionLength} lines (avg: ${metrics.avgFunctionLength})`);
|
|
@@ -491,6 +503,45 @@ export class ComplexityClient {
|
|
|
491
503
|
return totalOps * Math.log2(uniqueOps);
|
|
492
504
|
}
|
|
493
505
|
|
|
506
|
+
/**
|
|
507
|
+
* Calculate Shannon entropy of code tokens
|
|
508
|
+
* Measures predictability/uniformity of code
|
|
509
|
+
* 0 = completely uniform, 1 = maximum entropy
|
|
510
|
+
*/
|
|
511
|
+
private calculateCodeEntropy(sourceText: string): number {
|
|
512
|
+
// Tokenize by splitting on whitespace and common delimiters
|
|
513
|
+
const tokens = sourceText
|
|
514
|
+
.replace(/\/\/.*/g, "") // Remove single-line comments
|
|
515
|
+
.replace(/\/\*[\s\S]*?\*\//g, "") // Remove multi-line comments
|
|
516
|
+
.replace(/["'`][^"'`]*["'`]/g, "STR") // Normalize strings
|
|
517
|
+
.replace(/\b\d+(\.\d+)?\b/g, "NUM") // Normalize numbers
|
|
518
|
+
.split(/[\s\n\r\t,;:()[\]{}=<>!&|+\-*/%^~?]+/)
|
|
519
|
+
.filter(t => t.length > 0);
|
|
520
|
+
|
|
521
|
+
if (tokens.length === 0) return 0;
|
|
522
|
+
|
|
523
|
+
// Count token frequencies
|
|
524
|
+
const freq = new Map<string, number>();
|
|
525
|
+
for (const token of tokens) {
|
|
526
|
+
freq.set(token, (freq.get(token) || 0) + 1);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Calculate Shannon entropy: H = -sum(p * log2(p))
|
|
530
|
+
let entropy = 0;
|
|
531
|
+
for (const count of freq.values()) {
|
|
532
|
+
const p = count / tokens.length;
|
|
533
|
+
if (p > 0) {
|
|
534
|
+
entropy -= p * Math.log2(p);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Normalize to 0-1 range
|
|
539
|
+
const maxEntropy = Math.log2(freq.size);
|
|
540
|
+
if (maxEntropy === 0) return 0;
|
|
541
|
+
|
|
542
|
+
return Math.min(1, entropy / maxEntropy);
|
|
543
|
+
}
|
|
544
|
+
|
|
494
545
|
private isKeyword(text: string): boolean {
|
|
495
546
|
const keywords = new Set([
|
|
496
547
|
"if", "else", "for", "while", "do", "switch", "case", "break", "continue",
|
package/package.json
CHANGED