slopbrick 0.25.1 → 0.26.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/engine/worker.cjs +343 -6
- package/dist/engine/worker.js +343 -6
- package/dist/index.cjs +392 -10
- package/dist/index.js +392 -10
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -36,7 +36,7 @@ var VERSION;
|
|
|
36
36
|
var init_header = __esm({
|
|
37
37
|
"src/types/_header.ts"() {
|
|
38
38
|
"use strict";
|
|
39
|
-
VERSION = "0.
|
|
39
|
+
VERSION = "0.26.0";
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -30704,6 +30704,55 @@ var init_arraylist_vs_linkedlist = __esm({
|
|
|
30704
30704
|
}
|
|
30705
30705
|
});
|
|
30706
30706
|
|
|
30707
|
+
// src/rules/java/builder-overuse.ts
|
|
30708
|
+
var BUILDER_ANNOTATION_REGEX, FIELD_DECL_REGEX, DEFAULT_FIELD_COUNT_CAP, javaBuilderOveruseRule;
|
|
30709
|
+
var init_builder_overuse = __esm({
|
|
30710
|
+
"src/rules/java/builder-overuse.ts"() {
|
|
30711
|
+
"use strict";
|
|
30712
|
+
init_rule();
|
|
30713
|
+
BUILDER_ANNOTATION_REGEX = /@Builder\b/;
|
|
30714
|
+
FIELD_DECL_REGEX = /(?:private|public|protected)\s+(?:final\s+)?[\w<>,\s]+\s+(\w+)\s*[=;]/g;
|
|
30715
|
+
DEFAULT_FIELD_COUNT_CAP = 3;
|
|
30716
|
+
javaBuilderOveruseRule = createRule({
|
|
30717
|
+
id: "java/builder-overuse",
|
|
30718
|
+
category: "typo",
|
|
30719
|
+
severity: "low",
|
|
30720
|
+
aiSpecific: true,
|
|
30721
|
+
description: "@Builder on a class with few fields \u2014 plain constructor is simpler",
|
|
30722
|
+
create(_context) {
|
|
30723
|
+
return { fieldCountCap: DEFAULT_FIELD_COUNT_CAP };
|
|
30724
|
+
},
|
|
30725
|
+
analyze(context, facts) {
|
|
30726
|
+
const issues = [];
|
|
30727
|
+
const source = facts.v2?._source;
|
|
30728
|
+
if (!source) return issues;
|
|
30729
|
+
if (!/\.java$/i.test(facts.filePath)) return issues;
|
|
30730
|
+
BUILDER_ANNOTATION_REGEX.lastIndex = 0;
|
|
30731
|
+
const builderMatch = BUILDER_ANNOTATION_REGEX.exec(source);
|
|
30732
|
+
if (!builderMatch) return issues;
|
|
30733
|
+
const firstBuilderLine = source.slice(0, builderMatch.index).split("\n").length;
|
|
30734
|
+
FIELD_DECL_REGEX.lastIndex = 0;
|
|
30735
|
+
let fieldCount = 0;
|
|
30736
|
+
while (FIELD_DECL_REGEX.exec(source) !== null) {
|
|
30737
|
+
fieldCount++;
|
|
30738
|
+
}
|
|
30739
|
+
if (fieldCount > context.fieldCountCap) return issues;
|
|
30740
|
+
issues.push({
|
|
30741
|
+
ruleId: "java/builder-overuse",
|
|
30742
|
+
category: "typo",
|
|
30743
|
+
severity: "low",
|
|
30744
|
+
aiSpecific: true,
|
|
30745
|
+
message: `@Builder on a class with ${fieldCount} field(s) \u2014 plain constructor is simpler`,
|
|
30746
|
+
line: firstBuilderLine,
|
|
30747
|
+
column: 1,
|
|
30748
|
+
advice: "Use a plain constructor for classes with \u2264 3 fields. AI agents default to @Builder because their training data emphasizes the pattern. Builder adds Lombok dependency and a Builder inner class for every annotated class. Reference: java/builder-overuse v0.26.0."
|
|
30749
|
+
});
|
|
30750
|
+
return issues;
|
|
30751
|
+
}
|
|
30752
|
+
});
|
|
30753
|
+
}
|
|
30754
|
+
});
|
|
30755
|
+
|
|
30707
30756
|
// src/rules/java/empty-catch-block.ts
|
|
30708
30757
|
var SINGLE_LINE_EMPTY_CATCH_REGEX, javaEmptyCatchBlockRule;
|
|
30709
30758
|
var init_empty_catch_block = __esm({
|
|
@@ -30746,6 +30795,65 @@ var init_empty_catch_block = __esm({
|
|
|
30746
30795
|
}
|
|
30747
30796
|
});
|
|
30748
30797
|
|
|
30798
|
+
// src/rules/java/immutable-collection-preference.ts
|
|
30799
|
+
var IMMUTABLE_REGEX, MUTABLE_REGEX, DEFAULT_IMMUTABLE_THRESHOLD, DEFAULT_MUTABLE_CAP, javaImmutableCollectionPreferenceRule;
|
|
30800
|
+
var init_immutable_collection_preference = __esm({
|
|
30801
|
+
"src/rules/java/immutable-collection-preference.ts"() {
|
|
30802
|
+
"use strict";
|
|
30803
|
+
init_rule();
|
|
30804
|
+
IMMUTABLE_REGEX = /\b(List|Map|Set)\.of\s*\(/g;
|
|
30805
|
+
MUTABLE_REGEX = /new\s+(ArrayList|HashMap|HashSet|LinkedList|TreeMap)\s*[<(]/g;
|
|
30806
|
+
DEFAULT_IMMUTABLE_THRESHOLD = 5;
|
|
30807
|
+
DEFAULT_MUTABLE_CAP = 1;
|
|
30808
|
+
javaImmutableCollectionPreferenceRule = createRule({
|
|
30809
|
+
id: "java/immutable-collection-preference",
|
|
30810
|
+
category: "typo",
|
|
30811
|
+
severity: "low",
|
|
30812
|
+
aiSpecific: true,
|
|
30813
|
+
description: "Immutable factory method over-use \u2014 prefer mutable when collection will be modified",
|
|
30814
|
+
create(_context) {
|
|
30815
|
+
return {
|
|
30816
|
+
immutableThreshold: DEFAULT_IMMUTABLE_THRESHOLD,
|
|
30817
|
+
mutableCap: DEFAULT_MUTABLE_CAP
|
|
30818
|
+
};
|
|
30819
|
+
},
|
|
30820
|
+
analyze(context, facts) {
|
|
30821
|
+
const issues = [];
|
|
30822
|
+
const source = facts.v2?._source;
|
|
30823
|
+
if (!source) return issues;
|
|
30824
|
+
if (!/\.java$/i.test(facts.filePath)) return issues;
|
|
30825
|
+
IMMUTABLE_REGEX.lastIndex = 0;
|
|
30826
|
+
let immutableCount = 0;
|
|
30827
|
+
let firstIdx = 0;
|
|
30828
|
+
let m;
|
|
30829
|
+
while ((m = IMMUTABLE_REGEX.exec(source)) !== null) {
|
|
30830
|
+
immutableCount++;
|
|
30831
|
+
if (firstIdx === 0) firstIdx = m.index;
|
|
30832
|
+
}
|
|
30833
|
+
if (immutableCount < context.immutableThreshold) return issues;
|
|
30834
|
+
MUTABLE_REGEX.lastIndex = 0;
|
|
30835
|
+
let mutableCount = 0;
|
|
30836
|
+
while ((m = MUTABLE_REGEX.exec(source)) !== null) {
|
|
30837
|
+
mutableCount++;
|
|
30838
|
+
}
|
|
30839
|
+
if (mutableCount > context.mutableCap) return issues;
|
|
30840
|
+
const line = source.slice(0, firstIdx).split("\n").length;
|
|
30841
|
+
issues.push({
|
|
30842
|
+
ruleId: "java/immutable-collection-preference",
|
|
30843
|
+
category: "typo",
|
|
30844
|
+
severity: "low",
|
|
30845
|
+
aiSpecific: true,
|
|
30846
|
+
message: `${immutableCount} immutable factory calls (List/Map/Set.of) with only ${mutableCount} mutable collection \u2014 likely over-preferring immutability`,
|
|
30847
|
+
line,
|
|
30848
|
+
column: 1,
|
|
30849
|
+
advice: "Prefer mutable collections (new ArrayList<>()) when the collection will be modified later. AI agents default to List.of/Map.of/Set.of because their training data emphasizes functional-style Java. Reference: java/immutable-collection-preference v0.26.0."
|
|
30850
|
+
});
|
|
30851
|
+
return issues;
|
|
30852
|
+
}
|
|
30853
|
+
});
|
|
30854
|
+
}
|
|
30855
|
+
});
|
|
30856
|
+
|
|
30749
30857
|
// src/rules/java/legacy-date-api.ts
|
|
30750
30858
|
var LEGACY_IMPORT_REGEX, LEGACY_USAGE_REGEX, CALENDAR_GET_INSTANCE_REGEX, javaLegacyDateApiRule;
|
|
30751
30859
|
var init_legacy_date_api = __esm({
|
|
@@ -30822,6 +30930,59 @@ var init_legacy_date_api = __esm({
|
|
|
30822
30930
|
}
|
|
30823
30931
|
});
|
|
30824
30932
|
|
|
30933
|
+
// src/rules/java/optional-overuse.ts
|
|
30934
|
+
var OR_ELSE_THROW_REGEX, NULL_CHECK_REGEX, DEFAULT_THRESHOLD, javaOptionalOveruseRule;
|
|
30935
|
+
var init_optional_overuse = __esm({
|
|
30936
|
+
"src/rules/java/optional-overuse.ts"() {
|
|
30937
|
+
"use strict";
|
|
30938
|
+
init_rule();
|
|
30939
|
+
OR_ELSE_THROW_REGEX = /\.orElseThrow\s*\(/g;
|
|
30940
|
+
NULL_CHECK_REGEX = /Objects\.requireNonNull\s*\(|if\s*\([^)]*==\s*null\)\s*(?:throw|return)/g;
|
|
30941
|
+
DEFAULT_THRESHOLD = 2;
|
|
30942
|
+
javaOptionalOveruseRule = createRule({
|
|
30943
|
+
id: "java/optional-overuse",
|
|
30944
|
+
category: "typo",
|
|
30945
|
+
severity: "low",
|
|
30946
|
+
aiSpecific: true,
|
|
30947
|
+
description: "Optional chain over-use \u2014 null check or Objects.requireNonNull is faster",
|
|
30948
|
+
create(_context) {
|
|
30949
|
+
return { threshold: DEFAULT_THRESHOLD };
|
|
30950
|
+
},
|
|
30951
|
+
analyze(context, facts) {
|
|
30952
|
+
const issues = [];
|
|
30953
|
+
const source = facts.v2?._source;
|
|
30954
|
+
if (!source) return issues;
|
|
30955
|
+
if (!/\.java$/i.test(facts.filePath)) return issues;
|
|
30956
|
+
OR_ELSE_THROW_REGEX.lastIndex = 0;
|
|
30957
|
+
let orElseThrowCount = 0;
|
|
30958
|
+
let firstIdx = 0;
|
|
30959
|
+
let m;
|
|
30960
|
+
while ((m = OR_ELSE_THROW_REGEX.exec(source)) !== null) {
|
|
30961
|
+
orElseThrowCount++;
|
|
30962
|
+
if (firstIdx === 0) firstIdx = m.index;
|
|
30963
|
+
}
|
|
30964
|
+
if (orElseThrowCount < context.threshold) return issues;
|
|
30965
|
+
NULL_CHECK_REGEX.lastIndex = 0;
|
|
30966
|
+
const nullCheckCount = (source.match(NULL_CHECK_REGEX) ?? []).length;
|
|
30967
|
+
const optionalRatio = orElseThrowCount / Math.max(orElseThrowCount + nullCheckCount, 1);
|
|
30968
|
+
if (optionalRatio < 0.6) return issues;
|
|
30969
|
+
const line = source.slice(0, firstIdx).split("\n").length;
|
|
30970
|
+
issues.push({
|
|
30971
|
+
ruleId: "java/optional-overuse",
|
|
30972
|
+
category: "typo",
|
|
30973
|
+
severity: "low",
|
|
30974
|
+
aiSpecific: true,
|
|
30975
|
+
message: `${orElseThrowCount} .orElseThrow() calls with ${nullCheckCount} null checks \u2014 Optional chain over-use`,
|
|
30976
|
+
line,
|
|
30977
|
+
column: 1,
|
|
30978
|
+
advice: 'Use Objects.requireNonNull(x, "msg") for null checks; reserve Optional for return values. AI agents default to Optional chains because their training data emphasizes null-safety. Real Java code uses null checks in hot paths. Reference: java/optional-overuse v0.26.0.'
|
|
30979
|
+
});
|
|
30980
|
+
return issues;
|
|
30981
|
+
}
|
|
30982
|
+
});
|
|
30983
|
+
}
|
|
30984
|
+
});
|
|
30985
|
+
|
|
30825
30986
|
// src/rules/java/raw-type-overuse.ts
|
|
30826
30987
|
var RAW_TYPE_REGEX, javaRawTypeOveruseRule;
|
|
30827
30988
|
var init_raw_type_overuse = __esm({
|
|
@@ -30865,6 +31026,75 @@ var init_raw_type_overuse = __esm({
|
|
|
30865
31026
|
}
|
|
30866
31027
|
});
|
|
30867
31028
|
|
|
31029
|
+
// src/rules/java/stream-overuse.ts
|
|
31030
|
+
var STREAM_OPS, DEFAULT_CHAIN_THRESHOLD, javaStreamOveruseRule;
|
|
31031
|
+
var init_stream_overuse = __esm({
|
|
31032
|
+
"src/rules/java/stream-overuse.ts"() {
|
|
31033
|
+
"use strict";
|
|
31034
|
+
init_rule();
|
|
31035
|
+
STREAM_OPS = [
|
|
31036
|
+
".map(",
|
|
31037
|
+
".filter(",
|
|
31038
|
+
".flatMap(",
|
|
31039
|
+
".collect(",
|
|
31040
|
+
".reduce(",
|
|
31041
|
+
".sorted(",
|
|
31042
|
+
".distinct(",
|
|
31043
|
+
".limit(",
|
|
31044
|
+
".skip(",
|
|
31045
|
+
".anyMatch(",
|
|
31046
|
+
".allMatch(",
|
|
31047
|
+
".noneMatch(",
|
|
31048
|
+
".findFirst(",
|
|
31049
|
+
".findAny("
|
|
31050
|
+
];
|
|
31051
|
+
DEFAULT_CHAIN_THRESHOLD = 3;
|
|
31052
|
+
javaStreamOveruseRule = createRule({
|
|
31053
|
+
id: "java/stream-overuse",
|
|
31054
|
+
category: "typo",
|
|
31055
|
+
severity: "low",
|
|
31056
|
+
aiSpecific: true,
|
|
31057
|
+
description: "Stream API chain over-use \u2014 for-loop is faster for simple transformations",
|
|
31058
|
+
create(_context) {
|
|
31059
|
+
return { chainThreshold: DEFAULT_CHAIN_THRESHOLD };
|
|
31060
|
+
},
|
|
31061
|
+
analyze(context, facts) {
|
|
31062
|
+
const issues = [];
|
|
31063
|
+
const source = facts.v2?._source;
|
|
31064
|
+
if (!source) return issues;
|
|
31065
|
+
if (!/\.java$/i.test(facts.filePath)) return issues;
|
|
31066
|
+
const lines = source.split("\n");
|
|
31067
|
+
const streamOpPattern = new RegExp(STREAM_OPS.map((op) => op.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"), "g");
|
|
31068
|
+
let firstOffendingLine = 0;
|
|
31069
|
+
let firstOffendingCount = 0;
|
|
31070
|
+
for (let i = 0; i < lines.length; i++) {
|
|
31071
|
+
const line = lines[i] ?? "";
|
|
31072
|
+
if (line.trim().startsWith("//") || line.trim().startsWith("*")) continue;
|
|
31073
|
+
const matches = line.match(streamOpPattern);
|
|
31074
|
+
if (matches && matches.length >= context.chainThreshold) {
|
|
31075
|
+
if (firstOffendingLine === 0) {
|
|
31076
|
+
firstOffendingLine = i + 1;
|
|
31077
|
+
firstOffendingCount = matches.length;
|
|
31078
|
+
}
|
|
31079
|
+
}
|
|
31080
|
+
}
|
|
31081
|
+
if (firstOffendingLine === 0) return issues;
|
|
31082
|
+
issues.push({
|
|
31083
|
+
ruleId: "java/stream-overuse",
|
|
31084
|
+
category: "typo",
|
|
31085
|
+
severity: "low",
|
|
31086
|
+
aiSpecific: true,
|
|
31087
|
+
message: `${firstOffendingCount} stream operations on a single line \u2014 for-loop is faster`,
|
|
31088
|
+
line: firstOffendingLine,
|
|
31089
|
+
column: 1,
|
|
31090
|
+
advice: "Prefer a for-loop for simple transformations. AI agents default to Stream API chains because their training data emphasizes functional-style Java. Stream chains allocate intermediate objects; for small collections, a for-loop is faster and more readable. Reference: java/stream-overuse v0.26.0."
|
|
31091
|
+
});
|
|
31092
|
+
return issues;
|
|
31093
|
+
}
|
|
31094
|
+
});
|
|
31095
|
+
}
|
|
31096
|
+
});
|
|
31097
|
+
|
|
30868
31098
|
// src/rules/java/string-concat-loop.ts
|
|
30869
31099
|
var STRING_CONCAT_REGEX, javaStringConcatLoopRule;
|
|
30870
31100
|
var init_string_concat_loop = __esm({
|
|
@@ -30909,13 +31139,13 @@ var init_string_concat_loop = __esm({
|
|
|
30909
31139
|
});
|
|
30910
31140
|
|
|
30911
31141
|
// src/rules/java/system-out-println.ts
|
|
30912
|
-
var PRINTLN_REGEX,
|
|
31142
|
+
var PRINTLN_REGEX, DEFAULT_THRESHOLD2, javaSystemOutPrintlnRule;
|
|
30913
31143
|
var init_system_out_println = __esm({
|
|
30914
31144
|
"src/rules/java/system-out-println.ts"() {
|
|
30915
31145
|
"use strict";
|
|
30916
31146
|
init_rule();
|
|
30917
31147
|
PRINTLN_REGEX = /System\.out\.println\s*\(/g;
|
|
30918
|
-
|
|
31148
|
+
DEFAULT_THRESHOLD2 = 1;
|
|
30919
31149
|
javaSystemOutPrintlnRule = createRule({
|
|
30920
31150
|
id: "java/system-out-println",
|
|
30921
31151
|
category: "typo",
|
|
@@ -30923,7 +31153,7 @@ var init_system_out_println = __esm({
|
|
|
30923
31153
|
aiSpecific: true,
|
|
30924
31154
|
description: "System.out.println in production code \u2014 use a logger (SLF4J, Log4j, etc.)",
|
|
30925
31155
|
create(_context) {
|
|
30926
|
-
return { threshold:
|
|
31156
|
+
return { threshold: DEFAULT_THRESHOLD2 };
|
|
30927
31157
|
},
|
|
30928
31158
|
analyze(context, facts) {
|
|
30929
31159
|
const issues = [];
|
|
@@ -30958,6 +31188,63 @@ var init_system_out_println = __esm({
|
|
|
30958
31188
|
}
|
|
30959
31189
|
});
|
|
30960
31190
|
|
|
31191
|
+
// src/rules/java/verbose-javadoc.ts
|
|
31192
|
+
var TAG_REGEX, DEFAULT_TAG_THRESHOLD, DEFAULT_BODY_LENGTH_CAP, javaVerboseJavadocRule;
|
|
31193
|
+
var init_verbose_javadoc = __esm({
|
|
31194
|
+
"src/rules/java/verbose-javadoc.ts"() {
|
|
31195
|
+
"use strict";
|
|
31196
|
+
init_rule();
|
|
31197
|
+
TAG_REGEX = /@(param|return|throws)\b/g;
|
|
31198
|
+
DEFAULT_TAG_THRESHOLD = 3;
|
|
31199
|
+
DEFAULT_BODY_LENGTH_CAP = 5;
|
|
31200
|
+
javaVerboseJavadocRule = createRule({
|
|
31201
|
+
id: "java/verbose-javadoc",
|
|
31202
|
+
category: "typo",
|
|
31203
|
+
severity: "low",
|
|
31204
|
+
aiSpecific: true,
|
|
31205
|
+
description: "Excessive Javadoc tags on trivial methods \u2014 over-documentation is an AI fingerprint",
|
|
31206
|
+
create(_context) {
|
|
31207
|
+
return {
|
|
31208
|
+
tagThreshold: DEFAULT_TAG_THRESHOLD,
|
|
31209
|
+
bodyLengthCap: DEFAULT_BODY_LENGTH_CAP
|
|
31210
|
+
};
|
|
31211
|
+
},
|
|
31212
|
+
analyze(context, facts) {
|
|
31213
|
+
const issues = [];
|
|
31214
|
+
const source = facts.v2?._source;
|
|
31215
|
+
if (!source) return issues;
|
|
31216
|
+
if (!/\.java$/i.test(facts.filePath)) return issues;
|
|
31217
|
+
TAG_REGEX.lastIndex = 0;
|
|
31218
|
+
let tagCount = 0;
|
|
31219
|
+
let firstTagLine = 0;
|
|
31220
|
+
let m;
|
|
31221
|
+
while ((m = TAG_REGEX.exec(source)) !== null) {
|
|
31222
|
+
tagCount++;
|
|
31223
|
+
if (firstTagLine === 0) {
|
|
31224
|
+
firstTagLine = source.slice(0, m.index).split("\n").length;
|
|
31225
|
+
}
|
|
31226
|
+
}
|
|
31227
|
+
if (tagCount < context.tagThreshold) return issues;
|
|
31228
|
+
const lineCount = source.split("\n").length;
|
|
31229
|
+
const tagDensity = tagCount / Math.max(lineCount, 1);
|
|
31230
|
+
if (tagDensity < 0.05) return issues;
|
|
31231
|
+
if (lineCount > 200) return issues;
|
|
31232
|
+
issues.push({
|
|
31233
|
+
ruleId: "java/verbose-javadoc",
|
|
31234
|
+
category: "typo",
|
|
31235
|
+
severity: "low",
|
|
31236
|
+
aiSpecific: true,
|
|
31237
|
+
message: `${tagCount} Javadoc tags in ${lineCount} lines (density ${(tagDensity * 100).toFixed(1)}%) \u2014 likely over-documented`,
|
|
31238
|
+
line: firstTagLine,
|
|
31239
|
+
column: 1,
|
|
31240
|
+
advice: "Skip Javadoc on trivial methods (getters, setters, builders). AI agents default to over-documentation because their training data has countless textbook Javadoc examples. Real Java code limits Javadoc to public API surface. Reference: java/verbose-javadoc v0.26.0."
|
|
31241
|
+
});
|
|
31242
|
+
return issues;
|
|
31243
|
+
}
|
|
31244
|
+
});
|
|
31245
|
+
}
|
|
31246
|
+
});
|
|
31247
|
+
|
|
30961
31248
|
// src/rules/kotlin/coroutine-global-scope.ts
|
|
30962
31249
|
var GLOBAL_SCOPE_REGEX, kotlinCoroutineGlobalScopeRule;
|
|
30963
31250
|
var init_coroutine_global_scope = __esm({
|
|
@@ -31122,13 +31409,13 @@ var init_object_singleton_misuse = __esm({
|
|
|
31122
31409
|
});
|
|
31123
31410
|
|
|
31124
31411
|
// src/rules/kotlin/println-debug.ts
|
|
31125
|
-
var PRINTLN_REGEX2,
|
|
31412
|
+
var PRINTLN_REGEX2, DEFAULT_THRESHOLD3, kotlinPrintlnDebugRule;
|
|
31126
31413
|
var init_println_debug = __esm({
|
|
31127
31414
|
"src/rules/kotlin/println-debug.ts"() {
|
|
31128
31415
|
"use strict";
|
|
31129
31416
|
init_rule();
|
|
31130
31417
|
PRINTLN_REGEX2 = /^\s*println\s*\(/gm;
|
|
31131
|
-
|
|
31418
|
+
DEFAULT_THRESHOLD3 = 1;
|
|
31132
31419
|
kotlinPrintlnDebugRule = createRule({
|
|
31133
31420
|
id: "kotlin/println-debug",
|
|
31134
31421
|
category: "typo",
|
|
@@ -31136,7 +31423,7 @@ var init_println_debug = __esm({
|
|
|
31136
31423
|
aiSpecific: true,
|
|
31137
31424
|
description: "println(...) in production code \u2014 use Timber, android.util.Log, or an SLF4J facade",
|
|
31138
31425
|
create(_context) {
|
|
31139
|
-
return { threshold:
|
|
31426
|
+
return { threshold: DEFAULT_THRESHOLD3 };
|
|
31140
31427
|
},
|
|
31141
31428
|
analyze(context, facts) {
|
|
31142
31429
|
const issues = [];
|
|
@@ -40841,13 +41128,13 @@ var init_implicitly_unwrapped_optional = __esm({
|
|
|
40841
41128
|
});
|
|
40842
41129
|
|
|
40843
41130
|
// src/rules/swift/print-debug.ts
|
|
40844
|
-
var PRINT_REGEX,
|
|
41131
|
+
var PRINT_REGEX, DEFAULT_THRESHOLD4, swiftPrintDebugRule;
|
|
40845
41132
|
var init_print_debug = __esm({
|
|
40846
41133
|
"src/rules/swift/print-debug.ts"() {
|
|
40847
41134
|
"use strict";
|
|
40848
41135
|
init_rule();
|
|
40849
41136
|
PRINT_REGEX = /\bprint\s*\(/g;
|
|
40850
|
-
|
|
41137
|
+
DEFAULT_THRESHOLD4 = 1;
|
|
40851
41138
|
swiftPrintDebugRule = createRule({
|
|
40852
41139
|
id: "swift/print-debug",
|
|
40853
41140
|
category: "typo",
|
|
@@ -40855,7 +41142,7 @@ var init_print_debug = __esm({
|
|
|
40855
41142
|
aiSpecific: true,
|
|
40856
41143
|
description: "print(...) in production Swift \u2014 use Logger (os.log) for level-controlled output",
|
|
40857
41144
|
create(_context) {
|
|
40858
|
-
return { threshold:
|
|
41145
|
+
return { threshold: DEFAULT_THRESHOLD4 };
|
|
40859
41146
|
},
|
|
40860
41147
|
analyze(context, facts) {
|
|
40861
41148
|
const issues = [];
|
|
@@ -46606,11 +46893,16 @@ var init_builtins = __esm({
|
|
|
46606
46893
|
init_nil_slice_vs_empty();
|
|
46607
46894
|
init_struct_tag_inconsistency();
|
|
46608
46895
|
init_arraylist_vs_linkedlist();
|
|
46896
|
+
init_builder_overuse();
|
|
46609
46897
|
init_empty_catch_block();
|
|
46898
|
+
init_immutable_collection_preference();
|
|
46610
46899
|
init_legacy_date_api();
|
|
46900
|
+
init_optional_overuse();
|
|
46611
46901
|
init_raw_type_overuse();
|
|
46902
|
+
init_stream_overuse();
|
|
46612
46903
|
init_string_concat_loop();
|
|
46613
46904
|
init_system_out_println();
|
|
46905
|
+
init_verbose_javadoc();
|
|
46614
46906
|
init_coroutine_global_scope();
|
|
46615
46907
|
init_data_class_defaults_overuse();
|
|
46616
46908
|
init_object_singleton_misuse();
|
|
@@ -46741,11 +47033,16 @@ var init_builtins = __esm({
|
|
|
46741
47033
|
goNilSliceVsEmptyRule,
|
|
46742
47034
|
goStructTagInconsistencyRule,
|
|
46743
47035
|
javaArraylistVsLinkedlistRule,
|
|
47036
|
+
javaBuilderOveruseRule,
|
|
46744
47037
|
javaEmptyCatchBlockRule,
|
|
47038
|
+
javaImmutableCollectionPreferenceRule,
|
|
46745
47039
|
javaLegacyDateApiRule,
|
|
47040
|
+
javaOptionalOveruseRule,
|
|
46746
47041
|
javaRawTypeOveruseRule,
|
|
47042
|
+
javaStreamOveruseRule,
|
|
46747
47043
|
javaStringConcatLoopRule,
|
|
46748
47044
|
javaSystemOutPrintlnRule,
|
|
47045
|
+
javaVerboseJavadocRule,
|
|
46749
47046
|
kotlinCoroutineGlobalScopeRule,
|
|
46750
47047
|
kotlinDataClassDefaultsOveruseRule,
|
|
46751
47048
|
kotlinObjectSingletonMisuseRule,
|
|
@@ -49984,6 +50281,86 @@ var init_signal_strength = __esm({
|
|
|
49984
50281
|
_v9Precision: 0.0657,
|
|
49985
50282
|
defaultOff: true
|
|
49986
50283
|
},
|
|
50284
|
+
"java/verbose-javadoc": {
|
|
50285
|
+
recall: 0,
|
|
50286
|
+
fpRate: 0,
|
|
50287
|
+
ratio: 1,
|
|
50288
|
+
precision: 0,
|
|
50289
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50290
|
+
verdict: "DORMANT",
|
|
50291
|
+
_calibrationNote: "v0.26.0: new positive AI-signal rule. Triggers when a small Java file (< 200 lines) has 3+ Javadoc tags with density >= 0.05. Calibration pending v9 Java corpus re-run; placeholder values until then. v0.20.0: anti-pattern design was wrong (humans write more Javadoc on trivial methods because their training data has it). v0.26.0: redesigned as positive signal (AI over-documents trivial methods). Reference: java/verbose-javadoc v0.26.0.",
|
|
50292
|
+
aiSpecific: true,
|
|
50293
|
+
_v9Verdict: "DORMANT",
|
|
50294
|
+
_v9Lift: 1,
|
|
50295
|
+
_v9Recall: 0,
|
|
50296
|
+
_v9FpRate: 0,
|
|
50297
|
+
_v9Precision: 0,
|
|
50298
|
+
defaultOff: true
|
|
50299
|
+
},
|
|
50300
|
+
"java/optional-overuse": {
|
|
50301
|
+
recall: 0,
|
|
50302
|
+
fpRate: 0,
|
|
50303
|
+
ratio: 1,
|
|
50304
|
+
precision: 0,
|
|
50305
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50306
|
+
verdict: "DORMANT",
|
|
50307
|
+
_calibrationNote: "v0.26.0: new positive AI-signal rule. Triggers when a Java file has 2+ .orElseThrow() calls AND 0 Objects.requireNonNull()/null checks (optionalRatio > 0.6). Calibration pending v9 Java corpus re-run; placeholder values until then. v0.26.0: redesigned as positive signal (AI chains Optional.ofNullable().orElseThrow() where null checks would be cleaner). Reference: java/optional-overuse v0.26.0.",
|
|
50308
|
+
aiSpecific: true,
|
|
50309
|
+
_v9Verdict: "DORMANT",
|
|
50310
|
+
_v9Lift: 1,
|
|
50311
|
+
_v9Recall: 0,
|
|
50312
|
+
_v9FpRate: 0,
|
|
50313
|
+
_v9Precision: 0,
|
|
50314
|
+
defaultOff: true
|
|
50315
|
+
},
|
|
50316
|
+
"java/immutable-collection-preference": {
|
|
50317
|
+
recall: 0,
|
|
50318
|
+
fpRate: 0,
|
|
50319
|
+
ratio: 1,
|
|
50320
|
+
precision: 0,
|
|
50321
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50322
|
+
verdict: "DORMANT",
|
|
50323
|
+
_calibrationNote: "v0.26.0: new positive AI-signal rule. Triggers when a Java file has 5+ List.of/Map.of/Set.of calls AND < 1 new ArrayList/HashMap/HashSet/LinkedList/TreeMap calls. Calibration pending v9 Java corpus re-run; placeholder values until then. v0.26.0: redesigned as positive signal (AI defaults to immutable factory methods). Reference: java/immutable-collection-preference v0.26.0.",
|
|
50324
|
+
aiSpecific: true,
|
|
50325
|
+
_v9Verdict: "DORMANT",
|
|
50326
|
+
_v9Lift: 1,
|
|
50327
|
+
_v9Recall: 0,
|
|
50328
|
+
_v9FpRate: 0,
|
|
50329
|
+
_v9Precision: 0,
|
|
50330
|
+
defaultOff: true
|
|
50331
|
+
},
|
|
50332
|
+
"java/builder-overuse": {
|
|
50333
|
+
recall: 0,
|
|
50334
|
+
fpRate: 0,
|
|
50335
|
+
ratio: 1,
|
|
50336
|
+
precision: 0,
|
|
50337
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50338
|
+
verdict: "DORMANT",
|
|
50339
|
+
_calibrationNote: "v0.26.0: new positive AI-signal rule. Triggers when @Builder annotation (Lombok) is used on a class with <= 3 fields. Calibration pending v9 Java corpus re-run; placeholder values until then. v0.26.0: redesigned as positive signal (AI defaults to Builder pattern even for simple data classes). Reference: java/builder-overuse v0.26.0.",
|
|
50340
|
+
aiSpecific: true,
|
|
50341
|
+
_v9Verdict: "DORMANT",
|
|
50342
|
+
_v9Lift: 1,
|
|
50343
|
+
_v9Recall: 0,
|
|
50344
|
+
_v9FpRate: 0,
|
|
50345
|
+
_v9Precision: 0,
|
|
50346
|
+
defaultOff: true
|
|
50347
|
+
},
|
|
50348
|
+
"java/stream-overuse": {
|
|
50349
|
+
recall: 0,
|
|
50350
|
+
fpRate: 0,
|
|
50351
|
+
ratio: 1,
|
|
50352
|
+
precision: 0,
|
|
50353
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50354
|
+
verdict: "DORMANT",
|
|
50355
|
+
_calibrationNote: "v0.26.0: new positive AI-signal rule. Triggers when a single line has 3+ Stream API operations (.map, .filter, .flatMap, .collect, .reduce, .sorted, .distinct, .limit, .skip, .anyMatch, .allMatch, .noneMatch, .findFirst, .findAny). Calibration pending v9 Java corpus re-run; placeholder values until then. v0.26.0: redesigned as positive signal (AI chains Stream API for everything). Reference: java/stream-overuse v0.26.0.",
|
|
50356
|
+
aiSpecific: true,
|
|
50357
|
+
_v9Verdict: "DORMANT",
|
|
50358
|
+
_v9Lift: 1,
|
|
50359
|
+
_v9Recall: 0,
|
|
50360
|
+
_v9FpRate: 0,
|
|
50361
|
+
_v9Precision: 0,
|
|
50362
|
+
defaultOff: true
|
|
50363
|
+
},
|
|
49987
50364
|
"java/raw-type-overuse": {
|
|
49988
50365
|
recall: 0.1093,
|
|
49989
50366
|
fpRate: 0.2041,
|
|
@@ -59601,6 +59978,11 @@ var RULE_HINTS = {
|
|
|
59601
59978
|
"java/legacy-date-api": "Replace `java.util.Date` / `Calendar` with `java.time` (`LocalDate`, `LocalDateTime`, `Instant`, `ZonedDateTime`). java.time is immutable and thread-safe. AI agents default to the legacy API.",
|
|
59602
59979
|
"java/raw-type-overuse": "Replace raw `List` / `Map` / `Set` with the parameterized form. Raw types disable generic type checking (Effective Java, Item 23). AI agents default to raw types when unsure of the correct generic parameters.",
|
|
59603
59980
|
"java/string-concat-loop": "Declare a `StringBuilder` outside the loop: `StringBuilder sb = new StringBuilder(); sb.append(...);` then `return sb.toString();` after. String concat in a loop is O(n\xB2).",
|
|
59981
|
+
"java/verbose-javadoc": "Skip Javadoc on trivial methods (getters, setters, builders). AI over-documents; real Java limits Javadoc to public API surface. (v0.26.0 \u2014 DORMANT.)",
|
|
59982
|
+
"java/optional-overuse": "Use Objects.requireNonNull(x) for null checks; reserve Optional for return values. AI chains .ofNullable().orElseThrow() where null checks suffice. (v0.26.0 \u2014 DORMANT.)",
|
|
59983
|
+
"java/immutable-collection-preference": "Prefer mutable (new ArrayList<>()) when the collection will be modified. AI defaults to List.of/Map.of/Set.of; real Java uses mutable. (v0.26.0 \u2014 DORMANT.)",
|
|
59984
|
+
"java/builder-overuse": "Use a plain constructor for classes with \u2264 3 fields. AI defaults to @Builder; Builder adds Lombok dep and a Builder inner class per class. (v0.26.0 \u2014 DORMANT.)",
|
|
59985
|
+
"java/stream-overuse": "Prefer a for-loop for simple transformations. AI chains Stream API for everything; for small collections a for-loop is faster. (v0.26.0 \u2014 DORMANT.)",
|
|
59604
59986
|
// v0.24.0 — Kotlin rules (DORMANT until v9 Kotlin corpus calibration)
|
|
59605
59987
|
"kotlin/data-class-defaults-overuse": "Audit which fields are genuinely optional. Real Kotlin uses defaults sparingly (1-2 callbacks, the rest required). v0.24.0 \u2014 DORMANT until v9 calibration.",
|
|
59606
59988
|
"kotlin/coroutine-global-scope": "Replace with `viewModelScope.launch { ... }`, `lifecycleScope.launch { ... }`, or `coroutineScope { ... }`. GlobalScope bypasses cancellation. (v0.24.0 \u2014 DORMANT.)",
|