Skip to content

Commit 2648b26

Browse files
committed
补齐Gradle文档空注释、用途和异常说明诊断
1 parent 9b7f5a0 commit 2648b26

35 files changed

Lines changed: 8985 additions & 51 deletions

‎README.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,8 +1010,10 @@ For explicit Gradle documentation requests, the Java comments category preserves
10101010

10111011
An independent `gradle_javadoc_workbench::project` now validates selected paths, source digests and the native snapshot digest before first import, merges identical native locations, and retains execution failures or unqualified coverage as separate preparation observations. Identity survives line movement of the same path/rule/source-line anchor; anchor edits or duplicate-anchor insertion may change it. The initial projection acceptance did not wire persistence; the current integration and separate protocols are described below, while trusted closure remains open. See [projection acceptance](tests/acceptance/gradle-javadoc-projection.md).
10121012

1013-
The development `check java/all --gradle-javadoc` now captures selected inputs before native execution, revalidates digests/locations at first import, and saves local reports with stable findings and preparation tasks. Repeated scans append observations; missing Markdown can be restored from facts. `next` / `task show` provide original-task `task verify` arguments; selected inputs are retained in the bound original report and tool paths require validation. Check feedback 0.66 and repair preview 0.23 are separate closed protocols (historical 0.65/0.22 remain unchanged); ordinary Java checks also retain historical guidance. Counts in `gradle_javadoc_tasks` cover the current workspace sync, not exclusively Gradle records. Three actual public checks verify detection, reuse and empty output after repair while historical findings remain open. `task_verify_status=local_observation_only`: original-task verification is connected; trusted closure/reopen and complete rule/scope acceptance remain pending. See [workbench acceptance](tests/acceptance/gradle-javadoc-workbench.md).
1013+
The development `check java/all --gradle-javadoc` now captures selected inputs before native execution, revalidates digests/locations at first import, and saves local reports with stable findings and preparation tasks. Repeated scans append observations; missing Markdown can be restored from facts. `next` / `task show` provide original-task `task verify` arguments; selected inputs are retained in the bound original report and tool paths require validation. Check feedback 0.67 and repair preview 0.24 are separate closed protocols (historical 0.65/0.22 and 0.66/0.23 remain unchanged); ordinary Java checks also retain historical guidance. Counts in `gradle_javadoc_tasks` cover the current workspace sync, not exclusively Gradle records. Three actual public checks verify detection, reuse and empty output after repair while historical findings remain open. `task_verify_status=local_observation_only`: original-task verification is connected; trusted closure/reopen and complete rule/scope acceptance remain pending. See [workbench acceptance](tests/acceptance/gradle-javadoc-workbench.md).
10141014

1015-
The internal `gradle_javadoc_task_recheck` service binds the consumed original report, task scope/rule and selected inputs. Java bytes may be repaired; changed build configuration or known tool identity prevents native execution. Observations distinguish a present finding, untrusted absence, rule review and incomplete execution; malformed native reports cannot represent zero findings. Public `task verify` now reuses the original selected scope with `--gradle-bundle` and `--java-home`. Recheck import revalidates original facts and current inputs, persists attempt-bound observations, and supports findings whose first evidence is a recheck wrapper. `next` invalidates stale source/configuration/tool observations; a different finding with the same file/rule requires review rather than being treated as the original finding. Task preview 0.29 and repair preview 0.23 remain local observations; trusted closure and production qualification are still pending. The initial service baseline remains in [internal recheck acceptance](tests/acceptance/gradle-javadoc-task-recheck-service.md).
1015+
The internal `gradle_javadoc_task_recheck` service binds the consumed original report, task scope/rule and selected inputs. Java bytes may be repaired; changed build configuration or known tool identity prevents native execution. Observations distinguish a present finding, untrusted absence, rule review and incomplete execution; malformed native reports cannot represent zero findings. Public `task verify` now reuses the original selected scope with `--gradle-bundle` and `--java-home`. Recheck import revalidates original facts and current inputs, persists attempt-bound observations, and supports findings whose first evidence is a recheck wrapper. `next` invalidates stale source/configuration/tool observations; a different finding with the same file/rule requires review rather than being treated as the original finding. Task preview 0.30 and repair preview 0.24 remain local observations; trusted closure and production qualification are still pending. The initial service baseline remains in [internal recheck acceptance](tests/acceptance/gradle-javadoc-task-recheck-service.md).
10161016

