Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions .github/workflows/nightlydeploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ permissions:
contents: write
id-token: write

# The documentation generation for varconds and proof script commands
# extracts `///` markdown javadocs via therapi, which requires JDK 23+.
# `--release=21` is still set!
env:
JAVA_VERSION: 21
JAVA_VERSION: 25


jobs:
Expand All @@ -29,7 +32,7 @@ jobs:
uses: gradle/actions/setup-gradle@v6

- name: Build with Gradle
run: ./gradlew --parallel assemble javadoc alldoc
run: ./gradlew --parallel assemble javadoc alldoc :key.core:generateVarcondDoc :key.core:generateScriptDoc

- name: Upload ShadowJars (fat and slim)
uses: actions/upload-artifact@v7
Expand All @@ -40,6 +43,14 @@ jobs:
path: "*/build/libs/*-exe.jar"
retention-days: 1

- name: Upload varcond and proof script documentation
uses: actions/upload-artifact@v7
with:
name: varcond-script-docs
path: "key.core/build/docs/keydocs/*"
retention-days: 30
compression-level: '9'

- name: Package
run: tar cvf key-javadoc.tar.xz build/docs/javadoc

Expand Down
2 changes: 0 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ subprojects {
implementation(libs.slf4j.api)
testImplementation(libs.logback.classic)


compileOnly(libs.jspecify)
testCompileOnly(libs.jspecify)
compileOnly(libs.checkerframework.qual)
Expand Down Expand Up @@ -316,7 +315,6 @@ subprojects {
afterEvaluate {
description = project.description
assert (project.description != null && project.description != "") : "Description of modules are required at maven-central"
print(project.description)
}
url = 'https://key-project.org/'

Expand Down
6 changes: 6 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ stringtemplate = "4.3.4"
javapoet = "1.13.0"
javaparser = "3.28.0-K13.6"
truth = "1.4.5"
therapi = "0.13.0"

# UI and CLI
flatlaf = "3.7.2"
Expand All @@ -35,6 +36,7 @@ docking-frames = "1.1.3p1"
# External tools
scala-isabelle = "0.4.5"


[libraries]
# SLF4J and logging
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
Expand All @@ -43,6 +45,10 @@ logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "lo
# JSpecify (nullability annotations)
jspecify = { module = "org.jspecify:jspecify", version.ref = "jspecify" }

#Extracting Javadoc
therapi-processor = { module = "com.github.therapi:therapi-runtime-javadoc-scribe", version.ref = "therapi" }
therapi-runtime = { module = "com.github.therapi:therapi-runtime-javadoc", version.ref = "therapi" }

# EISOP Checker Framework
checkerframework-qual = { module = "io.github.eisop:checker-qual", version.ref = "eisop" }
checkerframework-util = { module = "io.github.eisop:checker-util", version.ref = "eisop" }
Expand Down
37 changes: 36 additions & 1 deletion key.core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ dependencies {
testImplementation(libs.truth)
testImplementation(project(":key.core"))

annotationProcessor(libs.therapi.processor)
api(libs.therapi.runtime)

// https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml
testImplementation(libs.jackson.dataformat.yaml)

Expand All @@ -32,7 +35,7 @@ dependencies {
}

tasks.withType(JavaCompile).configureEach {
options.compilerArgs << "-Ajavadoc.packages=de.uka.ilkd.key.scripts"
options.compilerArgs << "-Ajavadoc.packages=de.uka.ilkd.key.scripts,de.uka.ilkd.key.rule.conditions"
}

// The target directory for JavaCC (parser generation)
Expand Down Expand Up @@ -67,6 +70,38 @@ tasks.register('generateSMTListings') {
}
}

// Generates the markdown documentation of all variable conditions (varconds),
// see de.uka.ilkd.key.doc.VarcondDoc.
tasks.register('generateVarcondDoc', JavaExec) {
group = 'documentation'
description = 'Generates the markdown documentation of all variable conditions (varconds).'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'de.uka.ilkd.key.doc.VarcondDoc'
def mdFile = layout.buildDirectory.file("docs/keydocs/varconds.md")
def jsonFile = layout.buildDirectory.file("docs/keydocs/varconds.json")
outputs.file(mdFile)
outputs.file(jsonFile)
doFirst {
args = [mdFile.get().asFile.absolutePath, jsonFile.get().asFile.absolutePath ]
}
}

// Generates the markdown documentation of all proof script commands,
// see de.uka.ilkd.key.doc.ScriptDoc.
tasks.register('generateScriptDoc', JavaExec) {
group = 'documentation'
description = 'Generates the markdown documentation of all proof script commands.'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'de.uka.ilkd.key.doc.ScriptDoc'
def mdFile = layout.buildDirectory.file("docs/keydocs/script-commands.md")
def jsonFile = layout.buildDirectory.file("docs/keydocs/script-commands.json")
outputs.file(mdFile)
outputs.file(jsonFile)
doFirst {
args = [mdFile.get().asFile.absolutePath, jsonFile.get().asFile.absolutePath ]
}
}

tasks.register('generateSolverPropsList') {
def pack = "de/uka/ilkd/key/smt/solvertypes"
def resourcesDir = "${project.projectDir}/src/main/resources"
Expand Down
202 changes: 202 additions & 0 deletions key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
/* This file is part of KeY - https://key-project.org
* KeY is licensed under the GNU General Public License Version 2,
* or (at your option) any later version.
* SPDX-License-Identifier: GPL-2.0-or-later */
package de.uka.ilkd.key.doc;

import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;

import org.jspecify.annotations.Nullable;

/**
* Base class for the documentation generators of KeY's taclet language constructs, e.g., for the
* variable conditions ({@link VarcondDoc}) and the proof script commands ({@link ScriptDoc}). It
* provides the shared handling of the output target and the post-processing of javadoc text.
*
* @author Alexander Weigl
* @version 1 (23.08.26)
*/
public abstract class AbstractDocGenerator {

/// Runs this generator. If a command line argument is given, the markdown output is written
/// to that file together with a JSON dump ([#generateJsonData()]) next to it; otherwise the
/// markdown is printed to stdout.
///
/// @param mdFile an optional single argument with the path of the output file
/// @param jsonFile
/// @throws IOException if the output file cannot be written
protected void run(String mdFile, String jsonFile) throws IOException {
Path mdPath = Path.of(mdFile);
if (mdPath.getParent() != null) {
Files.createDirectories(mdPath.getParent());
}

try (var out = new PrintStream(Files.newOutputStream(mdPath), false)) {
generateDocumentation(out);
}


Object data = generateJsonData();

if (data != null) {
Path jsonPath = Paths.get(jsonFile);
if (jsonPath.getParent() != null) {
Files.createDirectories(jsonPath.getParent());
}
try (var out = new PrintWriter(Files.newOutputStream(jsonPath), false)) {
JsonWriter.toJson(data, out);
}
}
}

/// Writes the documentation of this generator in markdown format.
protected abstract void generateDocumentation(PrintStream out);

/// Returns the documentation data of this generator in a structured form, which is serialized
/// into a JSON dump next to the markdown file. Returns `null` if this generator does not
/// support a JSON dump.
///
/// @return the structured documentation data, or `null`
protected @Nullable Object generateJsonData() {
return null;
}

/// Converts a javadoc comment into markdown by replacing common HTML tags and inline tags
/// with their markdown equivalents.
///
/// @param it the javadoc comment, may be null
/// @return the comment as markdown
protected static String cleanJavadoc(@Nullable String it) {
if (it == null) {
it = "";
}
return it.replace("<tt>", "`")
.replace("<ul>", "\n")
.replace("</ul>", "\n")
.replace("<ul>", "\n")
.replace("<li>", "* ")
.replace("</li>", "")
.replace("{@link", "`")
.replace("}", "`")
.replace("<code>", "`")
.replace("</tt>", "`")
.replace("</code>", "`")
.replace("<b>", "**")
.replace("</b>", "**");
}

/// Indents each line of the given text by the given prefix.
///
/// @param spaces the indentation prefix
/// @param it the text to indent
/// @return the indented text
protected static String indent(String spaces, String it) {
return spaces + it.replace("\n", "\n" + spaces);
}
}


/**
* A minimal, dependency-free JSON serializer supporting the data structures used by the
* documentation generators: {@link Map}s, {@link Iterable}s, strings, numbers, booleans, and
* {@code null}. Other objects are serialized via their {@link Object#toString()}.
*
* @author Alexander Weigl
* @version 1 (10.10.26)
*/
final class JsonWriter {

private JsonWriter() {
}

/**
* Serializes the given value into a pretty-printed JSON string.
*
* @param value the value to serialize
* @param out target to write into
*/
public static void toJson(@Nullable Object value, PrintWriter out) {
write(out, value, 0);
}

private static void write(PrintWriter sb, @Nullable Object value, int depth) {
switch (value) {
case null -> sb.append("null");
case String s -> writeString(sb, s);
case Boolean b -> sb.print(b);
case Number n -> sb.print(n);
case Map<?, ?> map -> writeObject(sb, map, depth);
case Iterable<?> iterable -> writeArray(sb, iterable, depth);
default -> writeString(sb, value.toString());
}
}

private static void writeObject(PrintWriter sb, Map<?, ?> map, int depth) {
sb.append("{\n");
var it = map.entrySet().iterator();
while (it.hasNext()) {
var entry = it.next();
indent(sb, depth + 1);
writeString(sb, String.valueOf(entry.getKey()));
sb.append(": ");
write(sb, entry.getValue(), depth + 1);
if (it.hasNext()) {
sb.append(',');
}
sb.append('\n');
}
indent(sb, depth);
sb.append('}');
}

private static void writeArray(PrintWriter sb, Iterable<?> iterable, int depth) {
sb.append("[\n");
var it = iterable.iterator();
while (it.hasNext()) {
indent(sb, depth + 1);
write(sb, it.next(), depth + 1);
if (it.hasNext()) {
sb.append(',');
}
sb.append('\n');
}
indent(sb, depth);
sb.append(']');
}

private static void writeString(PrintWriter sb, String s) {
sb.append('"');
for (var i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '"' -> sb.append("\\\"");
case '\\' -> sb.append("\\\\");
case '\n' -> sb.append("\\n");
case '\r' -> sb.append("\\r");
case '\t' -> sb.append("\\t");
case '\b' -> sb.append("\\b");
case '\f' -> sb.append("\\f");
default -> {
if (c < 0x20) {
sb.append("\\u%04x".formatted((int) c));
} else {
sb.append(c);
}
}
}
}
sb.append('"');
}

private static void indent(PrintWriter sb, int depth) {
sb.append(" ".repeat(depth));
}
}
\newLocalVars(varDeclsSV: VARIABLE, updateBeforeSV: VARIABLE, updateFrameSV: VARIABLE, bodySV: VARIABLE)

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.slicing)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.slicing)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.core.wd)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.core.wd)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testRunAllFunProofs, ubuntu-latest, 21)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testRunAllFunProofs, ubuntu-latest, 21)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.ui)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.ui)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.core)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.core)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testRunAllInfProofs, ubuntu-latest, 21)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testRunAllInfProofs, ubuntu-latest, 21)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.caching)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testMt4w, ubuntu-latest, 21)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.caching)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testMt4w, ubuntu-latest, 21)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testMt2w, ubuntu-latest, 21)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testMt2w, ubuntu-latest, 21)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.core.testgen)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.core.testgen)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.proofmanagement)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.proofmanagement)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.core.infflow)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.core.infflow)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testRunAllWdProofs, ubuntu-latest, 21)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testRunAllWdProofs, ubuntu-latest, 21)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.ui.testgen)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.ui.testgen)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.core.example)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, key.core.example)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.isabelletranslation)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.isabelletranslation)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testMtStress, ubuntu-latest, 21)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testMtStress, ubuntu-latest, 21)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.exploration)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / unit-tests (ubuntu-latest, 21, keyext.exploration)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testProveRules, ubuntu-latest, 21)

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / integration-tests (testProveRules, ubuntu-latest, 21)

illegal character: '\'

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / checkerFramework

class, interface, enum, or record expected

Check failure on line 201 in key.core/src/main/java/de/uka/ilkd/key/doc/AbstractDocGenerator.java

View workflow job for this annotation

GitHub Actions / checkerFramework

illegal character: '\'

Loading
Loading