10171017
See [public recheck acceptance](tests/acceptance/gradle-javadoc-public-task-recheck.md) for native observations, attempt binding and invalidation evidence.
1018+
1019+
Gradle native documentation feedback now preserves empty comments, missing main descriptions and empty exception descriptions as `JavadocEmptyComment`, `JavadocMissingMainDescription` and `JavadocEmptyThrowsDescription`; existing empty parameter/return rules remain. Original JDK21 output is bound to selected source bytes before stable task import and original-tool recheck. Native/workbench/recheck protocols use separate 0.2 contracts; historical 0.1 is not widened. Aggregation 0.67, aborted feedback 0.18, repair preview 0.24 and task preview 0.30 remain closed contracts. Actual empty type/constructor/field/method comments yield four diagnostics, bare tags three, missing purpose one; detailed Chinese comments and valid inherited documentation yield zero, still untrusted. Standalone JDK/Maven historical protocols do not yet integrate these new rules, and complete documentation qualification remains pending. See [description acceptance](tests/acceptance/gradle-javadoc-detailed-descriptions.md).

‎crates/codeguard-adapters/src/gradle_javadoc_output.rs‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,14 @@ pub fn parse_gradle_javadoc_output(
4242
return Err("gradle_javadoc_source_unresolved");
4343
}
4444
let (path, source) = matches[0];
45-
// JDK21实际输出已验证的空标签描述;复用位置核验,不改变旧Javadoc协议的规则集合。
45+
// JDK21实际输出已验证的描述缺失;复用位置核验,保留各规则身份,旧独立Javadoc协议不扩大。
4646
let empty_description = [
47+
("empty comment", "JavadocEmptyComment"),
48+
("no main description", "JavadocMissingMainDescription"),
49+
(
50+
"no description for @throws",
51+
"JavadocEmptyThrowsDescription",
52+
),
4753
("no description for @param", "JavadocEmptyParamDescription"),
4854
(
4955
"no description for @return",

‎crates/codeguard-adapters/tests/gradle_javadoc.rs‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,36 @@ fn native_empty_tag_descriptions_are_not_treated_as_documented_code() {
6464
assert_eq!(parsed[0].rule_id, "JavadocEmptyParamDescription");
6565
assert_eq!(parsed[1].rule_id, "JavadocEmptyReturnDescription");
6666
}
67+
68+
#[test]
69+
fn empty_comments_main_descriptions_and_throws_keep_distinct_native_rules() {
70+
let sources = BTreeMap::from([(
71+
"/project/A.java".into(),
72+
b"public class A {}\n * @throws IllegalArgumentException\n/** @param value input\n"
73+
.to_vec(),
74+
)]);
75+
let log = b"/project/A.java:1: warning: empty comment\npublic class A {}\n ^\n/project/A.java:2: warning: no description for @throws\n * @throws IllegalArgumentException\n ^\n/project/A.java:3: warning: no main description\n/** @param value input\n ^\n3 warnings\n";
76+
let parsed = parse_gradle_javadoc_output(log, &sources)
77+
.expect("observed JDK21 description warnings must remain actionable native facts");
78+
assert_eq!(
79+
parsed.iter().map(|d| d.rule_id).collect::<Vec<_>>(),
80+
[
81+
"JavadocEmptyComment",
82+
"JavadocEmptyThrowsDescription",
83+
"JavadocMissingMainDescription"
84+
]
85+
);
86+
for bad in [
87+
String::from_utf8(log.to_vec())
88+
.unwrap()
89+
.replace("empty comment", "possibly empty comment"),
90+
String::from_utf8(log.to_vec())
91+
.unwrap()
92+
.replace("public class A {}", "public class B {}"),
93+
String::from_utf8(log.to_vec())
94+
.unwrap()
95+
.replace("3 warnings", "2 warnings"),
96+
] {
97+
assert!(parse_gradle_javadoc_output(bad.as_bytes(), &sources).is_err());
98+
}
99+
}

‎crates/codeguard-cli/src/check_command.rs‎

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,7 +2282,7 @@ fn run_scoped(args: &[String], lint_only: bool) -> ExitCode {
22822282
.iter()
22832283
.any(|entry| entry.checker_id.starts_with("java.gradle."));
22842284
let mut report = json!({
2285-
"schema_version":if parsed.gradle_javadoc || next["schema_version"] == "0.23.0" {"0.66.0"}else if gradle_requested {"0.62.0"}else if gradle_model_unresolved {"0.61.0"}else if next["schema_version"] == "0.21.0" || syntax_candidates["observations"].as_array().is_some_and(|rows| rows.iter().any(|row|row.get("javascript_mode_observation").is_some())) {"0.60.0"}else if lint_only {"0.59.0"}else if next["repair_brief"]["checker_id"] == "java.maven.p3c" && next["repair_brief"]["reason_code"] == "p3c_configuration_not_confirmed" {"0.58.0"}else if next["repair_brief"]["checker_id"] == "java.maven.javadoc" {"0.57.0"}else if next["repair_brief"]["checker_id"] == "rust.cargo_clippy" {"0.56.0"}else if syntax_candidates["observations"].as_array().is_some_and(|rows| rows.iter().any(|row| row["language"]=="erlang" && row.get("structural_observations").is_some())) {"0.55.0"} else if next["schema_version"] == "0.20.0" || syntax_candidates["observations"].as_array().is_some_and(|rows| rows.iter().any(|row| row["language"]=="javascript" && row.get("structural_observations").is_some())) {"0.54.0"}else if syntax_candidates["observations"].as_array().is_some_and(|rows|rows.iter().any(|row|row["language"]=="cfquery")) {"0.53.0"}else if shell_lint.is_object() || next["schema_version"]=="0.17.0" {"0.52.0"}else if ruby_lint.is_object() || next["schema_version"] == "0.15.0" {"0.51.0"} else if next["schema_version"] == "0.14.0" {"0.50.0"} else if next["schema_version"] == "0.13.0" || syntax_candidates["observations"].as_array().is_some_and(|rows| rows.iter().any(|row| row["language"] == "go" && row.get("structural_observations").is_some())) {"0.49.0"} else if syntax_candidates["observations"].as_array().is_some_and(|rows| rows.iter().any(|row| row.get("structural_observations").is_some())) {"0.48.0"} else if zig_lint["schema_version"] == "0.2.0" || next["schema_version"] == "0.12.0" {"0.47.0"}else if zig_lint.is_object() {"0.46.0"} else if matches!(parsed.selection, Selection::Language(_)) {"0.45.0"} else if swift_lint["schema_version"] == "0.2.0" || next["schema_version"] == "0.11.0" {"0.44.0"} else if swift_lint.is_object() {"0.43.0"} else if kotlin_lint.is_object() || next["schema_version"] == "0.10.0" {"0.42.0"} else if matches!(next["schema_version"].as_str(), Some("0.8.0" | "0.9.0")) {"0.41.0"} else if next["schema_version"] == "0.7.0" {"0.40.0"} else if next["schema_version"] == "0.6.0" {"0.39.0"} else {"0.38.0"}, "report_type":"check_feedback",
2285+
"schema_version":if parsed.gradle_javadoc || next["schema_version"] == "0.24.0" {"0.67.0"}else if gradle_requested {"0.62.0"}else if gradle_model_unresolved {"0.61.0"}else if next["schema_version"] == "0.21.0" || syntax_candidates["observations"].as_array().is_some_and(|rows| rows.iter().any(|row|row.get("javascript_mode_observation").is_some())) {"0.60.0"}else if lint_only {"0.59.0"}else if next["repair_brief"]["checker_id"] == "java.maven.p3c" && next["repair_brief"]["reason_code"] == "p3c_configuration_not_confirmed" {"0.58.0"}else if next["repair_brief"]["checker_id"] == "java.maven.javadoc" {"0.57.0"}else if next["repair_brief"]["checker_id"] == "rust.cargo_clippy" {"0.56.0"}else if syntax_candidates["observations"].as_array().is_some_and(|rows| rows.iter().any(|row| row["language"]=="erlang" && row.get("structural_observations").is_some())) {"0.55.0"} else if next["schema_version"] == "0.20.0" || syntax_candidates["observations"].as_array().is_some_and(|rows| rows.iter().any(|row| row["language"]=="javascript" && row.get("structural_observations").is_some())) {"0.54.0"}else if syntax_candidates["observations"].as_array().is_some_and(|rows|rows.iter().any(|row|row["language"]=="cfquery")) {"0.53.0"}else if shell_lint.is_object() || next["schema_version"]=="0.17.0" {"0.52.0"}else if ruby_lint.is_object() || next["schema_version"] == "0.15.0" {"0.51.0"} else if next["schema_version"] == "0.14.0" {"0.50.0"} else if next["schema_version"] == "0.13.0" || syntax_candidates["observations"].as_array().is_some_and(|rows| rows.iter().any(|row| row["language"] == "go" && row.get("structural_observations").is_some())) {"0.49.0"} else if syntax_candidates["observations"].as_array().is_some_and(|rows| rows.iter().any(|row| row.get("structural_observations").is_some())) {"0.48.0"} else if zig_lint["schema_version"] == "0.2.0" || next["schema_version"] == "0.12.0" {"0.47.0"}else if zig_lint.is_object() {"0.46.0"} else if matches!(parsed.selection, Selection::Language(_)) {"0.45.0"} else if swift_lint["schema_version"] == "0.2.0" || next["schema_version"] == "0.11.0" {"0.44.0"} else if swift_lint.is_object() {"0.43.0"} else if kotlin_lint.is_object() || next["schema_version"] == "0.10.0" {"0.42.0"} else if matches!(next["schema_version"].as_str(), Some("0.8.0" | "0.9.0")) {"0.41.0"} else if next["schema_version"] == "0.7.0" {"0.40.0"} else if next["schema_version"] == "0.6.0" {"0.39.0"} else {"0.38.0"}, "report_type":"check_feedback",
22862286
"operation":"check", "selection":parsed.selection.as_str(), "command_status":if request_cancelled { "cancelled" } else { "incomplete" },
22872287
"exit_code":if request_cancelled { 130 } else { 3 }, "delivery_decision":if parsed.selection == Selection::All { "incomplete" } else { "not_evaluated" }, "authority":"local_unverified",
22882288
"reason":if request_cancelled { "request_cancelled" } else if parsed.selection == Selection::All { "full_project_obligations_and_trusted_policy_unavailable" } else if parsed.selection == Selection::Java { "java_selection_obligations_and_trusted_policy_unavailable" } else { "language_selection_obligations_and_trusted_policy_unavailable" },
@@ -2302,7 +2302,7 @@ fn run_scoped(args: &[String], lint_only: bool) -> ExitCode {
23022302
if gradle_requested {
23032303
report["native_results"][gradle_result_key] = java_gradle_model;
23042304
}
2305-
if report["schema_version"] == "0.66.0" {
2305+
if report["schema_version"] == "0.67.0" {
23062306
report["gradle_javadoc_tasks"] = gradle_javadoc_tasks;
23072307
}
23082308
if zig_lint.is_object()
@@ -2328,7 +2328,7 @@ fn run_scoped(args: &[String], lint_only: bool) -> ExitCode {
23282328
| "0.63.0"
23292329
| "0.64.0"
23302330
| "0.65.0"
2331-
| "0.66.0"
2331+
| "0.67.0"
23322332
)
23332333
)
23342334
{
@@ -2362,7 +2362,7 @@ fn run_scoped(args: &[String], lint_only: bool) -> ExitCode {
23622362
| "0.63.0"
23632363
| "0.64.0"
23642364
| "0.65.0"
2365-
| "0.66.0"
2365+
| "0.67.0"
23662366
)
23672367
) {
23682368
if let Some(native) = report["native_results"].as_object_mut() {
@@ -2395,7 +2395,7 @@ fn run_scoped(args: &[String], lint_only: bool) -> ExitCode {
23952395
| "0.63.0"
23962396
| "0.64.0"
23972397
| "0.65.0"
2398-
| "0.66.0"
2398+
| "0.67.0"
23992399
)
24002400
) {
24012401
if let Some(native) = report["native_results"].as_object_mut() {
@@ -2420,7 +2420,7 @@ fn run_scoped(args: &[String], lint_only: bool) -> ExitCode {
24202420
| "0.63.0"
24212421
| "0.64.0"
24222422
| "0.65.0"
2423-
| "0.66.0"
2423+
| "0.67.0"
24242424
)
24252425
) {
24262426
report["native_results"]["ruby_lint"] = ruby_lint.clone();
@@ -2442,7 +2442,7 @@ fn run_scoped(args: &[String], lint_only: bool) -> ExitCode {
24422442
| "0.63.0"
24432443
| "0.64.0"
24442444
| "0.65.0"
2445-
| "0.66.0"
2445+
| "0.67.0"
24462446
)
24472447
) {
24482448
report["native_results"]["shell_lint"] = shell_lint.clone();
@@ -3362,7 +3362,7 @@ fn aborted_task_report(
33623362
execution_tasks.push(json!({"id":"zig.lint","status":if native_results["zig_lint"]["local_parse_complete"]==true {"native_observed_unverified"}else{"native_incomplete"}}));
33633363
}
33643364
json!({
3365-
"schema_version":if native_results.get("java_gradle_javadoc").is_some() {"0.17.0"}else if native_results.get("java_gradle_model").is_some() {"0.16.0"}else if native_results["zig_lint"].is_object() {"0.15.0"}else if matches!(selection, Selection::Language(_)) {"0.14.0"} else {"0.13.0"}, "report_type":"check_aborted",
3365+
"schema_version":if native_results.get("java_gradle_javadoc").is_some() {if native_results["java_gradle_javadoc"]["schema_version"] == "0.2.0" {"0.18.0"}else{"0.17.0"}}else if native_results.get("java_gradle_model").is_some() {"0.16.0"}else if native_results["zig_lint"].is_object() {"0.15.0"}else if matches!(selection, Selection::Language(_)) {"0.14.0"} else {"0.13.0"}, "report_type":"check_aborted",
33663366
"operation":"check", "selection":selection.as_str(),
33673367
"command_status":if cancelled { "cancelled" } else { "internal_error" },
33683368
"exit_code":if cancelled { 130 } else { 4 },
@@ -3949,6 +3949,28 @@ mod tests {
39493949
if let Some(path) = std::env::var_os("CODEGUARD_TEST_GRADLE_JAVADOC_ABORT_REPORT") {
39503950
std::fs::write(path, serde_json::to_vec_pretty(&report).unwrap()).unwrap();
39513951
}
3952+
3953+
// 新描述协议的兄弟失败不能吞掉已有原生问题;此处仅构造反馈边界,不执行工具。
3954+
let mut expanded = report["native_results"].clone();
3955+
expanded["java_gradle_javadoc"]["schema_version"] = json!("0.2.0");
3956+
expanded["java_gradle_javadoc"]["findings"][0]["rule_id"] = json!("JavadocEmptyComment");
3957+
let current = aborted_task_report(
3958+
Selection::Java,
3959+
source["discovery"].clone(),
3960+
&outcomes,
3961+
expanded,
3962+
false,
3963+
);
3964+
assert_eq!(current["schema_version"], "0.18.0");
3965+
assert_eq!(
3966+
current["native_results"]["java_gradle_javadoc"]["findings"][0]["rule_id"],
3967+
"JavadocEmptyComment"
3968+
);
3969+
assert_eq!(current["delivery_decision"], "not_evaluated");
3970+
assert_eq!(current["exit_code"], 4);
3971+
if let Some(path) = std::env::var_os("CODEGUARD_TEST_GRADLE_JAVADOC_ABORT_V2_REPORT") {
3972+
std::fs::write(path, serde_json::to_vec_pretty(&current).unwrap()).unwrap();
3973+
}
39523974
}
39533975

39543976
#[test]

0 commit comments

Comments
 (0)