From f75aec2a0f1369bd14ff6f13bfdfe0a98af622f8 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Sat, 29 Apr 2023 18:37:44 +0300 Subject: [PATCH 01/27] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20ve?= =?UTF-8?q?locity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 10 ----- .../ru/alkoleft/bsl/doc/render/Factory.java | 9 ---- .../render/velocity/VelocityItemRender.java | 42 ------------------ .../velocity/VelocityRenderContext.java | 44 ------------------- 4 files changed, 105 deletions(-) delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/velocity/VelocityItemRender.java delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/velocity/VelocityRenderContext.java diff --git a/build.gradle.kts b/build.gradle.kts index 0c995c9..0b42e3f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -51,8 +51,6 @@ dependencies { // template engine implementation("com.github.jknack:handlebars:4.3.1") - implementation("org.apache.velocity:velocity-engine-core:2.3") - implementation("org.apache.velocity:velocity-tools:2.0") testImplementation("org.junit.jupiter:junit-jupiter:$JUINT_VERSION") testImplementation("org.junit.jupiter:junit-jupiter-api:$JUINT_VERSION") @@ -74,17 +72,11 @@ tasks.withType { } tasks.jar { -// manifest { -// attributes["Main-Class"] = "ru.alkoleft.bsl.doc.Main" -// } enabled = true archiveClassifier.set("") } tasks.bootJar { -// manifest { -// attributes["Main-Class"] = "ru.alkoleft.bsl.doc.Main" -// } archiveClassifier.set("exec") } @@ -107,8 +99,6 @@ tasks { group = "build" } - - publishing { repositories { maven { diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/Factory.java b/src/main/java/ru/alkoleft/bsl/doc/render/Factory.java index 3bf7b1c..8616227 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/Factory.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/Factory.java @@ -2,19 +2,10 @@ import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.render.handlebars.HandlebarsRenderContext; -import ru.alkoleft.bsl.doc.render.velocity.VelocityRenderContext; @UtilityClass public class Factory { - public Render createRender(RenderOptions options) { - return new Render(null); - } - public RenderContext createRenderContext(RenderOptions options) { return new HandlebarsRenderContext(options.getOutputFormat().getPath()); } - - public RenderContext createVelocityRenderContext(RenderOptions options) { - return new VelocityRenderContext(options.getOutputFormat().getPath()); - } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/velocity/VelocityItemRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/velocity/VelocityItemRender.java deleted file mode 100644 index b54d579..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/render/velocity/VelocityItemRender.java +++ /dev/null @@ -1,42 +0,0 @@ -package ru.alkoleft.bsl.doc.render.velocity; - -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import ru.alkoleft.bsl.doc.render.ItemRender; - -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.StringWriter; -import java.nio.file.Path; - -public class VelocityItemRender implements ItemRender { - private final Template template; - - VelocityItemRender(Template template) { - this.template = template; - } - - VelocityContext context = new VelocityContext(); - - public void put(String key, Object value) { - context.put(key, value); - } - - public void renderToFile(Path fileName) throws IOException { - try (FileWriter writer = new FileWriter(fileName.toFile())) { - template.merge(context, writer); - } - } - - public String renderToString() { - StringWriter writer = new StringWriter(); - template.merge(context, writer); - return writer.toString(); - } - - public void renderToConsole() { - template.merge(context, new BufferedWriter(new OutputStreamWriter(System.out))); - } -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/velocity/VelocityRenderContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/velocity/VelocityRenderContext.java deleted file mode 100644 index 2bfafb6..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/render/velocity/VelocityRenderContext.java +++ /dev/null @@ -1,44 +0,0 @@ -package ru.alkoleft.bsl.doc.render.velocity; - -import org.apache.velocity.Template; -import org.apache.velocity.app.VelocityEngine; -import ru.alkoleft.bsl.doc.bsl.BslContext; -import ru.alkoleft.bsl.doc.render.ItemRender; -import ru.alkoleft.bsl.doc.render.RenderContext; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.StringWriter; -import java.util.Properties; - -public class VelocityRenderContext implements RenderContext { - VelocityEngine velocityEngine; - String path; - - public VelocityRenderContext(String name) { - path = name; - - velocityEngine = new VelocityEngine(); - Properties properties = new Properties(); - properties.setProperty("resource.loaders", "file"); -// properties.setProperty("runtime.log.logsystem.class", "org.apache.velocity.runtime.log.AvalonLogChute"); - properties.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); - velocityEngine.init(properties); - velocityEngine.init(); - } - - public Template getTemplate(String name) { - return velocityEngine.getTemplate(String.format("%s/%s.vm", path, name)); - } - - @Override - public ItemRender getRender(String name) throws IOException { - return new VelocityItemRender(getTemplate(name)); - } - - @Override - public void setContext(BslContext context) { - - } -} From ff6880e05a0a3a494cb10fd9ae7b74c69bcc235b Mon Sep 17 00:00:00 2001 From: alkoleft Date: Sun, 30 Apr 2023 01:53:58 +0300 Subject: [PATCH 02/27] =?UTF-8?q?=D0=92=D1=81=D1=82=D1=80=D0=BE=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D0=BE=D0=B5=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=81=D1=81=D1=8B=D0=BB=D0=BE=D0=BA=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B5=D0=BF=D1=83=D0=B1=D0=BB=D0=B8=D0=BA=D1=83?= =?UTF-8?q?=D0=B5=D0=BC=D1=8B=D0=B5=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/alkoleft/bsl/doc/bsl/BslContext.java | 50 +++++++++++++++++- .../java/ru/alkoleft/bsl/doc/bsl/Links.java | 51 +++++++++++++++++++ .../ru/alkoleft/bsl/doc/bsl/MethodInfo.java | 13 +++++ .../alkoleft/bsl/doc/bsl/ModuleContext.java | 6 ++- .../bsl/doc/bsl/symbols/MethodSymbol.java | 23 ++++++++- .../ru/alkoleft/bsl/doc/render/Render.java | 1 - .../doc/render/handlebars/HandleLinks.java | 38 ++++++++++---- .../bsl/doc/render/handlebars/Shifter.java | 13 +++-- src/main/resources/docusaurus/module.hbs | 2 +- .../resources/docusaurus/value-definition.hbs | 5 +- 10 files changed, 178 insertions(+), 24 deletions(-) create mode 100644 src/main/java/ru/alkoleft/bsl/doc/bsl/Links.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/bsl/MethodInfo.java diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java index 9d42d1d..aab791f 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java @@ -1,11 +1,11 @@ package ru.alkoleft.bsl.doc.bsl; -import com.github._1c_syntax.bsl.languageserver.utils.Trees; import com.github._1c_syntax.bsl.parser.BSLParser; import com.github._1c_syntax.bsl.parser.BSLTokenizer; import com.github._1c_syntax.bsl.types.MDOType; import com.github._1c_syntax.mdclasses.Configuration; import com.github._1c_syntax.mdclasses.mdo.MDCommonModule; +import com.google.common.base.Strings; import org.antlr.v4.runtime.Token; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbolComputer; @@ -16,14 +16,21 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; public class BslContext { + + private static BslContext current; + + public static BslContext getCurrent() { + return current; + } + Configuration configuration; Filter filter; - List modules = Collections.emptyList(); private static final Set VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH = Set.of( @@ -35,6 +42,7 @@ public class BslContext { public BslContext(Path path, Filter filter) { this.filter = filter; configuration = Configuration.create(path); + current = this; } public Stream getModules() { @@ -48,6 +56,10 @@ public boolean contains(String name) { return modules.stream().anyMatch(it -> it.getName().equalsIgnoreCase(name)); } + public Optional getModule(String name) { + return modules.stream().filter(it -> it.getName().equalsIgnoreCase(name)).findAny(); + } + public void load() { modules = configuration.getOrderedTopMDObjects().get(MDOType.COMMON_MODULE).stream() .map(MDCommonModule.class::cast) @@ -142,6 +154,15 @@ private ModuleContext buildModuleContext(ModuleContext module) { .build(); } + private boolean checkModule(ModuleContext module) { + return true; + } + + private boolean checkMethod(MethodSymbol method) { + return (!filter.isExport() || method.isExport()) + && (filter.getRegions().isEmpty() || regionFilter(method)); + } + private boolean regionFilter(MethodSymbol m) { var region = m.getRegion(); @@ -191,4 +212,29 @@ private static boolean isBlankLine(Token previousToken, Token currentToken) { && (previousToken.getTokenIndex() == 0 || (previousToken.getLine() + 1) != currentToken.getLine()); } + + public MethodInfo getMethodInfo(String link) { + if (Strings.isNullOrEmpty(link)) { + return null; + } + var linkInfo = Links.parseLink(link, false); + return getMethodInfo(linkInfo); + } + + public MethodInfo getMethodInfo(Links.Link link) { + + + if (link == null || link.getOwnerName() == null || link.getMethodName() == null) { + return null; + } + + var module = getModule(link.getOwnerName()); + var method = module.flatMap(it -> it.getMethod(link.getMethodName())); + + return MethodInfo.builder() + .module(module.orElse(null)) + .method(method.orElse(null)) + .publishing(module.isPresent() && method.isPresent() && checkModule(module.get()) && checkMethod(method.get())) + .build(); + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/Links.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/Links.java new file mode 100644 index 0000000..2f2abbb --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/Links.java @@ -0,0 +1,51 @@ +package ru.alkoleft.bsl.doc.bsl; + +import com.google.common.base.Strings; +import lombok.AllArgsConstructor; +import lombok.Value; +import lombok.experimental.UtilityClass; + +import java.util.regex.Pattern; + +@UtilityClass +public class Links { + private final Pattern patternWithSee = Pattern.compile("^см\\. (([\\wА-Яа-я\\.\\d]+)\\.)*([\\wА-Яа-я\\d]+)$"); + private final Pattern pattern = Pattern.compile("^(([\\wА-Яа-я\\.\\d]+)\\.)*([\\wА-Яа-я\\d]+)$"); + + public Link parseLink(String link, boolean withSee) { + var matcher = (withSee ? patternWithSee : pattern).matcher(link); + if (matcher.find()) { + return createLink(matcher.group(2), matcher.group(3)); + } + return null; + } + + public Link createLink(String owner, String method) { + if (owner != null && method != null) { + return new Link(owner, method); + } else if (BslContext.getCurrent().contains(method)) { + return new Link(method, null); + } else if (method != null) { + return new Link(null, method); + } else { + return null; + } + } + + @Value + @AllArgsConstructor + public static class Link { + String ownerName; + String methodName; + + public String getFullName() { + if (Strings.isNullOrEmpty(ownerName)) { + return methodName; + } else if (Strings.isNullOrEmpty(methodName)) { + return ownerName; + } else { + return ownerName + "." + methodName; + } + } + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/MethodInfo.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/MethodInfo.java new file mode 100644 index 0000000..9f39fb7 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/MethodInfo.java @@ -0,0 +1,13 @@ +package ru.alkoleft.bsl.doc.bsl; + +import lombok.Builder; +import lombok.Value; +import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; + +@Value +@Builder +public class MethodInfo { + MethodSymbol method; + ModuleContext module; + boolean publishing; +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleContext.java index 219270a..5b7557d 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleContext.java @@ -1,12 +1,12 @@ package ru.alkoleft.bsl.doc.bsl; import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; -import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Value; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; import java.util.List; +import java.util.Optional; @Builder @Value @@ -22,4 +22,8 @@ public String getName() { public boolean isNotEmpty() { return methods != null && !methods.isEmpty(); } + + public Optional getMethod(String name) { + return getMethods().stream().filter(it -> name.equalsIgnoreCase(it.getName())).findAny(); + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java index 6e033cb..c6724c9 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java @@ -4,6 +4,8 @@ import com.google.common.base.Strings; import lombok.Builder; import lombok.Value; +import lombok.extern.slf4j.Slf4j; +import ru.alkoleft.bsl.doc.bsl.BslContext; import java.util.Collections; import java.util.List; @@ -11,12 +13,14 @@ @Builder @Value +@Slf4j public class MethodSymbol { boolean deprecated; boolean function; boolean export; String name; Optional fullDescription; + List parameters; RegionSymbol region; @@ -32,9 +36,26 @@ public TypeDescription getReturnedValue() { var result = fullDescription.map(MethodDescription::getReturnedValue).filter(it -> !it.isEmpty()).map(it -> it.get(0)).orElse(null); if (result != null) { - return new TypeDescription(result.getName(), result.getDescription(), result.getParameters(), Strings.isNullOrEmpty(result.getLink()) ? null : "см. " + result.getLink(), result.isHyperlink()); + return createTypeDescription(result); } else { return null; } } + + private TypeDescription createTypeDescription(com.github._1c_syntax.bsl.languageserver.context.symbol.description.TypeDescription baseDescription) { + TypeDescription result = null; + if (!Strings.isNullOrEmpty(baseDescription.getLink())) { + var methodInfo = BslContext.getCurrent().getMethodInfo(baseDescription.getLink()); + + if (methodInfo != null && methodInfo.getMethod() != null) { + result = methodInfo.getMethod().getReturnedValue(); + } else { + log.warn("Bad link: " + baseDescription.getLink()); + } + } + if (result == null) { + result = new TypeDescription(baseDescription.getName(), baseDescription.getDescription(), baseDescription.getParameters(), Strings.isNullOrEmpty(baseDescription.getLink()) ? null : "см. " + baseDescription.getLink(), baseDescription.isHyperlink()); + } + return result; + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java index 94b6a44..5ed37f9 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java @@ -4,7 +4,6 @@ import lombok.SneakyThrows; import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.bsl.ModuleContext; -import ru.alkoleft.bsl.doc.render.RenderContext; import java.nio.file.Path; import java.util.concurrent.atomic.AtomicInteger; diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java index 86a1585..bbc0468 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java @@ -1,35 +1,51 @@ package ru.alkoleft.bsl.doc.render.handlebars; +import com.github.jknack.handlebars.Context; import com.github.jknack.handlebars.Helper; import com.github.jknack.handlebars.Options; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import ru.alkoleft.bsl.doc.bsl.BslContext; +import ru.alkoleft.bsl.doc.bsl.Links; -import java.io.IOException; import java.util.Locale; import java.util.regex.Pattern; +@Slf4j public class HandleLinks implements Helper { Pattern pattern = Pattern.compile("см\\. (([\\wА-Яа-я\\.\\d]+)\\.)*([\\wА-Яа-я\\d]+)"); BslContext context; @Override - public Object apply(String context, Options options) throws IOException { + public Object apply(String context, Options options) { + var matcher = pattern.matcher(context); if (matcher.find()) { - return matcher.replaceAll(matchResult -> String.format("[%s](%s)", matchResult.group(0), getLink(matcher.group(2), matcher.group(3)))); + return matcher.replaceAll(matchResult -> replaceTo(matcher.group(0), Links.createLink(matcher.group(2), matcher.group(3)), options)); } return context; } - private String getLink(String owner, String method) { - if (owner != null && method != null) { - return owner + "#" + method.toLowerCase(Locale.ROOT); - } else if (context.contains(method)) { - return method; - } else if (method != null) { - return "#" + method.toLowerCase(Locale.ROOT); - } else{ + @SneakyThrows + private String replaceTo(String baseValue, Links.Link link, Options options) { + var methodInfo = BslContext.getCurrent().getMethodInfo(link); + if (methodInfo == null || methodInfo.isPublishing()) { + return String.format("[%s](%s)", baseValue, getLink(link)); + } + + var context = Context.newBuilder(methodInfo.getMethod().getReturnedValue()).build(); + return baseValue + options.apply(options.fn, context).toString(); + } + + private String getLink(Links.Link link) { + if (link.getOwnerName() != null && link.getMethodName() != null) { + return link.getOwnerName() + "#" + link.getMethodName().toLowerCase(Locale.ROOT); + } else if (link.getOwnerName() != null) { + return link.getOwnerName(); + } else if (link.getMethodName() != null) { + return "#" + link.getMethodName().toLowerCase(Locale.ROOT); + } else { return ""; } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/Shifter.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/Shifter.java index 703434b..b7aed18 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/Shifter.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/Shifter.java @@ -10,13 +10,16 @@ public class Shifter implements Helper { @Override public Object apply(Object context, Options options) throws IOException { - Options.Buffer buffer = options.buffer(); - int startedShift = shift; + var buffer = options.buffer(); + var startedShift = shift; + + int delta = context instanceof Integer ? (Integer) context : 0; + shift += delta; shift++; var content = options.fn(); - shift--; - if (startedShift > 0) { - var newChar = "\n" + new String(new char[startedShift]).replace('\0', '\t'); + shift = startedShift; + if (startedShift + delta > 0) { + var newChar = "\n" + new String(new char[2 * (startedShift + delta)]).replace('\0', ' '); buffer.append(content.toString().replace("\n", newChar)); } else { buffer.append(content); diff --git a/src/main/resources/docusaurus/module.hbs b/src/main/resources/docusaurus/module.hbs index 9ed483f..92927b4 100644 --- a/src/main/resources/docusaurus/module.hbs +++ b/src/main/resources/docusaurus/module.hbs @@ -25,7 +25,7 @@ title: {{name}} {{#each parameters as | parameter|}} * `{{parameter.name}}` {{~#each parameter.types as | type typeIndex|}} - * `{{type.name}}` - {{links type.description}} + * {{#with type}}{{#shift 3}}{{#block "docusaurus/value-definition"}}{{/block}}{{/shift}}{{~/with}} {{~else}} - {{links description}} {{~/each}} {{~/each}} diff --git a/src/main/resources/docusaurus/value-definition.hbs b/src/main/resources/docusaurus/value-definition.hbs index 793e2c4..ed01455 100644 --- a/src/main/resources/docusaurus/value-definition.hbs +++ b/src/main/resources/docusaurus/value-definition.hbs @@ -1,8 +1,9 @@ {{~#if link~}} {{links link}} {{~/if}} -{{~#if parameters}}
{{description}} ({{name}}) -{{~else}}`{{name}}` - {{links description}} +{{~#if parameters}} +
{{description}} ({{name}}) +{{~else}}`{{name}}` - {{#links description}}{{#block "docusaurus/value-definition"}}{{/block}}{{/links}} {{~/if}} {{~#if parameters}} {{/if}} From ae5957e8b536085daba493edaead22cd6e8dbb76 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Mon, 1 May 2023 02:29:05 +0300 Subject: [PATCH 03/27] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=B2=D1=8B=D1=8F=D0=B2=D0=BB=D0=B5=D0=BD=D0=BD=D1=8B=D1=85=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B1=D0=BB=D0=B5=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 19 ------- .../ru/alkoleft/bsl/doc/bsl/BslContext.java | 6 ++- .../java/ru/alkoleft/bsl/doc/bsl/Filter.java | 3 ++ .../bsl/doc/bsl/symbols/MethodSymbol.java | 6 +++ .../doc/bsl/symbols/MethodSymbolComputer.java | 54 ++++++++++++++----- .../bsl/doc/bsl/symbols/RegionSymbol.java | 1 + .../bsl/doc/commands/RenderCommand.java | 24 +++++---- .../bsl/doc/render/RenderOptions.java | 5 -- .../doc/render/handlebars/HandleLinks.java | 2 +- src/main/resources/docusaurus/module.hbs | 7 ++- 10 files changed, 75 insertions(+), 52 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0b42e3f..acb6725 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -80,25 +80,6 @@ tasks.bootJar { archiveClassifier.set("exec") } -tasks { - val fatJar = register("fatJar") { - dependsOn.addAll(listOf("compileJava", "processResources")) // We need this for Gradle optimization to work - archiveClassifier.set("standalone") // Naming the jar - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - manifest { attributes(mapOf("Main-Class" to application.mainClass)) } // Provided we set it up in the application plugin configuration - val sourcesMain = sourceSets.main.get() - val contents = configurations.runtimeClasspath.get() - .map { if (it.isDirectory) it else zipTree(it) } + - sourcesMain.output - from(contents) - } - build { - dependsOn(fatJar) // Trigger fat jar creation during build - } - - group = "build" -} - publishing { repositories { maven { diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java index aab791f..e3a1e8f 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java @@ -6,6 +6,7 @@ import com.github._1c_syntax.mdclasses.Configuration; import com.github._1c_syntax.mdclasses.mdo.MDCommonModule; import com.google.common.base.Strings; +import lombok.extern.slf4j.Slf4j; import org.antlr.v4.runtime.Token; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbolComputer; @@ -21,6 +22,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +@Slf4j public class BslContext { private static BslContext current; @@ -69,7 +71,9 @@ public void load() { private ModuleContext buildModuleContext(MDCommonModule module) { var bslModules = module.getModules(); - var srcPath = Path.of(bslModules.get(0).getUri()); + var bslModule = bslModules.get(0); + log.debug("Parse module: " + bslModule.getOwner().getName() + "." + bslModule.getModuleType()); + var srcPath = Path.of(bslModule.getUri()); List methods; String description; try { diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java index 8341efd..58c444f 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java @@ -12,4 +12,7 @@ public class Filter { boolean isExport; @Singular List regions; + @Singular + List rootSubsystems; + } diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java index c6724c9..66868a9 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java @@ -3,8 +3,11 @@ import com.github._1c_syntax.bsl.languageserver.context.symbol.description.MethodDescription; import com.google.common.base.Strings; import lombok.Builder; +import lombok.Setter; import lombok.Value; +import lombok.experimental.NonFinal; import lombok.extern.slf4j.Slf4j; +import org.eclipse.lsp4j.Range; import ru.alkoleft.bsl.doc.bsl.BslContext; import java.util.Collections; @@ -22,7 +25,10 @@ public class MethodSymbol { Optional fullDescription; List parameters; + @Setter + @NonFinal RegionSymbol region; + Range range; public String getDescription() { return fullDescription.map(MethodDescription::getPurposeDescription).orElse(""); diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbolComputer.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbolComputer.java index e9e14ee..9c0dca9 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbolComputer.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbolComputer.java @@ -6,6 +6,7 @@ import com.github._1c_syntax.bsl.parser.BSLParser; import com.github._1c_syntax.bsl.parser.BSLParserBaseVisitor; import com.github._1c_syntax.bsl.parser.BSLTokenizer; +import lombok.extern.slf4j.Slf4j; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.TerminalNode; @@ -19,16 +20,27 @@ import java.util.Stack; import java.util.stream.Collectors; +@Slf4j public class MethodSymbolComputer extends BSLParserBaseVisitor { private final List methods = new ArrayList<>(); private BSLTokenizer tokenizer; - Stack regions = new Stack<>(); + List regionData = new ArrayList<>(); + Stack regions = new Stack<>(); public List compute(BSLTokenizer tokenizer) { this.tokenizer = tokenizer; methods.clear(); visitFile(tokenizer.getAst()); + + // Используется постпривязка регионов, тк порядок обхода не соответствует порядку следования объект (в метод заходит раньше региона) + for (var region : regionData) { + for (var method : methods) { + if (Ranges.containsRange(region.range, method.getRange())) { + method.setRegion(region.region); + } + } + } return methods; } @@ -36,35 +48,44 @@ public List compute(BSLTokenizer tokenizer) { public ParseTree visitRegionStart(BSLParser.RegionStartContext ctx) { var name = ctx.regionName().getText(); - RegionSymbol region; + log.debug("Start region: " + name); + var data = new RegionData(); + data.start = ctx; if (regions.isEmpty()) { - region = new RegionSymbol(name, null); + data.region = new RegionSymbol(name, null); } else { - region = new RegionSymbol(name, regions.peek()); + data.region = new RegionSymbol(name, regions.peek().region); } - regions.push(region); + regions.push(data); + regionData.add(data); return super.visitRegionStart(ctx); } @Override public ParseTree visitRegionEnd(BSLParser.RegionEndContext ctx) { - regions.pop(); + if (!regions.isEmpty()) { + var regionData = regions.pop(); + log.debug("End region: " + regionData.region.getName()); + regionData.end = ctx; + regionData.range = Ranges.create(regionData.start, regionData.end); + } return super.visitRegionEnd(ctx); } @Override public ParseTree visitFunction(BSLParser.FunctionContext ctx) { - BSLParser.FuncDeclarationContext declaration = ctx.funcDeclaration(); - - TerminalNode startNode = declaration.FUNCTION_KEYWORD(); + var declaration = ctx.funcDeclaration(); + log.debug("Function: " + declaration.subName().getText()); + var startNode = declaration.FUNCTION_KEYWORD(); handleMethod(startNode, declaration.subName().getStart(), declaration.paramList(), true, declaration.EXPORT_KEYWORD() != null); return super.visitFunction(ctx); } @Override public ParseTree visitProcedure(BSLParser.ProcedureContext ctx) { - BSLParser.ProcDeclarationContext declaration = ctx.procDeclaration(); + var declaration = ctx.procDeclaration(); + log.debug("Procedure: " + declaration.subName().getText()); TerminalNode startNode = declaration.PROCEDURE_KEYWORD(); handleMethod(startNode, declaration.subName().getStart(), declaration.paramList(), false, declaration.EXPORT_KEYWORD() != null); @@ -72,8 +93,8 @@ public ParseTree visitProcedure(BSLParser.ProcedureContext ctx) { } private void handleMethod(TerminalNode startNode, Token subName, BSLParser.ParamListContext paramList, boolean function, boolean export) { - Optional description = createDescription(startNode.getSymbol()); - boolean deprecated = description + var description = createDescription(startNode.getSymbol()); + var deprecated = description .map(MethodDescription::isDeprecated) .orElse(false); @@ -84,7 +105,7 @@ private void handleMethod(TerminalNode startNode, Token subName, BSLParser.Param .fullDescription(description) .deprecated(deprecated) .parameters(createParameters(paramList, description)) - .region(regions.peek()) + .range(Ranges.create(startNode)) .build(); methods.add(method); } @@ -177,4 +198,11 @@ private Optional createDescription(Token token) { return Optional.of(new MethodDescription(comments)); } + + private static class RegionData { + RegionSymbol region; + BSLParser.RegionStartContext start; + BSLParser.RegionEndContext end; + Range range; + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/RegionSymbol.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/RegionSymbol.java index a00668c..c29d700 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/RegionSymbol.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/RegionSymbol.java @@ -13,4 +13,5 @@ public class RegionSymbol { String name; RegionSymbol parent; + } diff --git a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java index 84d8b0f..6c4184f 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java +++ b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java @@ -1,33 +1,33 @@ package ru.alkoleft.bsl.doc.commands; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import picocli.CommandLine.Command; import picocli.CommandLine.Option; import picocli.CommandLine.Parameters; -import ru.alkoleft.bsl.doc.render.Render; import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.bsl.Filter; import ru.alkoleft.bsl.doc.bsl.symbols.RegionSymbol; import ru.alkoleft.bsl.doc.render.Factory; import ru.alkoleft.bsl.doc.render.OutputFormat; +import ru.alkoleft.bsl.doc.render.Render; import ru.alkoleft.bsl.doc.render.RenderOptions; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +@Slf4j @Command(helpCommand = true) public class RenderCommand implements Runnable { @Parameters(description = "source") Path sources; @Parameters(description = "destination") Path destination; - @Option(names = {"-f", "--format"}, defaultValue = "Markdown") OutputFormat format; @Option(names = {"-s", "--only-subsystems"}) List onlySubsystems; - @Option(names = {"-r", "--regions"}, split = " ", defaultValue = RegionSymbol.PUBLIC_REGION_RU + " " + RegionSymbol.PUBLIC_REGION_EN) List regions; @@ -35,19 +35,25 @@ public class RenderCommand implements Runnable { @Override public void run() { - var filter = Filter.builder() + var filterBuilder = Filter.builder() .isExport(true); - regions.forEach(filter::region); + regions.forEach(filterBuilder::region); + onlySubsystems.forEach(filterBuilder::rootSubsystem); - var options = RenderOptions.builder() + var optionsBuilder = RenderOptions.builder() .outputFormat(format) .subsystemHierarchy(true); - onlySubsystems.forEach(options::rootSubsystem); - var renderContext = Factory.createRenderContext(options.build()); + var filter = filterBuilder.build(); + var options = optionsBuilder.build(); + + log.debug("Filter: " + filter.toString()); + log.debug("Options: " + options.toString()); + + var renderContext = Factory.createRenderContext(options); var render = new Render(renderContext); - BslContext bslContext = new BslContext(sources, filter.build()); + BslContext bslContext = new BslContext(sources, filter); bslContext.load(); Files.createDirectories(destination); diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/RenderOptions.java b/src/main/java/ru/alkoleft/bsl/doc/render/RenderOptions.java index 20f9758..37bc503 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/RenderOptions.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/RenderOptions.java @@ -1,17 +1,12 @@ package ru.alkoleft.bsl.doc.render; import lombok.Builder; -import lombok.Singular; import lombok.Value; -import java.util.List; - @Builder @Value public class RenderOptions { OutputFormat outputFormat; boolean subsystemHierarchy; - @Singular - List rootSubsystems; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java index bbc0468..59f28bd 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java @@ -37,7 +37,7 @@ private String replaceTo(String baseValue, Links.Link link, Options options) { var context = Context.newBuilder(methodInfo.getMethod().getReturnedValue()).build(); return baseValue + options.apply(options.fn, context).toString(); } - + private String getLink(Links.Link link) { if (link.getOwnerName() != null && link.getMethodName() != null) { return link.getOwnerName() + "#" + link.getMethodName().toLowerCase(Locale.ROOT); diff --git a/src/main/resources/docusaurus/module.hbs b/src/main/resources/docusaurus/module.hbs index 92927b4..dc6ce44 100644 --- a/src/main/resources/docusaurus/module.hbs +++ b/src/main/resources/docusaurus/module.hbs @@ -12,10 +12,9 @@ title: {{name}} {{~/if}} ## Методы модуля - -{{~#each methods}} - +{{#each methods}} --- + ### `{{name}}` {{#if description}}{{links description}}{{/if}} @@ -48,4 +47,4 @@ title: {{name}} ``` {{/if}} -{{~/each}} +{{/each}} From dfa7addffc1220c794b8aee9294b80e620204a17 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Mon, 1 May 2023 17:20:23 +0300 Subject: [PATCH 04/27] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B8=20=D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Выделение "важных" блоков * Отметка устаревшего метода --- .../doc/render/handlebars/HandleLinks.java | 21 ++++++++++++++++--- src/main/resources/docusaurus/module.hbs | 4 ++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java index 59f28bd..5f93073 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java @@ -15,16 +15,22 @@ public class HandleLinks implements Helper { Pattern pattern = Pattern.compile("см\\. (([\\wА-Яа-я\\.\\d]+)\\.)*([\\wА-Яа-я\\d]+)"); + Pattern warningPattern = Pattern.compile("(\\n\\s*\\n|^)(Важно[\\s\\S]+)(\\n\\s*\\n|$)"); BslContext context; @Override public Object apply(String context, Options options) { - var matcher = pattern.matcher(context); + String result; if (matcher.find()) { - return matcher.replaceAll(matchResult -> replaceTo(matcher.group(0), Links.createLink(matcher.group(2), matcher.group(3)), options)); + result = matcher.replaceAll(matchResult -> replaceTo(matcher.group(0), Links.createLink(matcher.group(2), matcher.group(3)), options)); + } else { + result = context; } - return context; + + result = handleWarning(result); + + return result; } @SneakyThrows @@ -38,6 +44,15 @@ private String replaceTo(String baseValue, Links.Link link, Options options) { return baseValue + options.apply(options.fn, context).toString(); } + private String handleWarning(String content) { + // TODO Реализовать и другие блоки https://docusaurus.io/docs/markdown-features/admonitions + if (content.contains("Важно")) { + var matcher = warningPattern.matcher(content); + content = matcher.replaceAll(m -> m.group(1) + ":::tip важно\n\n" + matcher.group(2) + "\n\n:::" + matcher.group(3)); + } + return content; + } + private String getLink(Links.Link link) { if (link.getOwnerName() != null && link.getMethodName() != null) { return link.getOwnerName() + "#" + link.getMethodName().toLowerCase(Locale.ROOT); diff --git a/src/main/resources/docusaurus/module.hbs b/src/main/resources/docusaurus/module.hbs index dc6ce44..9abf6cb 100644 --- a/src/main/resources/docusaurus/module.hbs +++ b/src/main/resources/docusaurus/module.hbs @@ -17,6 +17,10 @@ title: {{name}} ### `{{name}}` +{{#if deprecated~}} +:::caution Устаревший +::: +{{~/if}} {{#if description}}{{links description}}{{/if}} {{~#if parameters}} From ad84b78a453aa2b714814f3b1fa7298f95485be2 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Tue, 5 Sep 2023 03:27:01 +0300 Subject: [PATCH 05/27] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20=D1=84=D0=BE=D1=80=D0=BC=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Для кейсов когда описывается структура с ключами. Добавлены отладочные сообщения --- build.gradle.kts | 2 +- .../ru/alkoleft/bsl/doc/bsl/BslContext.java | 13 ++++++++---- .../java/ru/alkoleft/bsl/doc/bsl/Filter.java | 2 ++ .../ru/alkoleft/bsl/doc/render/Render.java | 4 ++++ .../handlebars/HandlebarsRenderContext.java | 1 + .../doc/render/handlebars/RenderDebugger.java | 16 +++++++++++++++ src/main/resources/docusaurus/module.hbs | 4 ++-- .../resources/docusaurus/value-definition.hbs | 20 ++++++------------- 8 files changed, 41 insertions(+), 21 deletions(-) create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderDebugger.java diff --git a/build.gradle.kts b/build.gradle.kts index acb6725..5a9ce7c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,7 +33,7 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-websocket") implementation("info.picocli:picocli-spring-boot-starter:4.7.1") - implementation("com.github.1c-syntax", "bsl-language-server", "0.20.0") + implementation("io.github.1c-syntax", "bsl-language-server", "0.20.0") implementation("com.github.1c-syntax", "mdclasses", "0.10.3") implementation("io.github.1c-syntax", "bsl-common-library", "f6714e4e") diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java index e3a1e8f..5b75099 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java @@ -48,10 +48,15 @@ public BslContext(Path path, Filter filter) { } public Stream getModules() { - return modules - .stream() - .map(this::buildModuleContext) - .filter(ModuleContext::isNotEmpty); + var stream = modules.stream(); + + if (!filter.getModules().isEmpty()) { + stream = stream.filter(m -> filter.getModules().contains(m.getName())); + } + + return stream + .map(this::buildModuleContext) + .filter(ModuleContext::isNotEmpty); } public boolean contains(String name) { diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java index 58c444f..b35d1bb 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java @@ -14,5 +14,7 @@ public class Filter { List regions; @Singular List rootSubsystems; + @Singular + List modules; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java index 5ed37f9..9e1bfb9 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java @@ -2,12 +2,14 @@ import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.bsl.ModuleContext; import java.nio.file.Path; import java.util.concurrent.atomic.AtomicInteger; +@Slf4j public class Render { RenderContext renderContext; @@ -27,6 +29,8 @@ public void render(BslContext bslContext, Path output) { public void renderModule(ModuleContext module, Path outputPath, int index) { var itemRender = renderContext.getRender("module"); + log.debug("Render module " + module.getOwner().getName()); + itemRender.put("index", index); itemRender.put("name", module.getOwner().getName()); itemRender.put("present", getPresent(module.getOwner())); diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarsRenderContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarsRenderContext.java index 938c80c..b28695c 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarsRenderContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarsRenderContext.java @@ -22,6 +22,7 @@ public HandlebarsRenderContext(String path) { handlebars = new Handlebars().with(value -> value); handlebars.registerHelper("links", linksRender = new HandleLinks()); handlebars.registerHelper("shift", new Shifter()); + handlebars.registerHelper("debug", new RenderDebugger()); } public void setContext(BslContext context) { diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderDebugger.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderDebugger.java new file mode 100644 index 0000000..d7dc5b8 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderDebugger.java @@ -0,0 +1,16 @@ +package ru.alkoleft.bsl.doc.render.handlebars; + +import com.github.jknack.handlebars.Helper; +import com.github.jknack.handlebars.Options; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; + +@Slf4j +public class RenderDebugger implements Helper { + @Override + public Object apply(Object context, Options options) throws IOException { + log.debug(options.fn().toString()); + return null; + } +} diff --git a/src/main/resources/docusaurus/module.hbs b/src/main/resources/docusaurus/module.hbs index 9abf6cb..46e2bc2 100644 --- a/src/main/resources/docusaurus/module.hbs +++ b/src/main/resources/docusaurus/module.hbs @@ -15,7 +15,7 @@ title: {{name}} {{#each methods}} --- -### `{{name}}` +### `{{name}}`{{#debug}}Формирование описания метода {{name}}{{/debug}} {{#if deprecated~}} :::caution Устаревший @@ -26,7 +26,7 @@ title: {{name}} **Параметры метода** {{#each parameters as | parameter|}} -* `{{parameter.name}}` +* `{{parameter.name}}`{{#debug}}Формирование описания параметра {{parameter.name}}{{/debug}} {{~#each parameter.types as | type typeIndex|}} * {{#with type}}{{#shift 3}}{{#block "docusaurus/value-definition"}}{{/block}}{{/shift}}{{~/with}} {{~else}} - {{links description}} diff --git a/src/main/resources/docusaurus/value-definition.hbs b/src/main/resources/docusaurus/value-definition.hbs index ed01455..351c65d 100644 --- a/src/main/resources/docusaurus/value-definition.hbs +++ b/src/main/resources/docusaurus/value-definition.hbs @@ -1,18 +1,10 @@ {{~#if link~}} {{links link}} {{~/if}} -{{~#if parameters}} -
{{description}} ({{name}}) -{{~else}}`{{name}}` - {{#links description}}{{#block "docusaurus/value-definition"}}{{/block}}{{/links}} -{{~/if}} -{{~#if parameters}} -{{/if}} - -{{~#each parameters}} -{{#shift}}* `{{name}}` - {{#each types~}}{{#block "docusaurus/value-definition"}}{{/block}}{{~/each}}{{/shift}} -{{~/each}} - -{{~#if parameters}} - +{{~#if parameters}}`{{name}}` -
{{description}} +{{~#each parameters as |parameter| }}{{#with parameter}} + {{#shift}}* `{{name}}` - {{#each types as | type|~}}{{#with type}}{{#block "docusaurus/value-definition"}}{{/block}}{{/with}}{{~/each}}{{/shift}} +{{~/with}}{{~/each}}
-{{/if}} \ No newline at end of file +{{~else}}`{{name}}` - {{#links description}}{{#block "docusaurus/value-definition"}}{{/block}}{{/links}} +{{~/if}} \ No newline at end of file From 0f3baf44bc30a0b28618cc07a2a753fc8b934e53 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Tue, 5 Sep 2023 14:16:09 +0300 Subject: [PATCH 06/27] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20=D1=84=D0=BE=D1=80=D0=BC=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B9=20=D1=81=D0=B2=D0=BE=D0=B9=D1=81=D1=82?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Была ошибка сборки docusaurus --- src/main/resources/docusaurus/value-definition.hbs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/resources/docusaurus/value-definition.hbs b/src/main/resources/docusaurus/value-definition.hbs index 351c65d..ee882b0 100644 --- a/src/main/resources/docusaurus/value-definition.hbs +++ b/src/main/resources/docusaurus/value-definition.hbs @@ -1,10 +1,16 @@ {{~#if link~}} {{links link}} {{~/if}} -{{~#if parameters}}`{{name}}` -
{{description}} -{{~#each parameters as |parameter| }}{{#with parameter}} - {{#shift}}* `{{name}}` - {{#each types as | type|~}}{{#with type}}{{#block "docusaurus/value-definition"}}{{/block}}{{/with}}{{~/each}}{{/shift}} -{{~/with}}{{~/each}} +{{~#if parameters}} +
+ +`{{name}}` - {{description}} + + + +{{#each parameters as |parameter| }}{{#with parameter}} +{{~#shift}}* `{{name}}` - {{#each types as | type|~}}{{#with type}}{{#block "docusaurus/value-definition"}}{{/block}}{{/with}}{{~/each}}{{/shift}} +{{/with}}{{/each}}
{{~else}}`{{name}}` - {{#links description}}{{#block "docusaurus/value-definition"}}{{/block}}{{/links}} {{~/if}} \ No newline at end of file From db198ab4f9b9851018c32d82a5c5377d03fa2274 Mon Sep 17 00:00:00 2001 From: Aleksey Ko Date: Fri, 6 Oct 2023 19:41:32 +0300 Subject: [PATCH 07/27] #ORAIS-183 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Структура подсистем --- README.md | 11 +++ .../ru/alkoleft/bsl/doc/bsl/BslContext.java | 94 +++++++++++++++++-- .../alkoleft/bsl/doc/bsl/ModuleContext.java | 6 ++ .../bsl/doc/commands/RenderCommand.java | 14 +-- .../ru/alkoleft/bsl/doc/render/Render.java | 53 ++++++++--- .../bsl/doc/render/StructureRender.java | 82 ++++++++++++++++ .../bsl/doc/render/StructureStrategy.java | 79 +++++++++++++--- .../bsl/doc/render/SubsystemTreeRender.java | 47 ++++++++++ .../doc/render/contexts/ModuleContext.java | 17 ++++ .../doc/render/handlebars/HandleLinks.java | 2 +- .../handlebars/HandlebarsRenderContext.java | 2 + .../doc/render/handlebars/HelperGreat.java | 26 +++++ .../render/handlebars/SingleLineHelper.java | 24 +++++ .../alkoleft/bsl/doc/structure/Builder.java | 37 ++++++++ .../ru/alkoleft/bsl/doc/structure/Item.java | 27 ++++++ .../bsl/doc/structure/MDObjectItem.java | 20 ++++ .../bsl/doc/structure/ModuleItem.java | 18 ++++ .../bsl/doc/structure/StructureVisitor.java | 11 +++ .../bsl/doc/structure/SubsystemItem.java | 14 +++ .../bsl/doc/structure/Subsystems.java | 56 +++++++++++ .../ru/alkoleft/bsl/doc/structure/Utils.java | 21 +++++ src/main/resources/md/module.hbs | 10 +- src/main/resources/md/module.vm | 18 ---- src/main/resources/md/subsystem.hbs | 8 ++ 24 files changed, 630 insertions(+), 67 deletions(-) create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/SubsystemTreeRender.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HelperGreat.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/handlebars/SingleLineHelper.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/Item.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/MDObjectItem.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/ModuleItem.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/StructureVisitor.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/Subsystems.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/Utils.java delete mode 100644 src/main/resources/md/module.vm create mode 100644 src/main/resources/md/subsystem.hbs diff --git a/README.md b/README.md index c1533d8..f85e651 100644 --- a/README.md +++ b/README.md @@ -1 +1,12 @@ # bsldoc + +## Запуск + +### Параметры запуска + +`bsldoc --format= --only-subsystems= --regions= source destination` +* `--format` - Формат +* `--only-subsystems` - Список подсистем, по которым строится документация +* `--regions` - Фильтр регионов, для которых строится документация +* `source` - Каталог исходников +* `destination` - Каталог выгрузки документации \ No newline at end of file diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java index 5b75099..732bb2b 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java @@ -4,8 +4,14 @@ import com.github._1c_syntax.bsl.parser.BSLTokenizer; import com.github._1c_syntax.bsl.types.MDOType; import com.github._1c_syntax.mdclasses.Configuration; +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; import com.github._1c_syntax.mdclasses.mdo.MDCommonModule; +import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; import com.google.common.base.Strings; +import io.vavr.control.Either; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.antlr.v4.runtime.Token; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; @@ -15,7 +21,9 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; @@ -25,16 +33,28 @@ @Slf4j public class BslContext { + @Getter private static BslContext current; - public static BslContext getCurrent() { - return current; - } - + @Getter Configuration configuration; + + @Getter Filter filter; + List modules = Collections.emptyList(); + Set topObjectsType = Set.of( + MDOType.COMMON_MODULE, + MDOType.ENUM, + MDOType.CATALOG, + MDOType.DOCUMENT, + MDOType.ACCOUNTING_REGISTER, + MDOType.ACCUMULATION_REGISTER, + MDOType.CALCULATION_REGISTER, + MDOType.INFORMATION_REGISTER + ); + private static final Set VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH = Set.of( BSLParser.LINE_COMMENT, BSLParser.WHITE_SPACE, @@ -55,8 +75,39 @@ public Stream getModules() { } return stream - .map(this::buildModuleContext) - .filter(ModuleContext::isNotEmpty); + .map(this::buildModuleContext) + .filter(ModuleContext::isNotEmpty); + } + + public Stream getRootSubsystems() { + return configuration.getOrderedTopMDObjects().get(MDOType.SUBSYSTEM).stream() + .map(MDSubsystem.class::cast); + } + + public Stream getChildrenSubsystems(MDSubsystem parent) { + return parent.getChildren().stream() + .filter(Either::isRight) + .map(Either::get) + .filter(MDSubsystem.class::isInstance) + .map(MDSubsystem.class::cast); + } + + public Stream getSubsystems() { + return getRootSubsystems() + .flatMap(this::getRecursiveChildrenSubsystems); + } + + private Stream getRecursiveChildrenSubsystems(MDSubsystem parent) { + if (parent.getChildren().isEmpty()) { + return Stream.of(parent); + } + + return Stream.concat(Stream.of(parent), parent.getChildren().stream() + .filter(Either::isRight) + .map(Either::get) + .filter(MDSubsystem.class::isInstance) + .map(MDSubsystem.class::cast) + .flatMap(this::getRecursiveChildrenSubsystems)); } public boolean contains(String name) { @@ -67,6 +118,20 @@ public Optional getModule(String name) { return modules.stream().filter(it -> it.getName().equalsIgnoreCase(name)).findAny(); } + public Stream getSubsystemObjects(MDSubsystem subsystem) { + + return configuration.getChildren() + .stream() + .filter(AbstractMDObjectBSL.class::isInstance) + .filter(this::isTopObject) + .filter(it -> it.getIncludedSubsystems().contains(subsystem)) + .map(AbstractMDObjectBSL.class::cast); + } + + boolean isTopObject(AbstractMDObjectBase obj) { + return topObjectsType.contains(obj.getMdoType()); + } + public void load() { modules = configuration.getOrderedTopMDObjects().get(MDOType.COMMON_MODULE).stream() .map(MDCommonModule.class::cast) @@ -74,10 +139,18 @@ public void load() { .collect(Collectors.toList()); } - private ModuleContext buildModuleContext(MDCommonModule module) { + public ModuleContext buildModuleContext(MDCommonModule module) { var bslModules = module.getModules(); var bslModule = bslModules.get(0); - log.debug("Parse module: " + bslModule.getOwner().getName() + "." + bslModule.getModuleType()); + return buildModuleContext(bslModule); + } + + public ModuleContext buildFilteredModuleContext(MDOModule bslModule) { + return buildModuleContext(buildModuleContext(bslModule)); + } + public ModuleContext buildModuleContext(MDOModule bslModule) { + var owner = (AbstractMDObjectBSL) bslModule.getOwner(); + log.debug("Parse module: " + owner.getName() + "." + bslModule.getModuleType()); var srcPath = Path.of(bslModule.getUri()); List methods; String description; @@ -88,11 +161,12 @@ private ModuleContext buildModuleContext(MDCommonModule module) { methods = computer.compute(tokenizer); description = computeModuleDescription(tokenizer); } catch (Exception e) { - throw new RuntimeException(module.getMdoReference().getMdoRef() + ". Module parsing error", e); + throw new RuntimeException(owner.getMdoReference().getMdoRef() + ". Module parsing error", e); } return ModuleContext.builder() - .owner(module) + .owner(owner) + .module(bslModule) .methods(methods) .description(description) .build(); diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleContext.java index 5b7557d..7e505bf 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleContext.java @@ -1,6 +1,7 @@ package ru.alkoleft.bsl.doc.bsl; import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; +import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; import lombok.Builder; import lombok.Value; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; @@ -12,6 +13,7 @@ @Value public class ModuleContext { AbstractMDObjectBSL owner; + MDOModule module; List methods; String description; @@ -23,6 +25,10 @@ public boolean isNotEmpty() { return methods != null && !methods.isEmpty(); } + public boolean isEmpty() { + return methods == null || methods.isEmpty(); + } + public Optional getMethod(String name) { return getMethods().stream().filter(it -> name.equalsIgnoreCase(it.getName())).findAny(); } diff --git a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java index 6c4184f..2b0394e 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java +++ b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java @@ -12,8 +12,9 @@ import ru.alkoleft.bsl.doc.render.OutputFormat; import ru.alkoleft.bsl.doc.render.Render; import ru.alkoleft.bsl.doc.render.RenderOptions; +import ru.alkoleft.bsl.doc.render.StructureRender; +import ru.alkoleft.bsl.doc.structure.Builder; -import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @@ -50,13 +51,14 @@ public void run() { log.debug("Filter: " + filter.toString()); log.debug("Options: " + options.toString()); + var bslContext = new BslContext(sources, filter); var renderContext = Factory.createRenderContext(options); - var render = new Render(renderContext); - BslContext bslContext = new BslContext(sources, filter); - bslContext.load(); + var structure = Builder.build(bslContext); + Builder.print(structure); - Files.createDirectories(destination); - render.render(bslContext, destination); + new StructureRender().render(new Render(renderContext), structure, destination); +// var render = new SubsystemTreeRender(bslContext, renderContext, destination); +// render.render(); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java index 9e1bfb9..d001325 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java @@ -1,13 +1,15 @@ package ru.alkoleft.bsl.doc.render; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; +import com.github._1c_syntax.mdclasses.mdo.MDCommonModule; +import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.bsl.ModuleContext; import java.nio.file.Path; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.Collections; +import java.util.List; @Slf4j public class Render { @@ -18,32 +20,55 @@ public Render(RenderContext renderContext) { this.renderContext = renderContext; } - public void render(BslContext bslContext, Path output) { - AtomicInteger index = new AtomicInteger(); - - renderContext.setContext(bslContext); - bslContext.getModules().forEach(it -> renderModule(it, output, index.getAndIncrement())); - } - @SneakyThrows - public void renderModule(ModuleContext module, Path outputPath, int index) { + public void render(ModuleContext module, Path outputPath, int index) { var itemRender = renderContext.getRender("module"); - log.debug("Render module " + module.getOwner().getName()); + log.debug("Render module '{}' to '{}'", module.getOwner().getName(), outputPath); itemRender.put("index", index); itemRender.put("name", module.getOwner().getName()); itemRender.put("present", getPresent(module.getOwner())); + itemRender.put("isCommonModule", module.getOwner() instanceof MDCommonModule); + itemRender.put("type", module.getOwner().getMdoType().getNameRu()); itemRender.put("methods", module.getMethods()); itemRender.put("description", module.getDescription()); - itemRender.renderToFile(outputPath.resolve(module.getOwner().getName() + ".md")); + itemRender.renderToFile(outputPath); } - private String getPresent(AbstractMDObjectBSL object) { + private String getPresent(AbstractMDObjectBase object) { if (object.getSynonyms().isEmpty()) { return object.getName(); } else { return object.getSynonyms().get(0).getContent(); } } + + public void render(ModuleContext module, StructureStrategy strategy, int index) { + var path = strategy.getModulePath(module); + render(module, path, index); + } + + @SneakyThrows + public void render(MDSubsystem subsystem, Path path, int level, List childrenItems) { + var itemRender = renderContext.getRender("subsystem"); + log.debug("Render module '{}' to '{}'", subsystem.getName(), path); + + itemRender.put("level", level); + itemRender.put("name", subsystem.getName()); + itemRender.put("present", getPresent(subsystem)); + itemRender.put("description", subsystem.getComment()); + itemRender.put("children", childrenItems); + itemRender.renderToFile(path); + } + + public void render(MDSubsystem subsystem, StructureStrategy strategy, int level) { + Path path; + if (level == 0) { + path = strategy.getPath().resolve("index.md"); + } else { + path = strategy.getObjectPath(subsystem).resolve("index.md"); + } + render(subsystem, path, level, Collections.emptyList()); + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java new file mode 100644 index 0000000..835b349 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java @@ -0,0 +1,82 @@ +package ru.alkoleft.bsl.doc.render; + +import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import lombok.SneakyThrows; +import ru.alkoleft.bsl.doc.bsl.BslContext; +import ru.alkoleft.bsl.doc.structure.Item; +import ru.alkoleft.bsl.doc.structure.MDObjectItem; +import ru.alkoleft.bsl.doc.structure.ModuleItem; +import ru.alkoleft.bsl.doc.structure.StructureVisitor; +import ru.alkoleft.bsl.doc.structure.SubsystemItem; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; +import java.util.stream.Collectors; + +public class StructureRender implements StructureVisitor { + Render render; + int subsystemLevel = 0; + + Stack paths = new Stack<>(); + Stack> children = new Stack<>(); + + boolean withRoot = false; + + public void render(Render render, List structure, Path destination) { + this.render = render; + paths.push(destination); + children.push(new ArrayList<>()); + for (int i = 0; i < structure.size(); i++) { + structure.get(i).accept(this, i); + } + } + + @Override + public void visit(SubsystemItem item, int index) { + boolean isRoot = subsystemLevel == 0; + subsystemLevel++; + children.push(new ArrayList<>()); + Path path; + if (!withRoot && isRoot) { + path = paths.peek(); + item.accentChildren(this); + } else { + path = paths.peek().resolve(item.getName()); + paths.push(path); + item.accentChildren(this); + paths.pop(); + } + subsystemLevel--; + List childrenItems = + children.pop().stream() + .map(it -> it.toString().substring(path.toString().length() + 1)) + .collect(Collectors.toList()); + if (!childrenItems.isEmpty()) { + render.render((MDSubsystem) item.getObject(), path.resolve("index.md"), subsystemLevel, childrenItems); + children.peek().add(path.resolve("index.md")); + } + } + + @Override + @SneakyThrows + public void visit(ModuleItem item, int index) { + var moduleContext = BslContext.getCurrent().buildFilteredModuleContext(item.getModule()); + if (moduleContext.isEmpty()) { + return; + } + final var path = paths.peek().resolve(item.getModule().getOwner().getName() + ".md"); + if (!Files.exists(path.getParent())) { + Files.createDirectories(path.getParent()); + } + children.peek().add(path); + render.render(moduleContext, path, index); + } + + @Override + public void visit(MDObjectItem item, int index) { + item.accentChildren(this); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureStrategy.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureStrategy.java index 553ab9a..55df4ca 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/StructureStrategy.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/StructureStrategy.java @@ -1,26 +1,29 @@ package ru.alkoleft.bsl.doc.render; import com.github._1c_syntax.bsl.mdo.MD; -import com.github._1c_syntax.bsl.mdo.MDObject; import com.github._1c_syntax.mdclasses.Configuration; +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; +import lombok.Getter; +import lombok.SneakyThrows; +import ru.alkoleft.bsl.doc.bsl.ModuleContext; -import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; public abstract class StructureStrategy { + @Getter protected Path path; protected String extension; - StructureStrategy(Path path, String extension) throws IOException { + StructureStrategy(Path path, String extension) { this.path = path; this.extension = extension; createIfNotExists(path); } - public Path getPath(MDObject object) throws IOException { + public Path getPath(AbstractMDObjectBase object) { Path objectPath = path.resolve(getObjectPath(object)); createIfNotExists(objectPath.getParent()); return objectPath; @@ -31,11 +34,13 @@ public Path getPath(MD object) { return path.resolve(getFileName(object)); } - public String getLink(MDObject object) { + public String getLink(AbstractMDObjectBase object) { return "../" + getObjectPath(object); } - protected abstract String getObjectPath(MDObject object); + protected abstract Path getObjectPath(AbstractMDObjectBase object); + + protected abstract Path getModulePath(ModuleContext module); public String getFileName(MD object) { return String.format("%s.%s", object.getName(), extension); @@ -45,20 +50,72 @@ public String getFileName(Configuration object) { return String.format("configuration.%s", extension); } - protected void createIfNotExists(Path path) throws IOException { + @SneakyThrows + protected void createIfNotExists(Path path) { if (!Files.exists(path)) { Files.createDirectories(path); } } - static class Metadata extends StructureStrategy { - public Metadata(Path path, String extension) throws IOException { + public static class Metadata extends StructureStrategy { + public Metadata(Path path, String extension) { super(path, extension); } @Override - public String getObjectPath(MDObject object) { - return Path.of(object.getMdoType().getGroupName(), getFileName(object)).toString(); + public Path getObjectPath(AbstractMDObjectBase object) { + return Path.of(object.getMdoType().getGroupName(), getFileName(object)); + } + + @Override + public Path getModulePath(ModuleContext module) { + var object = module.getOwner(); + var modulePath = path + .resolve(object.getMdoType().getGroupName()) + .resolve(getFileName(object)); + createIfNotExists(modulePath.getParent()); + return modulePath; + } + } + + public static class Subsystems extends StructureStrategy { + + boolean withRootSubsystem; + + public Subsystems(Path path, String extension, boolean withRootSubsystem) { + super(path, extension); + this.withRootSubsystem = withRootSubsystem; + } + + @Override + protected Path getObjectPath(AbstractMDObjectBase object) { + var basePath = Path.of(""); + AbstractMDObjectBase owner = object; + while (true) { + var subsytems = owner.getIncludedSubsystems(); + if (subsytems.isEmpty()) { + break; + } + owner = subsytems.get(0); + if (!withRootSubsystem && owner.getIncludedSubsystems().isEmpty()) { + break; + } + basePath = Path.of(owner.getName(), basePath.toString()); + } + basePath = path.resolve(basePath.toString()); + basePath = basePath.resolve(object.getName()); + createIfNotExists(basePath); + return basePath; + } + + @Override + protected Path getModulePath(ModuleContext module) { + var object = module.getOwner(); + var basePath = getObjectPath(object); + + var modulePath = basePath.resolve(getFileName(object)); + createIfNotExists(modulePath.getParent()); + return modulePath; } } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/SubsystemTreeRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/SubsystemTreeRender.java new file mode 100644 index 0000000..57ec336 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/SubsystemTreeRender.java @@ -0,0 +1,47 @@ +package ru.alkoleft.bsl.doc.render; + +import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import ru.alkoleft.bsl.doc.bsl.BslContext; + +import java.nio.file.Path; +import java.util.concurrent.atomic.AtomicInteger; + +public class SubsystemTreeRender { + + StructureStrategy.Subsystems strategy; + Render render; + + BslContext context; + boolean withRoot; + + public SubsystemTreeRender(BslContext context, RenderContext renderContext, Path destination) { + withRoot = context.getFilter().getRootSubsystems().size() > 1; + render = new Render(renderContext); + strategy = new StructureStrategy.Subsystems(destination, "md", withRoot); + this.context = context; + } + + public void render() { + var rootSubsystems = context.getRootSubsystems() + .filter(it -> context.getFilter().getRootSubsystems().contains(it.getName())); + + if (withRoot) { + rootSubsystems.forEach(it -> renderSubsystem(it, 1)); + } else { + rootSubsystems + .forEach(it -> renderSubsystem(it, 0)); + } + } + + private void renderSubsystem(MDSubsystem subsystem, int level) { + render.render(subsystem, strategy, level); + context.getChildrenSubsystems(subsystem) + .forEach(it -> renderSubsystem(it, level + 1)); + AtomicInteger index = new AtomicInteger(); + context.getSubsystemObjects(subsystem) + .flatMap(it->it.getModules().stream()) + .peek(it -> index.getAndIncrement()) + .map(context::buildModuleContext) + .forEach(it -> render.render(it, strategy, index.get())); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java new file mode 100644 index 0000000..5b512d7 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java @@ -0,0 +1,17 @@ +package ru.alkoleft.bsl.doc.render.contexts; + +import lombok.Builder; +import lombok.Value; +import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; + +import java.util.List; + +@Value +@Builder +public class ModuleContext { + int index; + String name; + String present; + String description; + List methods; +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java index 5f93073..6dcced1 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java @@ -36,7 +36,7 @@ public Object apply(String context, Options options) { @SneakyThrows private String replaceTo(String baseValue, Links.Link link, Options options) { var methodInfo = BslContext.getCurrent().getMethodInfo(link); - if (methodInfo == null || methodInfo.isPublishing()) { + if (methodInfo == null || methodInfo.isPublishing() || methodInfo.getMethod() == null) { return String.format("[%s](%s)", baseValue, getLink(link)); } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarsRenderContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarsRenderContext.java index b28695c..9d293b4 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarsRenderContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarsRenderContext.java @@ -23,6 +23,8 @@ public HandlebarsRenderContext(String path) { handlebars.registerHelper("links", linksRender = new HandleLinks()); handlebars.registerHelper("shift", new Shifter()); handlebars.registerHelper("debug", new RenderDebugger()); + handlebars.registerHelper("great", new HelperGreat()); + handlebars.registerHelper("single-line", new SingleLineHelper()); } public void setContext(BslContext context) { diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HelperGreat.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HelperGreat.java new file mode 100644 index 0000000..ba81a02 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HelperGreat.java @@ -0,0 +1,26 @@ +package ru.alkoleft.bsl.doc.render.handlebars; + +import com.github.jknack.handlebars.Helper; +import com.github.jknack.handlebars.Options; + +import java.io.IOException; +import java.util.List; + +public class HelperGreat implements Helper { + @Override + public Object apply(Object context, Options options) throws IOException { + int secondValue = options.param(0, 0); + boolean success = false; + if (context instanceof Integer) { + success = ((Integer) context) > secondValue; + } + if (context instanceof List) { + success = ((List) context).size() > secondValue; + } + + if (success) { + return options.fn(this); + } + return options.inverse(this); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/SingleLineHelper.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/SingleLineHelper.java new file mode 100644 index 0000000..aabff80 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/SingleLineHelper.java @@ -0,0 +1,24 @@ +package ru.alkoleft.bsl.doc.render.handlebars; + +import com.github.jknack.handlebars.Helper; +import com.github.jknack.handlebars.Options; +import com.github.jknack.handlebars.TagType; + +import java.io.IOException; + +public class SingleLineHelper implements Helper { + @Override + public Object apply(Object context, Options options) throws IOException { + var buffer = options.buffer(); + + String content; + if (options.tagType == TagType.SECTION) { + content = options.fn().toString(); + }else{ + content = context.toString(); + } + + buffer.append(content.replace("\n", "
")); + return buffer; + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java new file mode 100644 index 0000000..00ad22e --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java @@ -0,0 +1,37 @@ +package ru.alkoleft.bsl.doc.structure; + +import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.bsl.BslContext; + +import java.util.List; + +@UtilityClass +public class Builder { + + public List build(BslContext context) { + return new Subsystems(context).buildStructure(); + } + + public void print(List structure) { + print(structure, ""); + } + + private void print(List structure, String prefix) { + Item item; + for (int index = 0; index < structure.size(); index++) { + item = structure.get(index); + if (index == structure.size() - 1) { + System.out.printf("%s└── %s\n", prefix, item.getPresent()); + if (!item.getChildren().isEmpty()) { + print(item.getChildren(), prefix + " "); + } + } else { + System.out.printf("%s├── %s\n", prefix, item.getPresent()); + if (!item.getChildren().isEmpty()) { + print(item.getChildren(), prefix + "│   "); + } + } + } + } + +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Item.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Item.java new file mode 100644 index 0000000..a5befdd --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/Item.java @@ -0,0 +1,27 @@ +package ru.alkoleft.bsl.doc.structure; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +@AllArgsConstructor +@Getter +public abstract class Item { + private final Object object; + private final String name; + private final List children = new ArrayList<>(); + + public String getPresent() { + return name; + } + + public abstract void accept(StructureVisitor visitor, int index); + + public void accentChildren(StructureVisitor visitor) { + for (int i = 0; i < getChildren().size(); i++) { + getChildren().get(i).accept(visitor, i); + } + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/MDObjectItem.java b/src/main/java/ru/alkoleft/bsl/doc/structure/MDObjectItem.java new file mode 100644 index 0000000..f05d016 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/MDObjectItem.java @@ -0,0 +1,20 @@ +package ru.alkoleft.bsl.doc.structure; + +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; + +public class MDObjectItem extends Item { + public MDObjectItem(AbstractMDObjectBase object) { + super(object, object.getName()); + } + + @Override + public String getPresent() { + var mdo = (AbstractMDObjectBase) getObject(); + return String.format("%s.%s", mdo.getMdoType().name(), mdo.getName()); + } + + @Override + public void accept(StructureVisitor visitor, int index) { + visitor.visit(this, index); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/ModuleItem.java b/src/main/java/ru/alkoleft/bsl/doc/structure/ModuleItem.java new file mode 100644 index 0000000..6d703b9 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/ModuleItem.java @@ -0,0 +1,18 @@ +package ru.alkoleft.bsl.doc.structure; + +import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; + +public class ModuleItem extends Item { + public ModuleItem(MDOModule module) { + super(module, module.getModuleType().name()); + } + + public MDOModule getModule() { + return (MDOModule) getObject(); + } + + @Override + public void accept(StructureVisitor visitor, int index) { + visitor.visit(this, index); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/StructureVisitor.java b/src/main/java/ru/alkoleft/bsl/doc/structure/StructureVisitor.java new file mode 100644 index 0000000..b8d7c3e --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/StructureVisitor.java @@ -0,0 +1,11 @@ +package ru.alkoleft.bsl.doc.structure; + +import java.util.List; + +public interface StructureVisitor { + void visit(SubsystemItem item, int index); + + void visit(ModuleItem item, int index); + + void visit(MDObjectItem item, int index); +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java new file mode 100644 index 0000000..c206deb --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java @@ -0,0 +1,14 @@ +package ru.alkoleft.bsl.doc.structure; + +import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; + +public class SubsystemItem extends Item { + public SubsystemItem(MDSubsystem subsystem) { + super(subsystem, subsystem.getName()); + } + + @Override + public void accept(StructureVisitor visitor, int index) { + visitor.visit(this, index); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Subsystems.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Subsystems.java new file mode 100644 index 0000000..721f8a0 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/Subsystems.java @@ -0,0 +1,56 @@ +package ru.alkoleft.bsl.doc.structure; + + +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; +import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import lombok.AllArgsConstructor; +import ru.alkoleft.bsl.doc.bsl.BslContext; + +import java.util.List; +import java.util.stream.Collectors; + +@AllArgsConstructor +public class Subsystems { + + final BslContext context; + + public List buildStructure() { + + return context.getRootSubsystems() + .filter(it -> context.getFilter().getRootSubsystems().contains(it.getName())) + .map(this::createSubSystemItem) + .collect(Collectors.toList()); + } + + private Item createSubSystemItem(MDSubsystem subsystem) { + var item = new SubsystemItem(subsystem); + fillChildrenSubsystems(item); + fillChildrenObjects(item); + return item; + } + + private Item createMDObjectItem(AbstractMDObjectBSL owner) { + var item = new MDObjectItem(owner); + owner.getModules() + .stream() + .filter(Utils::isManagerModule) + .map(ModuleItem::new) + .forEach(item.getChildren()::add); + return item; + } + + private void fillChildrenObjects(Item item) { + context.getSubsystemObjects((MDSubsystem) item.getObject()) + .map(this::createMDObjectItem) + .filter(it -> !it.getChildren().isEmpty()) + .forEach(item.getChildren()::add); + } + + private void fillChildrenSubsystems(Item subsystemItem) { + context.getChildrenSubsystems((MDSubsystem) subsystemItem.getObject()) + .forEach(it -> { + var item = createSubSystemItem(it); + subsystemItem.getChildren().add(item); + }); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Utils.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Utils.java new file mode 100644 index 0000000..acf749d --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/Utils.java @@ -0,0 +1,21 @@ +package ru.alkoleft.bsl.doc.structure; + +import com.github._1c_syntax.bsl.types.ModuleType; +import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; +import lombok.experimental.UtilityClass; + +import java.util.Set; + +@UtilityClass +public class Utils { + + Set moduleTypes = Set.of( + ModuleType.CommonModule, + ModuleType.ValueManagerModule, + ModuleType.ManagerModule + ); + + public boolean isManagerModule(MDOModule module) { + return moduleTypes.contains(module.getModuleType()); + } +} diff --git a/src/main/resources/md/module.hbs b/src/main/resources/md/module.hbs index 7daf3c6..e3dbe55 100644 --- a/src/main/resources/md/module.hbs +++ b/src/main/resources/md/module.hbs @@ -1,6 +1,4 @@ -# {{present}} ({{name}}) - -## Методы модуля +# Программный интерфейс: {{#unless isCommonModule}}{{type}}.{{/unless}}{{present}} {{~#each methods}} @@ -9,13 +7,11 @@ {{#if description}}{{description}}{{/if}} {{~#if parameters}} -Параметры метода: - | Имя | Тип | Описание | |-----|-----|---------| {{~#each parameters as | parameter|}} {{~#each parameter.types as | type typeIndex|}} -| {{#unless typeIndex}}`{{parameter.name}}`{{/unless}} | `{{type.name}}` | {{type.description}} | +| {{#unless typeIndex}}`{{parameter.name}}`{{/unless}} | `{{type.name}}` | {{#single-line}}{{links type.description}}{{/single-line}} | {{~else}} | {{name}} | | {{description}} | {{~/each}} @@ -23,7 +19,7 @@ {{~/if}} {{~#if returnedValue}} -Возвращает: +Возвращаемое значение {{#if returnedValue.link}} [{{returnedValue.link}}]({{returnedValue.link}}) diff --git a/src/main/resources/md/module.vm b/src/main/resources/md/module.vm deleted file mode 100644 index 3506296..0000000 --- a/src/main/resources/md/module.vm +++ /dev/null @@ -1,18 +0,0 @@ -#set( $H = '#' ) -$H $present ($name) - -$H$H Методы модуля -#foreach( $method in $methods) - -$H$H$H $method.name - -$method.description -#if (!$method.parameters.empty) - -**Параметры метода** -#foreach( $parameter in $method.parameters) - -* $parameter.name - $parameter.description -#end -#end -#end \ No newline at end of file diff --git a/src/main/resources/md/subsystem.hbs b/src/main/resources/md/subsystem.hbs new file mode 100644 index 0000000..9dec684 --- /dev/null +++ b/src/main/resources/md/subsystem.hbs @@ -0,0 +1,8 @@ +# {{#great level 1}}Подсистема {{/great}}{{present}} + +{{description}} + +Содержимое: +{{#each children as | item|}} +* [{{item}}]({{item}}) +{{/each}} \ No newline at end of file From dc5dcc61e24ac6a9cb1486eec8588c2fbd8c3716 Mon Sep 17 00:00:00 2001 From: Aleksey Ko Date: Tue, 10 Oct 2023 13:21:59 +0300 Subject: [PATCH 08/27] Fixture --- src/test/resources/configuration/.project | 18 ++++++++ .../com.e1c.v8codestyle.autosort.prefs | 2 + .../.settings/com.e1c.v8codestyle.bsl.prefs | 3 ++ .../.settings/com.e1c.v8codestyle.prefs | 3 ++ .../org.eclipse.core.resources.prefs | 2 + .../configuration/DT-INF/PROJECT.PMF | 2 + .../Module.bsl" | 35 +++++++++++++++ ...0\262\320\260\320\275\320\270\321\217.mdo" | 9 ++++ .../Module.bsl" | 45 +++++++++++++++++++ ...0\275\320\272\321\206\320\270\320\270.mdo" | 9 ++++ .../src/Configuration/CommandInterface.cmi | 2 + .../src/Configuration/Configuration.mdo | 45 +++++++++++++++++++ .../MainSectionCommandInterface.cmi | 2 + .../CommandInterface.cmi" | 2 + .../CommandInterface.cmi" | 2 + .../CommandInterface.cmi" | 2 + ...0\262\320\260\320\275\320\270\321\217.mdo" | 12 +++++ .../CommandInterface.cmi" | 2 + ...0\275\320\272\321\206\320\270\320\270.mdo" | 12 +++++ ...\260\320\267\320\264\320\265\320\2731.mdo" | 14 ++++++ .../\320\237\320\237\320\230.mdo" | 11 +++++ 21 files changed, 234 insertions(+) create mode 100644 src/test/resources/configuration/.project create mode 100644 src/test/resources/configuration/.settings/com.e1c.v8codestyle.autosort.prefs create mode 100644 src/test/resources/configuration/.settings/com.e1c.v8codestyle.bsl.prefs create mode 100644 src/test/resources/configuration/.settings/com.e1c.v8codestyle.prefs create mode 100644 src/test/resources/configuration/.settings/org.eclipse.core.resources.prefs create mode 100644 src/test/resources/configuration/DT-INF/PROJECT.PMF create mode 100644 "src/test/resources/configuration/src/CommonModules/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/Module.bsl" create mode 100644 "src/test/resources/configuration/src/CommonModules/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" create mode 100644 "src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/Module.bsl" create mode 100644 "src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" create mode 100644 src/test/resources/configuration/src/Configuration/CommandInterface.cmi create mode 100644 src/test/resources/configuration/src/Configuration/Configuration.mdo create mode 100644 src/test/resources/configuration/src/Configuration/MainSectionCommandInterface.cmi create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/CommandInterface.cmi" create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/CommandInterface.cmi" create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/CommandInterface.cmi" create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/CommandInterface.cmi" create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/\320\237\320\237\320\230.mdo" diff --git a/src/test/resources/configuration/.project b/src/test/resources/configuration/.project new file mode 100644 index 0000000..84e659a --- /dev/null +++ b/src/test/resources/configuration/.project @@ -0,0 +1,18 @@ + + + BslDoc + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + + org.eclipse.xtext.ui.shared.xtextNature + com._1c.g5.v8.dt.core.V8ConfigurationNature + + diff --git a/src/test/resources/configuration/.settings/com.e1c.v8codestyle.autosort.prefs b/src/test/resources/configuration/.settings/com.e1c.v8codestyle.autosort.prefs new file mode 100644 index 0000000..23b0625 --- /dev/null +++ b/src/test/resources/configuration/.settings/com.e1c.v8codestyle.autosort.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +topObjects=true diff --git a/src/test/resources/configuration/.settings/com.e1c.v8codestyle.bsl.prefs b/src/test/resources/configuration/.settings/com.e1c.v8codestyle.bsl.prefs new file mode 100644 index 0000000..ac5ba52 --- /dev/null +++ b/src/test/resources/configuration/.settings/com.e1c.v8codestyle.bsl.prefs @@ -0,0 +1,3 @@ +addModuleStrictTypesAnnotation=false +createModuleStructure=false +eclipse.preferences.version=1 diff --git a/src/test/resources/configuration/.settings/com.e1c.v8codestyle.prefs b/src/test/resources/configuration/.settings/com.e1c.v8codestyle.prefs new file mode 100644 index 0000000..9e9b57e --- /dev/null +++ b/src/test/resources/configuration/.settings/com.e1c.v8codestyle.prefs @@ -0,0 +1,3 @@ +commonChecks=true +eclipse.preferences.version=1 +standardChecks=true diff --git a/src/test/resources/configuration/.settings/org.eclipse.core.resources.prefs b/src/test/resources/configuration/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/src/test/resources/configuration/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/src/test/resources/configuration/DT-INF/PROJECT.PMF b/src/test/resources/configuration/DT-INF/PROJECT.PMF new file mode 100644 index 0000000..e2a2031 --- /dev/null +++ b/src/test/resources/configuration/DT-INF/PROJECT.PMF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Runtime-Version: 8.3.21 diff --git "a/src/test/resources/configuration/src/CommonModules/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/Module.bsl" "b/src/test/resources/configuration/src/CommonModules/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/Module.bsl" new file mode 100644 index 0000000..130f397 --- /dev/null +++ "b/src/test/resources/configuration/src/CommonModules/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/Module.bsl" @@ -0,0 +1,35 @@ +#Область ПрограммныйИнтерфейс + +// ЗначениеВСтроку +// Преобразует переданное значение в строку +// +// Параметры: +// Значение - Произвольный - значение для преобразования в строковое представление +// ФорматнаяСтрока - Строка - формат получаемой строки для примитивных типов +// Кешировать - Булево - признак необходимости кэширования результата +// +// Возвращаемое значение: +// Строка - результат преобразования значения +// +Функция ЗначениеВСтроку(Значение, ФорматнаяСтрока = "", Кешировать = Ложь) Экспорт + +КонецФункции + +// ЧислоИзОднойСистемыВДругую +// Возвращает представление числа, преобразованного из одной системы счисления в другую. +// +// Параметры: +// ПредставлениеЧисла - Строка - представление числа. +// - Число - Преобразуемое число +// ОснованиеЧисла - Число - основание системы счисления переданного представления числа (1-32). +// ОснованиеРезультата - Число - основание системы счисления результата (1-32). +// ДлинаРезультата - Число - количество символов в возвращаемом представлении, если результат меньшей длины - будет дополнен нулями слева. +// ТекстОшибки - Строка - в этот параметр будет помещен текст возникшей ошибки. +// +// Возвращаемое значение: +// Строка - представление числа в требуемой системе счисления, "0" при ошибке. +Функция ЧислоИзОднойСистемыВДругую(ПредставлениеЧисла, ОснованиеЧисла, ОснованиеРезультата, ДлинаРезультата = 1, ТекстОшибки = "") Экспорт + +КонецФункции + +#КонецОбласти \ No newline at end of file diff --git "a/src/test/resources/configuration/src/CommonModules/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" "b/src/test/resources/configuration/src/CommonModules/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" new file mode 100644 index 0000000..0dc6fb9 --- /dev/null +++ "b/src/test/resources/configuration/src/CommonModules/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" @@ -0,0 +1,9 @@ + + + Преобразования + + ru + Преобразования + + true + diff --git "a/src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/Module.bsl" "b/src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/Module.bsl" new file mode 100644 index 0000000..01c32bd --- /dev/null +++ "b/src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/Module.bsl" @@ -0,0 +1,45 @@ +#Область ПрограммныйИнтерфейс + +// ПолучитьСтрокуИзКоллекцииПодстрок +// Устаревший +// Возвращает строку, полученную из массива элементов, списка значений или таблицы значений, разделенных символом разделителя +// +// Параметры: +// Коллекция - ФиксированныйМассив, Массив, СписокЗначений, ТаблицаЗначений - коллекция элементов из +// которых необходимо получить строку +// Разделитель - Строка - любой набор символов, +// который будет использован как разделитель между элементами в строке +// Колонки - Строка - Имена колонок таблицы +// значений, разделенные ";" или "*" если необходимо вывести все колонки +// ИгнорироватьОшибки - Булево - Если установлен в Истина, +// то неверные имена колонок игнорируются, в противном случае будет выдана ошибка, содержащая неверные колонки +// +// Возвращаемое значение: +// Строка - строка, полученная из коллекции элементов, разделенных символом разделителя +// +Функция ПолучитьСтрокуИзКоллекцииПодстрок(Коллекция, Разделитель = ",", Колонки = Неопределено, ИгнорироватьОшибки = Ложь) Экспорт + +КонецФункции + +// ПолучитьСтрокуИзКоллекцииПодстрок +// Устаревший +// Возвращает строку, полученную из массива элементов, списка значений или таблицы значений, разделенных символом разделителя +// +// Параметры: +// Коллекция - ФиксированныйМассив, Массив, СписокЗначений, ТаблицаЗначений - коллекция элементов из +// которых необходимо получить строку +// Разделитель - Строка - любой набор символов, +// который будет использован как разделитель между элементами в строке +// Колонки - Строка - Имена колонок таблицы +// значений, разделенные ";" или "*" если необходимо вывести все колонки +// ИгнорироватьОшибки - Булево - Если установлен в Истина, +// то неверные имена колонок игнорируются, в противном случае будет выдана ошибка, содержащая неверные колонки +// +// Возвращаемое значение: +// Строка - строка, полученная из коллекции элементов, разделенных символом разделителя +// +Функция ПолучитьСтрокуИзКоллекцииПодстрок2(Коллекция, Разделитель = ",", Колонки = Неопределено, ИгнорироватьОшибки = Ложь) Экспорт + +КонецФункции + +#КонецОбласти \ No newline at end of file diff --git "a/src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" "b/src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" new file mode 100644 index 0000000..4f360c6 --- /dev/null +++ "b/src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" @@ -0,0 +1,9 @@ + + + СтроковыеФункции + + ru + Строковые функции + + true + diff --git a/src/test/resources/configuration/src/Configuration/CommandInterface.cmi b/src/test/resources/configuration/src/Configuration/CommandInterface.cmi new file mode 100644 index 0000000..0cf6de8 --- /dev/null +++ b/src/test/resources/configuration/src/Configuration/CommandInterface.cmi @@ -0,0 +1,2 @@ + + diff --git a/src/test/resources/configuration/src/Configuration/Configuration.mdo b/src/test/resources/configuration/src/Configuration/Configuration.mdo new file mode 100644 index 0000000..0670b82 --- /dev/null +++ b/src/test/resources/configuration/src/Configuration/Configuration.mdo @@ -0,0 +1,45 @@ + + + BslDoc + + ru + Bsl doc + + + + + + + + + 8.3.21 + ManagedApplication + PersonalComputer + Russian + + + true + + + OSBackup + true + + + Language.Русский + Managed + NotAutoFree + DontUse + DontUse + 8.3.21 + + Русский + + ru + Русский + + ru + + Subsystem.ППИ + CommonModule.Преобразования + CommonModule.СтроковыеФункции + diff --git a/src/test/resources/configuration/src/Configuration/MainSectionCommandInterface.cmi b/src/test/resources/configuration/src/Configuration/MainSectionCommandInterface.cmi new file mode 100644 index 0000000..0cf6de8 --- /dev/null +++ b/src/test/resources/configuration/src/Configuration/MainSectionCommandInterface.cmi @@ -0,0 +1,2 @@ + + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/CommandInterface.cmi" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/CommandInterface.cmi" new file mode 100644 index 0000000..0cf6de8 --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/CommandInterface.cmi" @@ -0,0 +1,2 @@ + + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/CommandInterface.cmi" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/CommandInterface.cmi" new file mode 100644 index 0000000..0cf6de8 --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/CommandInterface.cmi" @@ -0,0 +1,2 @@ + + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/CommandInterface.cmi" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/CommandInterface.cmi" new file mode 100644 index 0000000..0cf6de8 --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/CommandInterface.cmi" @@ -0,0 +1,2 @@ + + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" new file mode 100644 index 0000000..20ddb73 --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" @@ -0,0 +1,12 @@ + + + Преобразования + + ru + Преобразования + + true + true + CommonModule.Преобразования + Subsystem.ППИ.Subsystem.Раздел1 + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/CommandInterface.cmi" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/CommandInterface.cmi" new file mode 100644 index 0000000..0cf6de8 --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/CommandInterface.cmi" @@ -0,0 +1,2 @@ + + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" new file mode 100644 index 0000000..9b0b7f6 --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" @@ -0,0 +1,12 @@ + + + СтроковыеФункции + + ru + Строковые функции + + true + true + CommonModule.СтроковыеФункции + Subsystem.ППИ.Subsystem.Раздел1 + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" new file mode 100644 index 0000000..b7ba36e --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" @@ -0,0 +1,14 @@ + + + Раздел1 + + ru + Раздел 1 + + true + true + CommonModule.СтроковыеФункции + СтроковыеФункции + Преобразования + Subsystem.ППИ + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/\320\237\320\237\320\230.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/\320\237\320\237\320\230.mdo" new file mode 100644 index 0000000..0b64e96 --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/\320\237\320\237\320\230.mdo" @@ -0,0 +1,11 @@ + + + ППИ + + ru + ППИ + + true + true + Раздел1 + From 903bc5fdae7c58a969e006a415342d8ba330aa19 Mon Sep 17 00:00:00 2001 From: Aleksey Ko Date: Tue, 10 Oct 2023 13:27:43 +0300 Subject: [PATCH 09/27] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B8=20=D0=BF=D0=BE=D0=B4=20=D1=81=D1=82=D1=80?= =?UTF-8?q?=D1=83=D0=BA=D1=82=D1=83=D1=80=D1=83=20=D0=BF=D0=BE=D0=B4=D1=81?= =?UTF-8?q?=D0=B8=D1=81=D1=82=D0=B5=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/alkoleft/bsl/doc/bsl/BslContext.java | 28 ++-- .../ru/alkoleft/bsl/doc/bsl/MethodInfo.java | 2 +- .../{ModuleContext.java => ModuleInfo.java} | 2 +- .../bsl/doc/commands/RenderCommand.java | 6 +- .../ru/alkoleft/bsl/doc/render/Factory.java | 11 -- .../alkoleft/bsl/doc/render/OutputFormat.java | 5 +- .../ru/alkoleft/bsl/doc/render/Render.java | 54 ++------ .../bsl/doc/render/RenderContext.java | 11 -- .../bsl/doc/render/StructureStrategy.java | 121 ------------------ .../bsl/doc/render/SubsystemTreeRender.java | 47 ------- .../doc/render/contexts/ContextFactory.java | 88 +++++++++++++ .../doc/render/contexts/ModuleContext.java | 10 +- .../doc/render/contexts/SubsystemContext.java | 17 +++ .../handlebars/HandlebarItemRender.java | 33 ----- .../doc/render/handlebars/HelperGreat.java | 26 ---- ...sRenderContext.java => RenderContext.java} | 31 ++++- src/main/resources/confluence-md/module.hbs | 54 ++++++++ .../resources/confluence-md/subsystem.hbs | 8 ++ .../confluence-md/value-definition.hbs | 11 ++ .../bsl/doc/commands/RenderCommandTest.java | 31 +++++ 20 files changed, 270 insertions(+), 326 deletions(-) rename src/main/java/ru/alkoleft/bsl/doc/bsl/{ModuleContext.java => ModuleInfo.java} (96%) delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/Factory.java delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/RenderContext.java delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/StructureStrategy.java delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/SubsystemTreeRender.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarItemRender.java delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HelperGreat.java rename src/main/java/ru/alkoleft/bsl/doc/render/handlebars/{HandlebarsRenderContext.java => RenderContext.java} (57%) create mode 100644 src/main/resources/confluence-md/module.hbs create mode 100644 src/main/resources/confluence-md/subsystem.hbs create mode 100644 src/main/resources/confluence-md/value-definition.hbs create mode 100644 src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java index 732bb2b..7b040f2 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java @@ -21,9 +21,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; @@ -42,7 +40,7 @@ public class BslContext { @Getter Filter filter; - List modules = Collections.emptyList(); + List modules = Collections.emptyList(); Set topObjectsType = Set.of( MDOType.COMMON_MODULE, @@ -67,7 +65,7 @@ public BslContext(Path path, Filter filter) { current = this; } - public Stream getModules() { + public Stream getModules() { var stream = modules.stream(); if (!filter.getModules().isEmpty()) { @@ -76,7 +74,7 @@ public Stream getModules() { return stream .map(this::buildModuleContext) - .filter(ModuleContext::isNotEmpty); + .filter(ModuleInfo::isNotEmpty); } public Stream getRootSubsystems() { @@ -114,7 +112,7 @@ public boolean contains(String name) { return modules.stream().anyMatch(it -> it.getName().equalsIgnoreCase(name)); } - public Optional getModule(String name) { + public Optional getModule(String name) { return modules.stream().filter(it -> it.getName().equalsIgnoreCase(name)).findAny(); } @@ -139,16 +137,17 @@ public void load() { .collect(Collectors.toList()); } - public ModuleContext buildModuleContext(MDCommonModule module) { + public ModuleInfo buildModuleContext(MDCommonModule module) { var bslModules = module.getModules(); var bslModule = bslModules.get(0); return buildModuleContext(bslModule); } - public ModuleContext buildFilteredModuleContext(MDOModule bslModule) { + public ModuleInfo buildFilteredModuleContext(MDOModule bslModule) { return buildModuleContext(buildModuleContext(bslModule)); } - public ModuleContext buildModuleContext(MDOModule bslModule) { + + public ModuleInfo buildModuleContext(MDOModule bslModule) { var owner = (AbstractMDObjectBSL) bslModule.getOwner(); log.debug("Parse module: " + owner.getName() + "." + bslModule.getModuleType()); var srcPath = Path.of(bslModule.getUri()); @@ -164,7 +163,7 @@ public ModuleContext buildModuleContext(MDOModule bslModule) { throw new RuntimeException(owner.getMdoReference().getMdoRef() + ". Module parsing error", e); } - return ModuleContext.builder() + return ModuleInfo.builder() .owner(owner) .module(bslModule) .methods(methods) @@ -218,7 +217,7 @@ private String computeModuleDescription(BSLTokenizer tokenizer) { } } - private ModuleContext buildModuleContext(ModuleContext module) { + private ModuleInfo buildModuleContext(ModuleInfo module) { var stream = module.getMethods().stream(); @@ -230,14 +229,15 @@ private ModuleContext buildModuleContext(ModuleContext module) { stream = stream.filter(this::regionFilter); } - return ModuleContext.builder() + return ModuleInfo.builder() + .module(module.getModule()) .owner(module.getOwner()) - .methods(stream.collect(Collectors.toList())) .description(module.getDescription()) + .methods(stream.collect(Collectors.toList())) .build(); } - private boolean checkModule(ModuleContext module) { + private boolean checkModule(ModuleInfo module) { return true; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/MethodInfo.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/MethodInfo.java index 9f39fb7..a853db0 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/MethodInfo.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/MethodInfo.java @@ -8,6 +8,6 @@ @Builder public class MethodInfo { MethodSymbol method; - ModuleContext module; + ModuleInfo module; boolean publishing; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleInfo.java similarity index 96% rename from src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleContext.java rename to src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleInfo.java index 7e505bf..5afe01c 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleInfo.java @@ -11,7 +11,7 @@ @Builder @Value -public class ModuleContext { +public class ModuleInfo { AbstractMDObjectBSL owner; MDOModule module; List methods; diff --git a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java index 2b0394e..1c1fa8b 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java +++ b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java @@ -8,11 +8,11 @@ import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.bsl.Filter; import ru.alkoleft.bsl.doc.bsl.symbols.RegionSymbol; -import ru.alkoleft.bsl.doc.render.Factory; import ru.alkoleft.bsl.doc.render.OutputFormat; import ru.alkoleft.bsl.doc.render.Render; import ru.alkoleft.bsl.doc.render.RenderOptions; import ru.alkoleft.bsl.doc.render.StructureRender; +import ru.alkoleft.bsl.doc.render.handlebars.RenderContext; import ru.alkoleft.bsl.doc.structure.Builder; import java.nio.file.Path; @@ -52,13 +52,11 @@ public void run() { log.debug("Options: " + options.toString()); var bslContext = new BslContext(sources, filter); - var renderContext = Factory.createRenderContext(options); + var renderContext = RenderContext.Factory.create(options); var structure = Builder.build(bslContext); Builder.print(structure); new StructureRender().render(new Render(renderContext), structure, destination); -// var render = new SubsystemTreeRender(bslContext, renderContext, destination); -// render.render(); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/Factory.java b/src/main/java/ru/alkoleft/bsl/doc/render/Factory.java deleted file mode 100644 index 8616227..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/render/Factory.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.alkoleft.bsl.doc.render; - -import lombok.experimental.UtilityClass; -import ru.alkoleft.bsl.doc.render.handlebars.HandlebarsRenderContext; - -@UtilityClass -public class Factory { - public RenderContext createRenderContext(RenderOptions options) { - return new HandlebarsRenderContext(options.getOutputFormat().getPath()); - } -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/OutputFormat.java b/src/main/java/ru/alkoleft/bsl/doc/render/OutputFormat.java index 0b5fd20..8952d91 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/OutputFormat.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/OutputFormat.java @@ -2,11 +2,12 @@ import lombok.Getter; +@Getter public enum OutputFormat { Docusaurus("docusaurus"), - Markdown("md"); + Markdown("md"), + ConfluenceMarkdown("confluence-md"); - @Getter private final String path; OutputFormat(String path) { diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java index d001325..ecd59d9 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java @@ -1,11 +1,11 @@ package ru.alkoleft.bsl.doc.render; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; -import com.github._1c_syntax.mdclasses.mdo.MDCommonModule; import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import ru.alkoleft.bsl.doc.bsl.ModuleContext; +import ru.alkoleft.bsl.doc.bsl.ModuleInfo; +import ru.alkoleft.bsl.doc.render.contexts.ContextFactory; +import ru.alkoleft.bsl.doc.render.handlebars.RenderContext; import java.nio.file.Path; import java.util.Collections; @@ -21,54 +21,18 @@ public Render(RenderContext renderContext) { } @SneakyThrows - public void render(ModuleContext module, Path outputPath, int index) { - var itemRender = renderContext.getRender("module"); - + public void render(ModuleInfo module, Path outputPath, int index) { log.debug("Render module '{}' to '{}'", module.getOwner().getName(), outputPath); - itemRender.put("index", index); - itemRender.put("name", module.getOwner().getName()); - itemRender.put("present", getPresent(module.getOwner())); - itemRender.put("isCommonModule", module.getOwner() instanceof MDCommonModule); - itemRender.put("type", module.getOwner().getMdoType().getNameRu()); - itemRender.put("methods", module.getMethods()); - itemRender.put("description", module.getDescription()); - itemRender.renderToFile(outputPath); - } - - private String getPresent(AbstractMDObjectBase object) { - if (object.getSynonyms().isEmpty()) { - return object.getName(); - } else { - return object.getSynonyms().get(0).getContent(); - } - } - - public void render(ModuleContext module, StructureStrategy strategy, int index) { - var path = strategy.getModulePath(module); - render(module, path, index); + var context = ContextFactory.create(module, index); + renderContext.renderToFile("module", context, outputPath); } @SneakyThrows public void render(MDSubsystem subsystem, Path path, int level, List childrenItems) { - var itemRender = renderContext.getRender("subsystem"); - log.debug("Render module '{}' to '{}'", subsystem.getName(), path); - - itemRender.put("level", level); - itemRender.put("name", subsystem.getName()); - itemRender.put("present", getPresent(subsystem)); - itemRender.put("description", subsystem.getComment()); - itemRender.put("children", childrenItems); - itemRender.renderToFile(path); - } + log.debug("Render subsystem '{}' to '{}'", subsystem.getName(), path); - public void render(MDSubsystem subsystem, StructureStrategy strategy, int level) { - Path path; - if (level == 0) { - path = strategy.getPath().resolve("index.md"); - } else { - path = strategy.getObjectPath(subsystem).resolve("index.md"); - } - render(subsystem, path, level, Collections.emptyList()); + var context = ContextFactory.create(subsystem, childrenItems, 0, level); + renderContext.renderToFile("subsystem", context, path); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/RenderContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/RenderContext.java deleted file mode 100644 index 81fe585..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/render/RenderContext.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.alkoleft.bsl.doc.render; - -import ru.alkoleft.bsl.doc.bsl.BslContext; - -import java.io.IOException; - -public interface RenderContext { - ItemRender getRender(String name) throws IOException; - - void setContext(BslContext context); -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureStrategy.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureStrategy.java deleted file mode 100644 index 55df4ca..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/render/StructureStrategy.java +++ /dev/null @@ -1,121 +0,0 @@ -package ru.alkoleft.bsl.doc.render; - -import com.github._1c_syntax.bsl.mdo.MD; -import com.github._1c_syntax.mdclasses.Configuration; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; -import lombok.Getter; -import lombok.SneakyThrows; -import ru.alkoleft.bsl.doc.bsl.ModuleContext; - -import java.nio.file.Files; -import java.nio.file.Path; - -public abstract class StructureStrategy { - - @Getter - protected Path path; - protected String extension; - - StructureStrategy(Path path, String extension) { - this.path = path; - this.extension = extension; - - createIfNotExists(path); - } - - public Path getPath(AbstractMDObjectBase object) { - Path objectPath = path.resolve(getObjectPath(object)); - createIfNotExists(objectPath.getParent()); - return objectPath; - - } - - public Path getPath(MD object) { - return path.resolve(getFileName(object)); - } - - public String getLink(AbstractMDObjectBase object) { - return "../" + getObjectPath(object); - } - - protected abstract Path getObjectPath(AbstractMDObjectBase object); - - protected abstract Path getModulePath(ModuleContext module); - - public String getFileName(MD object) { - return String.format("%s.%s", object.getName(), extension); - } - - public String getFileName(Configuration object) { - return String.format("configuration.%s", extension); - } - - @SneakyThrows - protected void createIfNotExists(Path path) { - if (!Files.exists(path)) { - Files.createDirectories(path); - } - } - - public static class Metadata extends StructureStrategy { - public Metadata(Path path, String extension) { - super(path, extension); - } - - @Override - public Path getObjectPath(AbstractMDObjectBase object) { - return Path.of(object.getMdoType().getGroupName(), getFileName(object)); - } - - @Override - public Path getModulePath(ModuleContext module) { - var object = module.getOwner(); - var modulePath = path - .resolve(object.getMdoType().getGroupName()) - .resolve(getFileName(object)); - createIfNotExists(modulePath.getParent()); - return modulePath; - } - } - - public static class Subsystems extends StructureStrategy { - - boolean withRootSubsystem; - - public Subsystems(Path path, String extension, boolean withRootSubsystem) { - super(path, extension); - this.withRootSubsystem = withRootSubsystem; - } - - @Override - protected Path getObjectPath(AbstractMDObjectBase object) { - var basePath = Path.of(""); - AbstractMDObjectBase owner = object; - while (true) { - var subsytems = owner.getIncludedSubsystems(); - if (subsytems.isEmpty()) { - break; - } - owner = subsytems.get(0); - if (!withRootSubsystem && owner.getIncludedSubsystems().isEmpty()) { - break; - } - basePath = Path.of(owner.getName(), basePath.toString()); - } - basePath = path.resolve(basePath.toString()); - basePath = basePath.resolve(object.getName()); - createIfNotExists(basePath); - return basePath; - } - - @Override - protected Path getModulePath(ModuleContext module) { - var object = module.getOwner(); - var basePath = getObjectPath(object); - - var modulePath = basePath.resolve(getFileName(object)); - createIfNotExists(modulePath.getParent()); - return modulePath; - } - } -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/SubsystemTreeRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/SubsystemTreeRender.java deleted file mode 100644 index 57ec336..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/render/SubsystemTreeRender.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.alkoleft.bsl.doc.render; - -import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; -import ru.alkoleft.bsl.doc.bsl.BslContext; - -import java.nio.file.Path; -import java.util.concurrent.atomic.AtomicInteger; - -public class SubsystemTreeRender { - - StructureStrategy.Subsystems strategy; - Render render; - - BslContext context; - boolean withRoot; - - public SubsystemTreeRender(BslContext context, RenderContext renderContext, Path destination) { - withRoot = context.getFilter().getRootSubsystems().size() > 1; - render = new Render(renderContext); - strategy = new StructureStrategy.Subsystems(destination, "md", withRoot); - this.context = context; - } - - public void render() { - var rootSubsystems = context.getRootSubsystems() - .filter(it -> context.getFilter().getRootSubsystems().contains(it.getName())); - - if (withRoot) { - rootSubsystems.forEach(it -> renderSubsystem(it, 1)); - } else { - rootSubsystems - .forEach(it -> renderSubsystem(it, 0)); - } - } - - private void renderSubsystem(MDSubsystem subsystem, int level) { - render.render(subsystem, strategy, level); - context.getChildrenSubsystems(subsystem) - .forEach(it -> renderSubsystem(it, level + 1)); - AtomicInteger index = new AtomicInteger(); - context.getSubsystemObjects(subsystem) - .flatMap(it->it.getModules().stream()) - .peek(it -> index.getAndIncrement()) - .map(context::buildModuleContext) - .forEach(it -> render.render(it, strategy, index.get())); - } -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java new file mode 100644 index 0000000..23d5dab --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java @@ -0,0 +1,88 @@ +package ru.alkoleft.bsl.doc.render.contexts; + +import com.github._1c_syntax.bsl.types.ModuleType; +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; +import com.github._1c_syntax.mdclasses.mdo.MDCommonModule; +import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import com.github.jknack.handlebars.Context; +import com.github.jknack.handlebars.context.FieldValueResolver; +import com.github.jknack.handlebars.context.JavaBeanValueResolver; +import com.github.jknack.handlebars.context.MapValueResolver; +import com.github.jknack.handlebars.context.MethodValueResolver; +import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.bsl.ModuleInfo; + +import java.util.List; + +@UtilityClass +public class ContextFactory { + + public Context create(ModuleInfo module, int index) { + var context = ModuleContext.builder() + .index(index) + .name(module.getOwner().getName()) + .present(getPresent(module.getOwner())) + .isCommonModule(module.getOwner() instanceof MDCommonModule) + .ownerType(module.getOwner().getMdoType().getNameRu()) + .moduleType(getPresent(module.getModule().getModuleType())) + .methods(module.getMethods()) + .description(module.getDescription()) + .build(); + return createContext(context); + } + + public Context create(MDSubsystem subsystem, List childrenItems, int index, int level) { + var context = SubsystemContext.builder() + .index(index) + .name(subsystem.getName()) + .present(getPresent(subsystem)) + .description(subsystem.getComment()) + .children(childrenItems) + .level(level) + .build(); + return createContext(context); + } + + private String getPresent(AbstractMDObjectBase object) { + if (object.getSynonyms().isEmpty()) { + return object.getName(); + } else { + return object.getSynonyms().get(0).getContent(); + } + } + + private Context createContext(Object obj) { + return Context.newBuilder(obj) + .resolver( + MapValueResolver.INSTANCE, + JavaBeanValueResolver.INSTANCE, + MethodValueResolver.INSTANCE, + FieldValueResolver.INSTANCE + ) + .build(); + } + + private String getPresent(ModuleType moduleType) { + switch (moduleType) { + case ManagerModule: + return "Модуль менеджера"; + case BotModule: + case ObjectModule: + return "Модуль объекта"; + case HTTPServiceModule: + return "Модуль http-сервиса"; + case WEBServiceModule: + return "Модуль web-сервиса"; + case CommonModule: + return "Модуль"; + case CommandModule: + return "Модуль команды"; + case RecordSetModule: + return "Модуль набора записей"; + case ValueManagerModule: + return "Модуль менеджера значений"; + default: + return moduleType.name(); + } + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java index 5b512d7..551eaef 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java @@ -1,17 +1,21 @@ package ru.alkoleft.bsl.doc.render.contexts; import lombok.Builder; -import lombok.Value; +import lombok.Getter; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; import java.util.List; -@Value @Builder +@Getter public class ModuleContext { int index; String name; String present; String description; - List methods; + boolean isCommonModule; + String ownerType; + String moduleType; + Listmethods; + } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java new file mode 100644 index 0000000..6977198 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java @@ -0,0 +1,17 @@ +package ru.alkoleft.bsl.doc.render.contexts; + +import lombok.Builder; +import lombok.Value; + +import java.util.List; + +@Value +@Builder +public class SubsystemContext { + int index; + String name; + String present; + String description; + List children; + int level; +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarItemRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarItemRender.java deleted file mode 100644 index 80cc207..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarItemRender.java +++ /dev/null @@ -1,33 +0,0 @@ -package ru.alkoleft.bsl.doc.render.handlebars; - -import com.github.jknack.handlebars.Template; -import ru.alkoleft.bsl.doc.render.ItemRender; - -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; - -public class HandlebarItemRender implements ItemRender { - - private final Template template; - - HandlebarItemRender(Template template) { - this.template = template; - } - - Map context = new HashMap<>(); - - @Override - public void put(String key, Object value) { - context.put(key, value); - } - - @Override - public void renderToFile(Path fileName) throws IOException { - try (FileWriter writer = new FileWriter(fileName.toFile())) { - template.apply(context, writer); - } - } -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HelperGreat.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HelperGreat.java deleted file mode 100644 index ba81a02..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HelperGreat.java +++ /dev/null @@ -1,26 +0,0 @@ -package ru.alkoleft.bsl.doc.render.handlebars; - -import com.github.jknack.handlebars.Helper; -import com.github.jknack.handlebars.Options; - -import java.io.IOException; -import java.util.List; - -public class HelperGreat implements Helper { - @Override - public Object apply(Object context, Options options) throws IOException { - int secondValue = options.param(0, 0); - boolean success = false; - if (context instanceof Integer) { - success = ((Integer) context) > secondValue; - } - if (context instanceof List) { - success = ((List) context).size() > secondValue; - } - - if (success) { - return options.fn(this); - } - return options.inverse(this); - } -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarsRenderContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java similarity index 57% rename from src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarsRenderContext.java rename to src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java index 9d293b4..dfe8a07 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandlebarsRenderContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java @@ -1,15 +1,21 @@ package ru.alkoleft.bsl.doc.render.handlebars; +import com.github.jknack.handlebars.Context; import com.github.jknack.handlebars.Handlebars; import com.github.jknack.handlebars.Template; +import com.github.jknack.handlebars.helper.ConditionalHelpers; +import lombok.SneakyThrows; +import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.bsl.BslContext; -import ru.alkoleft.bsl.doc.render.RenderContext; +import ru.alkoleft.bsl.doc.render.RenderOptions; +import java.io.FileWriter; import java.io.IOException; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; -public class HandlebarsRenderContext implements RenderContext { +public class RenderContext { private final String path; private final Handlebars handlebars; @@ -17,13 +23,14 @@ public class HandlebarsRenderContext implements RenderContext { private final HandleLinks linksRender; - public HandlebarsRenderContext(String path) { + private RenderContext(String path) { this.path = path; handlebars = new Handlebars().with(value -> value); handlebars.registerHelper("links", linksRender = new HandleLinks()); handlebars.registerHelper("shift", new Shifter()); handlebars.registerHelper("debug", new RenderDebugger()); - handlebars.registerHelper("great", new HelperGreat()); + handlebars.registerHelper("great", ConditionalHelpers.gt); + handlebars.registerHelper("eq", ConditionalHelpers.eq); handlebars.registerHelper("single-line", new SingleLineHelper()); } @@ -31,9 +38,12 @@ public void setContext(BslContext context) { linksRender.context = context; } - @Override - public HandlebarItemRender getRender(String name) throws IOException { - return new HandlebarItemRender(getTemplate(name)); + @SneakyThrows + public void renderToFile(String templateName, Context context, Path output){ + var template = getTemplate(templateName); + try (FileWriter writer = new FileWriter(output.toFile())) { + template.apply(context, writer); + } } private Template getTemplate(String name) throws IOException { @@ -45,4 +55,11 @@ private Template getTemplate(String name) throws IOException { loadedTemplates.put(name, template); return template; } + + @UtilityClass + public static class Factory{ + public RenderContext create(RenderOptions options) { + return new RenderContext(options.getOutputFormat().getPath()); + } + } } diff --git a/src/main/resources/confluence-md/module.hbs b/src/main/resources/confluence-md/module.hbs new file mode 100644 index 0000000..bba3b5b --- /dev/null +++ b/src/main/resources/confluence-md/module.hbs @@ -0,0 +1,54 @@ +# {{moduleType}} `{{#unless isCommonModule}}{{ownerType}}.{{/unless}}{{name}}` + +{{~#if description}} + +{{links description}} + +{{~/if}} + +{{~#each methods}} + +###### {{name}}({{#each parameters}}{{#if @index}}, {{/if}}{{name}}{{/each}}) + +{{#if deprecated~}} +:::caution Устаревший +::: +{{~/if}} +{{~#if description}}{{links description}}{{/if}} +{{~#if parameters}} + + +{{#each parameters as | parameter|}} +* `{{parameter.name}}`{{#debug}}Формирование описания параметра {{parameter.name}}{{/debug}} + {{~#eq parameter.types.size 1~}} + {{~#each parameter.types as | type typeIndex|}} - {{#with type~}}{{#shift 3}}{{#block "confluence-md/value-definition"}}{{/block}}{{/shift}}{{~/with}} + {{~else}} - {{links description}} + {{~/each}} + {{else}} + {{~#each parameter.types as | type typeIndex|}} + * {{#with type}}{{#shift 3}}{{#block "confluence-md/value-definition"}}{{/block}}{{/shift}}{{~/with}} + {{~else}} - {{links description}} + {{~/each}} + {{/eq}} +{{~/each}} + {{~/if}} +{{~#if returnedValue}} + +*Возвращаемое значение* + +{{#with returnedValue}}{{#block "confluence-md/value-definition"}}{{/block}}{{~/with}} +{{~/if}} + +{{~#if examples}} + +Примеры: + +```bsl +{{~#each examples}} +{{this}} +{{~/each}} +``` + +{{/if}} + +{{/each}} \ No newline at end of file diff --git a/src/main/resources/confluence-md/subsystem.hbs b/src/main/resources/confluence-md/subsystem.hbs new file mode 100644 index 0000000..9dec684 --- /dev/null +++ b/src/main/resources/confluence-md/subsystem.hbs @@ -0,0 +1,8 @@ +# {{#great level 1}}Подсистема {{/great}}{{present}} + +{{description}} + +Содержимое: +{{#each children as | item|}} +* [{{item}}]({{item}}) +{{/each}} \ No newline at end of file diff --git a/src/main/resources/confluence-md/value-definition.hbs b/src/main/resources/confluence-md/value-definition.hbs new file mode 100644 index 0000000..e25410b --- /dev/null +++ b/src/main/resources/confluence-md/value-definition.hbs @@ -0,0 +1,11 @@ +{{~#if link~}} +{{links link}} +{{~/if}} +{{~#if parameters}} +`{{name}}` - {{description}} + +{{#each parameters as |parameter| }}{{#with parameter}} +{{~#shift}}* `{{name}}` - {{#each types as | type|~}}{{#with type}}{{#block "confluence-md/value-definition"}}{{/block}}{{/with}}{{~/each}}{{/shift}} +{{/with}}{{/each}} +{{~else}}`{{name}}` - {{#links description}}{{#block "confluence-md/value-definition"}}{{/block}}{{/links}} +{{~/if}} \ No newline at end of file diff --git a/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java new file mode 100644 index 0000000..0971c1a --- /dev/null +++ b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java @@ -0,0 +1,31 @@ +package ru.alkoleft.bsl.doc.commands; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ru.alkoleft.bsl.doc.bsl.symbols.RegionSymbol; +import ru.alkoleft.bsl.doc.render.OutputFormat; + +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class RenderCommandTest { + + RenderCommand cmd; + @BeforeEach + void setUp() { + cmd = new RenderCommand(); + cmd.sources = Path.of( "/home/common/develop/repos/open-source/bsldoc/src/test/resources/configuration"); + cmd.destination = Path.of("/tmp/bsl-doc-fixture"); + cmd.format = OutputFormat.ConfluenceMarkdown; + cmd.onlySubsystems = List.of("ППИ"); + cmd.regions = List.of(RegionSymbol.PUBLIC_REGION_RU); + } + + @Test + void run() { + cmd.run(); + } +} \ No newline at end of file From af9cc5c238e646a703032393f6f92555b96a2ad0 Mon Sep 17 00:00:00 2001 From: Aleksey Ko Date: Tue, 10 Oct 2023 14:17:24 +0300 Subject: [PATCH 10/27] Refactoring --- .../bsl/doc/commands/RenderCommand.java | 4 +-- .../bsl/doc/options/OutputFormat.java | 16 ++++++++++ .../{render => options}/RenderOptions.java | 3 +- .../alkoleft/bsl/doc/render/ItemRender.java | 10 ------ .../alkoleft/bsl/doc/render/OutputFormat.java | 16 ---------- .../ru/alkoleft/bsl/doc/render/Render.java | 2 -- .../bsl/doc/render/StructureRender.java | 31 +++++++++++-------- .../doc/render/contexts/ModuleContext.java | 7 ++--- .../doc/render/contexts/SubsystemContext.java | 2 +- .../doc/render/handlebars/RenderContext.java | 20 ++++++------ .../Debugger.java} | 4 +-- .../{HandleLinks.java => helpers/Links.java} | 22 ++++++------- .../handlebars/{ => helpers}/Shifter.java | 2 +- .../SingleLine.java} | 4 +-- .../alkoleft/bsl/doc/structure/Builder.java | 5 +-- .../ru/alkoleft/bsl/doc/structure/Item.java | 9 +++++- ...s.java => SubsystemsStructureBuilder.java} | 2 +- src/main/resources/confluence-md/module.hbs | 2 +- .../bsl/doc/commands/RenderCommandTest.java | 5 +-- ...\260\320\267\320\264\320\265\320\2731.mdo" | 1 - 20 files changed, 82 insertions(+), 85 deletions(-) create mode 100644 src/main/java/ru/alkoleft/bsl/doc/options/OutputFormat.java rename src/main/java/ru/alkoleft/bsl/doc/{render => options}/RenderOptions.java (80%) delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/ItemRender.java delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/OutputFormat.java rename src/main/java/ru/alkoleft/bsl/doc/render/handlebars/{RenderDebugger.java => helpers/Debugger.java} (74%) rename src/main/java/ru/alkoleft/bsl/doc/render/handlebars/{HandleLinks.java => helpers/Links.java} (71%) rename src/main/java/ru/alkoleft/bsl/doc/render/handlebars/{ => helpers}/Shifter.java (93%) rename src/main/java/ru/alkoleft/bsl/doc/render/handlebars/{SingleLineHelper.java => helpers/SingleLine.java} (83%) rename src/main/java/ru/alkoleft/bsl/doc/structure/{Subsystems.java => SubsystemsStructureBuilder.java} (97%) diff --git a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java index 1c1fa8b..aa983a4 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java +++ b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java @@ -54,9 +54,9 @@ public void run() { var bslContext = new BslContext(sources, filter); var renderContext = RenderContext.Factory.create(options); - var structure = Builder.build(bslContext); + var structure = Builder.build(bslContext, options); Builder.print(structure); - new StructureRender().render(new Render(renderContext), structure, destination); + new StructureRender(new Render(renderContext)).render(structure, destination); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/options/OutputFormat.java b/src/main/java/ru/alkoleft/bsl/doc/options/OutputFormat.java new file mode 100644 index 0000000..124baaa --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/options/OutputFormat.java @@ -0,0 +1,16 @@ +package ru.alkoleft.bsl.doc.options; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum OutputFormat { + Docusaurus("docusaurus", "md"), + Markdown("md", "md"), + ConfluenceMarkdown("confluence-md", "md"); + + private final String path; + private final String extension; + +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/RenderOptions.java b/src/main/java/ru/alkoleft/bsl/doc/options/RenderOptions.java similarity index 80% rename from src/main/java/ru/alkoleft/bsl/doc/render/RenderOptions.java rename to src/main/java/ru/alkoleft/bsl/doc/options/RenderOptions.java index 37bc503..5428aee 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/RenderOptions.java +++ b/src/main/java/ru/alkoleft/bsl/doc/options/RenderOptions.java @@ -1,4 +1,4 @@ -package ru.alkoleft.bsl.doc.render; +package ru.alkoleft.bsl.doc.options; import lombok.Builder; import lombok.Value; @@ -7,6 +7,5 @@ @Value public class RenderOptions { OutputFormat outputFormat; - boolean subsystemHierarchy; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/ItemRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/ItemRender.java deleted file mode 100644 index 8c0ddde..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/render/ItemRender.java +++ /dev/null @@ -1,10 +0,0 @@ -package ru.alkoleft.bsl.doc.render; - -import java.io.IOException; -import java.nio.file.Path; - -public interface ItemRender { - void put(String key, Object value); - - void renderToFile(Path fileName) throws IOException; -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/OutputFormat.java b/src/main/java/ru/alkoleft/bsl/doc/render/OutputFormat.java deleted file mode 100644 index 8952d91..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/render/OutputFormat.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.alkoleft.bsl.doc.render; - -import lombok.Getter; - -@Getter -public enum OutputFormat { - Docusaurus("docusaurus"), - Markdown("md"), - ConfluenceMarkdown("confluence-md"); - - private final String path; - - OutputFormat(String path) { - this.path = path; - } -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java index ecd59d9..e6fd7cf 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java @@ -13,9 +13,7 @@ @Slf4j public class Render { - RenderContext renderContext; - public Render(RenderContext renderContext) { this.renderContext = renderContext; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java index 835b349..075a600 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java @@ -17,16 +17,22 @@ import java.util.stream.Collectors; public class StructureRender implements StructureVisitor { - Render render; - int subsystemLevel = 0; + private final Render render; + private final Stack paths = new Stack<>(); + private final Stack> children = new Stack<>(); + private boolean withRoot = false; + private int subsystemLevel = 0; - Stack paths = new Stack<>(); - Stack> children = new Stack<>(); + public StructureRender(Render render) { + this.render = render; + } - boolean withRoot = false; + public void render(List structure, Path destination) { + paths.clear(); + children.clear(); + subsystemLevel = 0; + withRoot = structure.size() > 1; - public void render(Render render, List structure, Path destination) { - this.render = render; paths.push(destination); children.push(new ArrayList<>()); for (int i = 0; i < structure.size(); i++) { @@ -36,7 +42,7 @@ public void render(Render render, List structure, Path destination) { @Override public void visit(SubsystemItem item, int index) { - boolean isRoot = subsystemLevel == 0; + var isRoot = subsystemLevel == 0; subsystemLevel++; children.push(new ArrayList<>()); Path path; @@ -50,10 +56,9 @@ public void visit(SubsystemItem item, int index) { paths.pop(); } subsystemLevel--; - List childrenItems = - children.pop().stream() - .map(it -> it.toString().substring(path.toString().length() + 1)) - .collect(Collectors.toList()); + var childrenItems = children.pop().stream() + .map(it -> it.toString().substring(path.toString().length() + 1)) + .collect(Collectors.toList()); if (!childrenItems.isEmpty()) { render.render((MDSubsystem) item.getObject(), path.resolve("index.md"), subsystemLevel, childrenItems); children.peek().add(path.resolve("index.md")); @@ -67,7 +72,7 @@ public void visit(ModuleItem item, int index) { if (moduleContext.isEmpty()) { return; } - final var path = paths.peek().resolve(item.getModule().getOwner().getName() + ".md"); + var path = paths.peek().resolve(item.getModule().getOwner().getName() + ".md"); if (!Files.exists(path.getParent())) { Files.createDirectories(path.getParent()); } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java index 551eaef..e0a45bc 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java @@ -1,13 +1,13 @@ package ru.alkoleft.bsl.doc.render.contexts; import lombok.Builder; -import lombok.Getter; +import lombok.Value; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; import java.util.List; @Builder -@Getter +@Value public class ModuleContext { int index; String name; @@ -16,6 +16,5 @@ public class ModuleContext { boolean isCommonModule; String ownerType; String moduleType; - Listmethods; - + List methods; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java index 6977198..e867862 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java @@ -5,8 +5,8 @@ import java.util.List; -@Value @Builder +@Value public class SubsystemContext { int index; String name; diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java index dfe8a07..8432aaf 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java @@ -7,7 +7,11 @@ import lombok.SneakyThrows; import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.bsl.BslContext; -import ru.alkoleft.bsl.doc.render.RenderOptions; +import ru.alkoleft.bsl.doc.options.RenderOptions; +import ru.alkoleft.bsl.doc.render.handlebars.helpers.Links; +import ru.alkoleft.bsl.doc.render.handlebars.helpers.Debugger; +import ru.alkoleft.bsl.doc.render.handlebars.helpers.Shifter; +import ru.alkoleft.bsl.doc.render.handlebars.helpers.SingleLine; import java.io.FileWriter; import java.io.IOException; @@ -16,32 +20,30 @@ import java.util.Map; public class RenderContext { - private final String path; private final Handlebars handlebars; private final Map loadedTemplates = new HashMap<>(); - - private final HandleLinks linksRender; + private final Links linksRender; private RenderContext(String path) { this.path = path; handlebars = new Handlebars().with(value -> value); - handlebars.registerHelper("links", linksRender = new HandleLinks()); + handlebars.registerHelper("links", linksRender = new Links()); handlebars.registerHelper("shift", new Shifter()); - handlebars.registerHelper("debug", new RenderDebugger()); + handlebars.registerHelper("debug", new Debugger()); + handlebars.registerHelper("single-line", new SingleLine()); handlebars.registerHelper("great", ConditionalHelpers.gt); handlebars.registerHelper("eq", ConditionalHelpers.eq); - handlebars.registerHelper("single-line", new SingleLineHelper()); } public void setContext(BslContext context) { - linksRender.context = context; + linksRender.setContext(context); } @SneakyThrows public void renderToFile(String templateName, Context context, Path output){ var template = getTemplate(templateName); - try (FileWriter writer = new FileWriter(output.toFile())) { + try (var writer = new FileWriter(output.toFile())) { template.apply(context, writer); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderDebugger.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Debugger.java similarity index 74% rename from src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderDebugger.java rename to src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Debugger.java index d7dc5b8..f268479 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderDebugger.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Debugger.java @@ -1,4 +1,4 @@ -package ru.alkoleft.bsl.doc.render.handlebars; +package ru.alkoleft.bsl.doc.render.handlebars.helpers; import com.github.jknack.handlebars.Helper; import com.github.jknack.handlebars.Options; @@ -7,7 +7,7 @@ import java.io.IOException; @Slf4j -public class RenderDebugger implements Helper { +public class Debugger implements Helper { @Override public Object apply(Object context, Options options) throws IOException { log.debug(options.fn().toString()); diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Links.java similarity index 71% rename from src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java rename to src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Links.java index 6dcced1..67d402c 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/HandleLinks.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Links.java @@ -1,29 +1,29 @@ -package ru.alkoleft.bsl.doc.render.handlebars; +package ru.alkoleft.bsl.doc.render.handlebars.helpers; import com.github.jknack.handlebars.Context; import com.github.jknack.handlebars.Helper; import com.github.jknack.handlebars.Options; +import lombok.Setter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import ru.alkoleft.bsl.doc.bsl.BslContext; -import ru.alkoleft.bsl.doc.bsl.Links; import java.util.Locale; import java.util.regex.Pattern; @Slf4j -public class HandleLinks implements Helper { - Pattern pattern = Pattern.compile("см\\. (([\\wА-Яа-я\\.\\d]+)\\.)*([\\wА-Яа-я\\d]+)"); - - Pattern warningPattern = Pattern.compile("(\\n\\s*\\n|^)(Важно[\\s\\S]+)(\\n\\s*\\n|$)"); - BslContext context; +public class Links implements Helper { + private final Pattern linkPattern = Pattern.compile("см\\. (([\\wА-Яа-я\\.\\d]+)\\.)*([\\wА-Яа-я\\d]+)"); + private final Pattern warningPattern = Pattern.compile("(\\n\\s*\\n|^)(Важно[\\s\\S]+)(\\n\\s*\\n|$)"); + @Setter + private BslContext context; @Override public Object apply(String context, Options options) { - var matcher = pattern.matcher(context); + var matcher = linkPattern.matcher(context); String result; if (matcher.find()) { - result = matcher.replaceAll(matchResult -> replaceTo(matcher.group(0), Links.createLink(matcher.group(2), matcher.group(3)), options)); + result = matcher.replaceAll(matchResult -> replaceTo(matcher.group(0), ru.alkoleft.bsl.doc.bsl.Links.createLink(matcher.group(2), matcher.group(3)), options)); } else { result = context; } @@ -34,7 +34,7 @@ public Object apply(String context, Options options) { } @SneakyThrows - private String replaceTo(String baseValue, Links.Link link, Options options) { + private String replaceTo(String baseValue, ru.alkoleft.bsl.doc.bsl.Links.Link link, Options options) { var methodInfo = BslContext.getCurrent().getMethodInfo(link); if (methodInfo == null || methodInfo.isPublishing() || methodInfo.getMethod() == null) { return String.format("[%s](%s)", baseValue, getLink(link)); @@ -53,7 +53,7 @@ private String handleWarning(String content) { return content; } - private String getLink(Links.Link link) { + private String getLink(ru.alkoleft.bsl.doc.bsl.Links.Link link) { if (link.getOwnerName() != null && link.getMethodName() != null) { return link.getOwnerName() + "#" + link.getMethodName().toLowerCase(Locale.ROOT); } else if (link.getOwnerName() != null) { diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/Shifter.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Shifter.java similarity index 93% rename from src/main/java/ru/alkoleft/bsl/doc/render/handlebars/Shifter.java rename to src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Shifter.java index b7aed18..f1b6400 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/Shifter.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Shifter.java @@ -1,4 +1,4 @@ -package ru.alkoleft.bsl.doc.render.handlebars; +package ru.alkoleft.bsl.doc.render.handlebars.helpers; import com.github.jknack.handlebars.Helper; import com.github.jknack.handlebars.Options; diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/SingleLineHelper.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/SingleLine.java similarity index 83% rename from src/main/java/ru/alkoleft/bsl/doc/render/handlebars/SingleLineHelper.java rename to src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/SingleLine.java index aabff80..9e5833e 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/SingleLineHelper.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/SingleLine.java @@ -1,4 +1,4 @@ -package ru.alkoleft.bsl.doc.render.handlebars; +package ru.alkoleft.bsl.doc.render.handlebars.helpers; import com.github.jknack.handlebars.Helper; import com.github.jknack.handlebars.Options; @@ -6,7 +6,7 @@ import java.io.IOException; -public class SingleLineHelper implements Helper { +public class SingleLine implements Helper { @Override public Object apply(Object context, Options options) throws IOException { var buffer = options.buffer(); diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java index 00ad22e..8805d4d 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java @@ -2,14 +2,15 @@ import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.bsl.BslContext; +import ru.alkoleft.bsl.doc.options.RenderOptions; import java.util.List; @UtilityClass public class Builder { - public List build(BslContext context) { - return new Subsystems(context).buildStructure(); + public List build(BslContext context, RenderOptions options) { + return new SubsystemsStructureBuilder(context).buildStructure(); } public void print(List structure) { diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Item.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Item.java index a5befdd..c71fd0d 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/Item.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/Item.java @@ -2,16 +2,23 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.Setter; import java.util.ArrayList; import java.util.List; -@AllArgsConstructor @Getter public abstract class Item { private final Object object; private final String name; private final List children = new ArrayList<>(); + @Setter + private String pageName; + + public Item(Object object, String name) { + this.object = object; + this.name = name; + } public String getPresent() { return name; diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Subsystems.java b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java similarity index 97% rename from src/main/java/ru/alkoleft/bsl/doc/structure/Subsystems.java rename to src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java index 721f8a0..ea8f3b4 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/Subsystems.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java @@ -10,7 +10,7 @@ import java.util.stream.Collectors; @AllArgsConstructor -public class Subsystems { +public class SubsystemsStructureBuilder { final BslContext context; diff --git a/src/main/resources/confluence-md/module.hbs b/src/main/resources/confluence-md/module.hbs index bba3b5b..c8d5add 100644 --- a/src/main/resources/confluence-md/module.hbs +++ b/src/main/resources/confluence-md/module.hbs @@ -1,4 +1,4 @@ -# {{moduleType}} `{{#unless isCommonModule}}{{ownerType}}.{{/unless}}{{name}}` +# {{moduleType}} {{#unless isCommonModule}}{{ownerType}}.{{/unless}}{{name}} {{~#if description}} diff --git a/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java index 0971c1a..ea2cbce 100644 --- a/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java +++ b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java @@ -3,14 +3,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import ru.alkoleft.bsl.doc.bsl.symbols.RegionSymbol; -import ru.alkoleft.bsl.doc.render.OutputFormat; +import ru.alkoleft.bsl.doc.options.OutputFormat; import java.nio.file.Path; -import java.util.Collections; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; - class RenderCommandTest { RenderCommand cmd; diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" index b7ba36e..2c90f94 100644 --- "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" @@ -7,7 +7,6 @@ true true - CommonModule.СтроковыеФункции СтроковыеФункции Преобразования Subsystem.ППИ From 12964f8788964b5c7923b88f6c0afc62663109a4 Mon Sep 17 00:00:00 2001 From: Aleksey Ko Date: Tue, 10 Oct 2023 18:29:43 +0300 Subject: [PATCH 11/27] =?UTF-8?q?=D0=92=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6?= =?UTF-8?q?=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D0=BE=D0=B1=D1=8A=D0=B5=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=20=D1=80=D1=83?= =?UTF-8?q?=D1=87=D0=BD=D1=8B=D0=BC=D0=B8=20=D0=B4=D0=BE=D0=BA=D0=B0=D0=BC?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/alkoleft/bsl/doc/bsl/BslContext.java | 8 ++- .../bsl/doc/commands/RenderCommand.java | 29 +++++++--- .../processor/MarkdownTitleCleaner.java | 13 +++++ .../doc/content/processor/TitleCleaner.java | 15 +++++ .../alkoleft/bsl/doc/indexer/FileIndexer.java | 26 +++++++++ .../bsl/doc/manual/ManualContent.java | 58 +++++++++++++++++++ .../alkoleft/bsl/doc/model/ContentModel.java | 11 ++++ .../bsl/doc/model/ContentModelBuilder.java | 34 +++++++++++ .../java/ru/alkoleft/bsl/doc/model/Page.java | 14 +++++ .../ru/alkoleft/bsl/doc/model/PageType.java | 7 +++ .../bsl/doc/options/MergeStrategy.java | 8 +++ .../ru/alkoleft/bsl/doc/render/Render.java | 19 ++++++ .../bsl/doc/render/StructureRender.java | 20 +++++-- .../doc/render/handlebars/RenderContext.java | 13 ++++- .../doc/render/processor/AppendProcessor.java | 13 +++++ .../doc/render/processor/MergeProcessor.java | 36 ++++++++++++ .../doc/render/processor/OutputProcessor.java | 55 ++++++++++++++++++ .../bsl/doc/render/processor/Writer.java | 13 +++++ .../alkoleft/bsl/doc/structure/Builder.java | 38 ------------ .../alkoleft/bsl/doc/structure/Factory.java | 42 ++++++++++++++ .../doc/structure/FlatStructureBuilder.java | 16 +++++ .../bsl/doc/structure/StructureBuilder.java | 49 ++++++++++++++++ .../structure/SubsystemsStructureBuilder.java | 44 +------------- .../bsl/doc/commands/RenderCommandTest.java | 6 +- src/test/resources/docs/Hello.md | 1 + .../index.md" | 5 ++ 26 files changed, 497 insertions(+), 96 deletions(-) create mode 100644 src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleCleaner.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/indexer/FileIndexer.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/model/ContentModelBuilder.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/model/Page.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/model/PageType.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/options/MergeStrategy.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/processor/AppendProcessor.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/processor/MergeProcessor.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/processor/OutputProcessor.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/processor/Writer.java delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/FlatStructureBuilder.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java create mode 100644 src/test/resources/docs/Hello.md create mode 100644 "src/test/resources/docs/\320\240\320\260\320\267\320\264\320\265\320\2731/index.md" diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java index 7b040f2..2df3273 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java @@ -65,7 +65,13 @@ public BslContext(Path path, Filter filter) { current = this; } - public Stream getModules() { + public Stream getModules() { + return configuration.getOrderedTopMDObjects().get(MDOType.COMMON_MODULE).stream() + .map(MDCommonModule.class::cast) + .map(it -> it.getModules().get(0)); + } + + public Stream getModulesInfo() { var stream = modules.stream(); if (!filter.getModules().isEmpty()) { diff --git a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java index aa983a4..097c4e0 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java +++ b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java @@ -8,12 +8,15 @@ import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.bsl.Filter; import ru.alkoleft.bsl.doc.bsl.symbols.RegionSymbol; -import ru.alkoleft.bsl.doc.render.OutputFormat; +import ru.alkoleft.bsl.doc.manual.ManualContent; +import ru.alkoleft.bsl.doc.options.MergeStrategy; +import ru.alkoleft.bsl.doc.options.OutputFormat; +import ru.alkoleft.bsl.doc.options.RenderOptions; import ru.alkoleft.bsl.doc.render.Render; -import ru.alkoleft.bsl.doc.render.RenderOptions; import ru.alkoleft.bsl.doc.render.StructureRender; import ru.alkoleft.bsl.doc.render.handlebars.RenderContext; -import ru.alkoleft.bsl.doc.structure.Builder; +import ru.alkoleft.bsl.doc.render.processor.OutputProcessor; +import ru.alkoleft.bsl.doc.structure.StructureBuilder; import java.nio.file.Path; import java.util.List; @@ -31,6 +34,10 @@ public class RenderCommand implements Runnable { List onlySubsystems; @Option(names = {"-r", "--regions"}, split = " ", defaultValue = RegionSymbol.PUBLIC_REGION_RU + " " + RegionSymbol.PUBLIC_REGION_EN) List regions; + @Option(names = {"-m", "--manual-docs"}, description = "Path to manual documentations") + Path manualDocumentation; + @Option(names = {"-ms", "--merge-strategy"}, description = "Merge strategy for manual and generated documentation", defaultValue = "NONE") + MergeStrategy mergeStrategy; @SneakyThrows @Override @@ -50,13 +57,21 @@ public void run() { log.debug("Filter: " + filter.toString()); log.debug("Options: " + options.toString()); + log.debug("Manual: " + manualDocumentation); + log.debug("Merge manual: " + mergeStrategy); var bslContext = new BslContext(sources, filter); - var renderContext = RenderContext.Factory.create(options); - var structure = Builder.build(bslContext, options); - Builder.print(structure); + var manual = new ManualContent(manualDocumentation, destination); + manual.buildModel(options.getOutputFormat()); + manual.copy(); + + var structure = StructureBuilder.Factory.build(bslContext, options); + StructureBuilder.Factory.print(structure); - new StructureRender(new Render(renderContext)).render(structure, destination); + var renderContext = RenderContext.Factory.create(options); + var processor = OutputProcessor.Factory.create(mergeStrategy); + processor.init(new Render(renderContext), options.getOutputFormat(), manual); + new StructureRender(processor).render(structure, destination); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java b/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java new file mode 100644 index 0000000..4995231 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java @@ -0,0 +1,13 @@ +package ru.alkoleft.bsl.doc.content.processor; + +import java.io.StringReader; +import java.util.stream.Collectors; + +public class MarkdownTitleCleaner implements TitleCleaner { + @Override + public String cleanTitle(String content) { + return content.lines() + .filter(it -> !it.startsWith("# ")) + .collect(Collectors.joining("\n")); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleCleaner.java b/src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleCleaner.java new file mode 100644 index 0000000..7a7de2e --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleCleaner.java @@ -0,0 +1,15 @@ +package ru.alkoleft.bsl.doc.content.processor; + +import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.options.OutputFormat; + +public interface TitleCleaner { + String cleanTitle(String content); + + @UtilityClass + class Factory { + public TitleCleaner create(OutputFormat format) { + return new MarkdownTitleCleaner(); + } + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/indexer/FileIndexer.java b/src/main/java/ru/alkoleft/bsl/doc/indexer/FileIndexer.java new file mode 100644 index 0000000..50f27a3 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/indexer/FileIndexer.java @@ -0,0 +1,26 @@ +package ru.alkoleft.bsl.doc.indexer; + +import lombok.AllArgsConstructor; +import lombok.SneakyThrows; +import org.apache.commons.io.FilenameUtils; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Stream; + +@AllArgsConstructor +public class FileIndexer { + private final String fileExtension; + + @SneakyThrows + public Stream pagePaths(Path rootPath) { + return Files.walk(rootPath) + .filter(path -> path.toFile().isFile()) + .filter(this::matchFileExtension); + + } + + protected boolean matchFileExtension(Path path) { + return FilenameUtils.getExtension(path.toString()).equals(fileExtension); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java b/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java new file mode 100644 index 0000000..ffb3e7e --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java @@ -0,0 +1,58 @@ +package ru.alkoleft.bsl.doc.manual; + +import lombok.SneakyThrows; +import org.apache.commons.io.FileUtils; +import ru.alkoleft.bsl.doc.model.ContentModel; +import ru.alkoleft.bsl.doc.model.ContentModelBuilder; +import ru.alkoleft.bsl.doc.model.Page; +import ru.alkoleft.bsl.doc.options.OutputFormat; + +import java.nio.file.Path; + +public class ManualContent { + private final Path location; + private final Path destination; + private ContentModel localModel; + private ContentModel destinationModel; + + public ManualContent(Path location, Path destination) { + this.location = location; + this.destination = destination; + } + + public void buildModel(OutputFormat format) { + if (location == null) { + return; + } + localModel = ContentModelBuilder.build(location, format); + destinationModel = null; + } + + public void copy() { + if (location == null) { + return; + } + copyFolder(location, destination); + destinationModel = new ContentModel(); + localModel.getPages().stream() + .map(it -> createDestinationPage(it, location, destination)) + .forEach(destinationModel.getPages()::add); + } + + public boolean contains(Path path){ + return destinationModel.getPages() + .stream() + .map(Page::getPath) + .anyMatch(it->it.equals(path)); + } + + private Page createDestinationPage(Page localPage, Path local, Path dest) { + var destPath = dest.resolve(local.relativize(localPage.getPath())); + return new Page(destPath, localPage.getTitle(), localPage.getType()); + } + + @SneakyThrows + private void copyFolder(Path src, Path dest) { + FileUtils.copyDirectory(src.toFile(), dest.toFile()); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java new file mode 100644 index 0000000..e0c50d7 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java @@ -0,0 +1,11 @@ +package ru.alkoleft.bsl.doc.model; + +import lombok.Value; + +import java.util.ArrayList; +import java.util.List; + +@Value +public class ContentModel { + List pages = new ArrayList<>(); +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/model/ContentModelBuilder.java b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModelBuilder.java new file mode 100644 index 0000000..04aeefc --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModelBuilder.java @@ -0,0 +1,34 @@ +package ru.alkoleft.bsl.doc.model; + +import lombok.SneakyThrows; +import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.indexer.FileIndexer; +import ru.alkoleft.bsl.doc.options.OutputFormat; + +import java.nio.file.Files; +import java.nio.file.Path; + +@UtilityClass +public class ContentModelBuilder { + public ContentModel build(Path location, OutputFormat format) { + var model = new ContentModel(); + + try (var files = new FileIndexer(format.getExtension()).pagePaths(location)) { + files.map(it -> new Page(it, it.getFileName().getName(0).toString(), PageType.UNKNOWN)) + .peek(it -> it.setTitle(extractTitle(it.getPath()))) + .forEach(model.getPages()::add); + } + + return model; + } + + @SneakyThrows + private String extractTitle(Path path) { + try (var lines = Files.lines(path)) { + return lines + .filter(it -> it.startsWith("# ")) + .findFirst() + .map(it -> it.substring(2).trim()).orElse(null); + } + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/model/Page.java b/src/main/java/ru/alkoleft/bsl/doc/model/Page.java new file mode 100644 index 0000000..8a0d4eb --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/model/Page.java @@ -0,0 +1,14 @@ +package ru.alkoleft.bsl.doc.model; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.nio.file.Path; + +@Data +@AllArgsConstructor +public class Page { + private Path path; + private String title; + private PageType type; +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/model/PageType.java b/src/main/java/ru/alkoleft/bsl/doc/model/PageType.java new file mode 100644 index 0000000..d4c2f88 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/model/PageType.java @@ -0,0 +1,7 @@ +package ru.alkoleft.bsl.doc.model; + +public enum PageType { + UNKNOWN, + SUBSYSTEM, + MODULE +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/options/MergeStrategy.java b/src/main/java/ru/alkoleft/bsl/doc/options/MergeStrategy.java new file mode 100644 index 0000000..fbc04f9 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/options/MergeStrategy.java @@ -0,0 +1,8 @@ +package ru.alkoleft.bsl.doc.options; + +public enum MergeStrategy { + NONE, + REPLACE, + APPEND, + MERGE +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java index e6fd7cf..79e02c1 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java @@ -1,6 +1,7 @@ package ru.alkoleft.bsl.doc.render; import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import lombok.Getter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import ru.alkoleft.bsl.doc.bsl.ModuleInfo; @@ -13,7 +14,9 @@ @Slf4j public class Render { + @Getter RenderContext renderContext; + public Render(RenderContext renderContext) { this.renderContext = renderContext; } @@ -26,6 +29,14 @@ public void render(ModuleInfo module, Path outputPath, int index) { renderContext.renderToFile("module", context, outputPath); } + @SneakyThrows + public String render(ModuleInfo module, int index) { + log.debug("Render module '{}'", module.getOwner().getName()); + + var context = ContextFactory.create(module, index); + return renderContext.render("module", context); + } + @SneakyThrows public void render(MDSubsystem subsystem, Path path, int level, List childrenItems) { log.debug("Render subsystem '{}' to '{}'", subsystem.getName(), path); @@ -33,4 +44,12 @@ public void render(MDSubsystem subsystem, Path path, int level, List chi var context = ContextFactory.create(subsystem, childrenItems, 0, level); renderContext.renderToFile("subsystem", context, path); } + + @SneakyThrows + public String render(MDSubsystem subsystem, int level, List childrenItems) { + log.debug("Render subsystem '{}'", subsystem.getName()); + + var context = ContextFactory.create(subsystem, childrenItems, 0, level); + return renderContext.render("subsystem", context); + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java index 075a600..d32c31f 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java @@ -3,6 +3,7 @@ import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; import lombok.SneakyThrows; import ru.alkoleft.bsl.doc.bsl.BslContext; +import ru.alkoleft.bsl.doc.render.processor.OutputProcessor; import ru.alkoleft.bsl.doc.structure.Item; import ru.alkoleft.bsl.doc.structure.MDObjectItem; import ru.alkoleft.bsl.doc.structure.ModuleItem; @@ -17,14 +18,14 @@ import java.util.stream.Collectors; public class StructureRender implements StructureVisitor { - private final Render render; + private final OutputProcessor outputProcessor; private final Stack paths = new Stack<>(); private final Stack> children = new Stack<>(); private boolean withRoot = false; private int subsystemLevel = 0; - public StructureRender(Render render) { - this.render = render; + public StructureRender(OutputProcessor outputProcessor) { + this.outputProcessor = outputProcessor; } public void render(List structure, Path destination) { @@ -60,8 +61,12 @@ public void visit(SubsystemItem item, int index) { .map(it -> it.toString().substring(path.toString().length() + 1)) .collect(Collectors.toList()); if (!childrenItems.isEmpty()) { - render.render((MDSubsystem) item.getObject(), path.resolve("index.md"), subsystemLevel, childrenItems); - children.peek().add(path.resolve("index.md")); + var itemPath = path.resolve("index.md"); + if (outputProcessor.needRender(itemPath)) { + var content = outputProcessor.getRender().render((MDSubsystem) item.getObject(), subsystemLevel, childrenItems); + outputProcessor.save(itemPath, content); + } + children.peek().add(itemPath); } } @@ -77,7 +82,10 @@ public void visit(ModuleItem item, int index) { Files.createDirectories(path.getParent()); } children.peek().add(path); - render.render(moduleContext, path, index); + if (outputProcessor.needRender(path)) { + var content = outputProcessor.getRender().render(moduleContext, index); + outputProcessor.save(path, content); + } } @Override diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java index 8432aaf..b889861 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java @@ -15,6 +15,7 @@ import java.io.FileWriter; import java.io.IOException; +import java.io.StringWriter; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; @@ -41,13 +42,21 @@ public void setContext(BslContext context) { } @SneakyThrows - public void renderToFile(String templateName, Context context, Path output){ + public void renderToFile(String templateName, Context context, Path output) { var template = getTemplate(templateName); try (var writer = new FileWriter(output.toFile())) { template.apply(context, writer); } } + @SneakyThrows + public String render(String templateName, Context context) { + var template = getTemplate(templateName); + var writer = new StringWriter(); + template.apply(context, writer); + return writer.toString(); + } + private Template getTemplate(String name) throws IOException { if (loadedTemplates.containsKey(name)) { return loadedTemplates.get(name); @@ -59,7 +68,7 @@ private Template getTemplate(String name) throws IOException { } @UtilityClass - public static class Factory{ + public static class Factory { public RenderContext create(RenderOptions options) { return new RenderContext(options.getOutputFormat().getPath()); } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/processor/AppendProcessor.java b/src/main/java/ru/alkoleft/bsl/doc/render/processor/AppendProcessor.java new file mode 100644 index 0000000..4a60f07 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/processor/AppendProcessor.java @@ -0,0 +1,13 @@ +package ru.alkoleft.bsl.doc.render.processor; + +import ru.alkoleft.bsl.doc.manual.ManualContent; +import ru.alkoleft.bsl.doc.render.Render; + +import java.nio.file.Path; + +public class AppendProcessor extends OutputProcessor { + @Override + public boolean needRender(Path location) { + return !manualContent.contains(location); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/processor/MergeProcessor.java b/src/main/java/ru/alkoleft/bsl/doc/render/processor/MergeProcessor.java new file mode 100644 index 0000000..681a0d6 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/processor/MergeProcessor.java @@ -0,0 +1,36 @@ +package ru.alkoleft.bsl.doc.render.processor; + +import com.github.jknack.handlebars.internal.Files; +import lombok.SneakyThrows; +import ru.alkoleft.bsl.doc.content.processor.TitleCleaner; +import ru.alkoleft.bsl.doc.manual.ManualContent; +import ru.alkoleft.bsl.doc.options.OutputFormat; +import ru.alkoleft.bsl.doc.render.Render; + +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.regex.Pattern; + +public class MergeProcessor extends OutputProcessor { + private static final Pattern replacePattern = Pattern.compile("^.*generated_content.*$", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); + TitleCleaner titleCleaner; + + @Override + public void init(Render render, OutputFormat format, ManualContent manualContent) { + super.init(render, format, manualContent); + titleCleaner = TitleCleaner.Factory.create(format); + } + + @SneakyThrows + @Override + public void save(Path itemPath, String content) { + if (!manualContent.contains(itemPath)) { + super.save(itemPath, content); + return; + } + var manualContent = Files.read(itemPath.toFile(), StandardCharsets.UTF_8); + content = titleCleaner.cleanTitle(content); + var result = replacePattern.matcher(manualContent).replaceFirst(content); + super.save(itemPath, result); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/processor/OutputProcessor.java b/src/main/java/ru/alkoleft/bsl/doc/render/processor/OutputProcessor.java new file mode 100644 index 0000000..16bf0d7 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/processor/OutputProcessor.java @@ -0,0 +1,55 @@ +package ru.alkoleft.bsl.doc.render.processor; + +import lombok.Getter; +import lombok.Setter; +import lombok.SneakyThrows; +import ru.alkoleft.bsl.doc.manual.ManualContent; +import ru.alkoleft.bsl.doc.options.MergeStrategy; +import ru.alkoleft.bsl.doc.options.OutputFormat; +import ru.alkoleft.bsl.doc.render.Render; + +import java.nio.file.Files; +import java.nio.file.Path; + +@Getter +public class OutputProcessor { + @Setter + protected Render render; + @Setter + protected OutputFormat format; + @Setter + protected ManualContent manualContent; + + public boolean needRender(Path location) { + return true; + } + + @SneakyThrows + public void save(Path itemPath, String content) { + Files.writeString(itemPath, content); + } + + public void init(Render render, OutputFormat format, ManualContent manualContent) { + this.render = render; + this.format = format; + this.manualContent = manualContent; + } + + public static class Factory { + public static OutputProcessor create(MergeStrategy strategy) { + OutputProcessor processor; + switch (strategy) { + case APPEND: + processor = new AppendProcessor(); + break; + case MERGE: + processor = new MergeProcessor(); + break; + default: + processor = new OutputProcessor(); + break; + } + return processor; + } + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/processor/Writer.java b/src/main/java/ru/alkoleft/bsl/doc/render/processor/Writer.java new file mode 100644 index 0000000..a160fed --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/processor/Writer.java @@ -0,0 +1,13 @@ +package ru.alkoleft.bsl.doc.render.processor; + +import ru.alkoleft.bsl.doc.options.OutputFormat; + +import java.nio.file.Path; + +public class Writer { + OutputFormat format; + + public void save(Path path, String content) { + + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java deleted file mode 100644 index 8805d4d..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/Builder.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.alkoleft.bsl.doc.structure; - -import lombok.experimental.UtilityClass; -import ru.alkoleft.bsl.doc.bsl.BslContext; -import ru.alkoleft.bsl.doc.options.RenderOptions; - -import java.util.List; - -@UtilityClass -public class Builder { - - public List build(BslContext context, RenderOptions options) { - return new SubsystemsStructureBuilder(context).buildStructure(); - } - - public void print(List structure) { - print(structure, ""); - } - - private void print(List structure, String prefix) { - Item item; - for (int index = 0; index < structure.size(); index++) { - item = structure.get(index); - if (index == structure.size() - 1) { - System.out.printf("%s└── %s\n", prefix, item.getPresent()); - if (!item.getChildren().isEmpty()) { - print(item.getChildren(), prefix + " "); - } - } else { - System.out.printf("%s├── %s\n", prefix, item.getPresent()); - if (!item.getChildren().isEmpty()) { - print(item.getChildren(), prefix + "│   "); - } - } - } - } - -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java new file mode 100644 index 0000000..1f4de10 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java @@ -0,0 +1,42 @@ +package ru.alkoleft.bsl.doc.structure; + +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; +import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.bsl.BslContext; + +@UtilityClass +public class Factory { + public Item createSubSystemItem(MDSubsystem subsystem, BslContext context) { + var item = new SubsystemItem(subsystem); + fillChildrenSubsystems(item, context); + fillChildrenObjects(item, context); + return item; + } + + public Item createMDObjectItem(AbstractMDObjectBSL owner) { + var item = new MDObjectItem(owner); + owner.getModules() + .stream() + .filter(Utils::isManagerModule) + .map(ModuleItem::new) + .forEach(item.getChildren()::add); + return item; + } + + private void fillChildrenObjects(Item item, BslContext context) { + context.getSubsystemObjects((MDSubsystem) item.getObject()) + .map(Factory::createMDObjectItem) + .filter(it -> !it.getChildren().isEmpty()) + .forEach(item.getChildren()::add); + } + + private void fillChildrenSubsystems(Item subsystemItem, BslContext context) { + context.getChildrenSubsystems((MDSubsystem) subsystemItem.getObject()) + .forEach(it -> { + var item = createSubSystemItem(it, context); + subsystemItem.getChildren().add(item); + }); + } + +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/FlatStructureBuilder.java b/src/main/java/ru/alkoleft/bsl/doc/structure/FlatStructureBuilder.java new file mode 100644 index 0000000..7c404b3 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/FlatStructureBuilder.java @@ -0,0 +1,16 @@ +package ru.alkoleft.bsl.doc.structure; + +import ru.alkoleft.bsl.doc.bsl.BslContext; + +import java.util.List; +import java.util.stream.Collectors; + +public class FlatStructureBuilder implements StructureBuilder { + + @Override + public List build(BslContext context) { + return context.getModules() + .map(ModuleItem::new) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java b/src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java new file mode 100644 index 0000000..780a2ff --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java @@ -0,0 +1,49 @@ +package ru.alkoleft.bsl.doc.structure; + +import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.bsl.BslContext; +import ru.alkoleft.bsl.doc.options.RenderOptions; + +import java.util.List; + +public interface StructureBuilder { + + List build(BslContext context); + + @UtilityClass + class Factory { + public StructureBuilder builder(RenderOptions options) { + if(options.isSubsystemHierarchy()){ + return new SubsystemsStructureBuilder(); + }else { + return new FlatStructureBuilder(); + } + } + + public List build(BslContext context, RenderOptions options) { + return builder(options).build(context); + } + + public void print(List structure) { + print(structure, ""); + } + + private void print(List structure, String prefix) { + Item item; + for (int index = 0; index < structure.size(); index++) { + item = structure.get(index); + if (index == structure.size() - 1) { + System.out.printf("%s└── %s\n", prefix, item.getPresent()); + if (!item.getChildren().isEmpty()) { + print(item.getChildren(), prefix + " "); + } + } else { + System.out.printf("%s├── %s\n", prefix, item.getPresent()); + if (!item.getChildren().isEmpty()) { + print(item.getChildren(), prefix + "│   "); + } + } + } + } + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java index ea8f3b4..bed83cf 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java @@ -1,56 +1,18 @@ package ru.alkoleft.bsl.doc.structure; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; -import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; -import lombok.AllArgsConstructor; import ru.alkoleft.bsl.doc.bsl.BslContext; import java.util.List; import java.util.stream.Collectors; -@AllArgsConstructor -public class SubsystemsStructureBuilder { +public class SubsystemsStructureBuilder implements StructureBuilder { - final BslContext context; - - public List buildStructure() { + public List build(BslContext context) { return context.getRootSubsystems() .filter(it -> context.getFilter().getRootSubsystems().contains(it.getName())) - .map(this::createSubSystemItem) + .map(it -> ru.alkoleft.bsl.doc.structure.Factory.createSubSystemItem(it, context)) .collect(Collectors.toList()); } - - private Item createSubSystemItem(MDSubsystem subsystem) { - var item = new SubsystemItem(subsystem); - fillChildrenSubsystems(item); - fillChildrenObjects(item); - return item; - } - - private Item createMDObjectItem(AbstractMDObjectBSL owner) { - var item = new MDObjectItem(owner); - owner.getModules() - .stream() - .filter(Utils::isManagerModule) - .map(ModuleItem::new) - .forEach(item.getChildren()::add); - return item; - } - - private void fillChildrenObjects(Item item) { - context.getSubsystemObjects((MDSubsystem) item.getObject()) - .map(this::createMDObjectItem) - .filter(it -> !it.getChildren().isEmpty()) - .forEach(item.getChildren()::add); - } - - private void fillChildrenSubsystems(Item subsystemItem) { - context.getChildrenSubsystems((MDSubsystem) subsystemItem.getObject()) - .forEach(it -> { - var item = createSubSystemItem(it); - subsystemItem.getChildren().add(item); - }); - } } diff --git a/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java index ea2cbce..b672337 100644 --- a/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java +++ b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import ru.alkoleft.bsl.doc.bsl.symbols.RegionSymbol; +import ru.alkoleft.bsl.doc.options.MergeStrategy; import ru.alkoleft.bsl.doc.options.OutputFormat; import java.nio.file.Path; @@ -11,14 +12,17 @@ class RenderCommandTest { RenderCommand cmd; + @BeforeEach void setUp() { cmd = new RenderCommand(); - cmd.sources = Path.of( "/home/common/develop/repos/open-source/bsldoc/src/test/resources/configuration"); + cmd.sources = Path.of("/home/common/develop/repos/open-source/bsldoc/src/test/resources/configuration"); cmd.destination = Path.of("/tmp/bsl-doc-fixture"); cmd.format = OutputFormat.ConfluenceMarkdown; cmd.onlySubsystems = List.of("ППИ"); cmd.regions = List.of(RegionSymbol.PUBLIC_REGION_RU); + cmd.manualDocumentation = Path.of("/home/common/develop/repos/open-source/bsldoc/src/test/resources/docs"); + cmd.mergeStrategy = MergeStrategy.MERGE; } @Test diff --git a/src/test/resources/docs/Hello.md b/src/test/resources/docs/Hello.md new file mode 100644 index 0000000..b2468c7 --- /dev/null +++ b/src/test/resources/docs/Hello.md @@ -0,0 +1 @@ +# Hi \ No newline at end of file diff --git "a/src/test/resources/docs/\320\240\320\260\320\267\320\264\320\265\320\2731/index.md" "b/src/test/resources/docs/\320\240\320\260\320\267\320\264\320\265\320\2731/index.md" new file mode 100644 index 0000000..61b54a7 --- /dev/null +++ "b/src/test/resources/docs/\320\240\320\260\320\267\320\264\320\265\320\2731/index.md" @@ -0,0 +1,5 @@ +# Раздел 1 + +Основной раздел системы + + \ No newline at end of file From 579d9885220959d5eeaea457afbfac10f24ddd62 Mon Sep 17 00:00:00 2001 From: Aleksey Ko Date: Tue, 10 Oct 2023 19:09:41 +0300 Subject: [PATCH 12/27] =?UTF-8?q?=D0=9E=D0=BF=D1=82=D0=B8=D0=BC=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bsl/doc/bsl/symbols/MethodSymbol.java | 31 +++++++++++++++++++ .../doc/bsl/symbols/ParameterDefinition.java | 4 +++ .../processor/MarkdownTitleCleaner.java | 1 - src/main/resources/confluence-md/module.hbs | 12 ++----- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java index 66868a9..defbdce 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java @@ -64,4 +64,35 @@ private TypeDescription createTypeDescription(com.github._1c_syntax.bsl.language } return result; } + + public String callExample() { + var builder = new StringBuilder(); + if (function) { + builder.append("Функция"); + } else { + builder.append("Процедура"); + } + builder.append(" ").append(name).append("("); + boolean firstParameter = true; + for (var parameter : parameters) { + if (firstParameter) { + firstParameter = false; + } else { + builder.append(", "); + } + if (parameter.isByValue()) { + builder.append("Знач "); + } + builder.append(parameter.getName()); + if (parameter.getDefaultValue().getType() != ParameterDefinition.ParameterType.EMPTY) { + builder.append(" = ").append(parameter.getDefaultValue().getValue()); + } + } + builder.append(")"); + if (isExport()) { + builder.append(" Экспорт"); + } + + return builder.toString(); + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDefinition.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDefinition.java index 61fe89d..289c9e4 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDefinition.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDefinition.java @@ -35,6 +35,10 @@ public List getTypes() { } } + public boolean isRequired() { + return defaultValue.type == ParameterType.EMPTY; + } + public enum ParameterType { DATETIME, BOOLEAN, diff --git a/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java b/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java index 4995231..739ceda 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java +++ b/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java @@ -1,6 +1,5 @@ package ru.alkoleft.bsl.doc.content.processor; -import java.io.StringReader; import java.util.stream.Collectors; public class MarkdownTitleCleaner implements TitleCleaner { diff --git a/src/main/resources/confluence-md/module.hbs b/src/main/resources/confluence-md/module.hbs index c8d5add..edfdd75 100644 --- a/src/main/resources/confluence-md/module.hbs +++ b/src/main/resources/confluence-md/module.hbs @@ -8,18 +8,12 @@ {{~#each methods}} -###### {{name}}({{#each parameters}}{{#if @index}}, {{/if}}{{name}}{{/each}}) +###### {{callExample}} -{{#if deprecated~}} -:::caution Устаревший -::: -{{~/if}} -{{~#if description}}{{links description}}{{/if}} +{{#if description}}{{links description}}{{/if}} {{~#if parameters}} - - {{#each parameters as | parameter|}} -* `{{parameter.name}}`{{#debug}}Формирование описания параметра {{parameter.name}}{{/debug}} +* `{{parameter.name}}`{{#if required}} (**Обязательный**){{/if}} {{~#eq parameter.types.size 1~}} {{~#each parameter.types as | type typeIndex|}} - {{#with type~}}{{#shift 3}}{{#block "confluence-md/value-definition"}}{{/block}}{{/shift}}{{~/with}} {{~else}} - {{links description}} From 9740230a7b81f424b0841a501cd01e190caaa5d4 Mon Sep 17 00:00:00 2001 From: Aleksey Ko Date: Tue, 10 Oct 2023 19:12:35 +0300 Subject: [PATCH 13/27] Reformat code --- LICENSE.md | 1 - README.md | 1 + .../ru/alkoleft/bsl/doc/bsl/BslContext.java | 91 +++++++++---------- .../bsl/doc/bsl/symbols/MethodSymbol.java | 2 +- .../bsl/doc/manual/ManualContent.java | 4 +- .../ru/alkoleft/bsl/doc/render/Render.java | 1 - .../doc/render/handlebars/RenderContext.java | 2 +- .../render/handlebars/helpers/SingleLine.java | 2 +- .../doc/render/processor/AppendProcessor.java | 3 - .../ru/alkoleft/bsl/doc/structure/Item.java | 1 - .../bsl/doc/structure/StructureBuilder.java | 4 +- .../bsl/doc/structure/StructureVisitor.java | 2 - 12 files changed, 51 insertions(+), 63 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 858cc21..f60438a 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,3 @@ - The MIT License (MIT) Copyright (c) 2023 alkoleft diff --git a/README.md b/README.md index f85e651..786c333 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ ### Параметры запуска `bsldoc --format= --only-subsystems= --regions= source destination` + * `--format` - Формат * `--only-subsystems` - Список подсистем, по которым строится документация * `--regions` - Фильтр регионов, для которых строится документация diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java index 2df3273..ec1ad8f 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java @@ -31,17 +31,18 @@ @Slf4j public class BslContext { + private static final Set VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH = Set.of( + BSLParser.LINE_COMMENT, + BSLParser.WHITE_SPACE, + BSLParser.AMPERSAND + ); @Getter private static BslContext current; - @Getter Configuration configuration; - @Getter Filter filter; - List modules = Collections.emptyList(); - Set topObjectsType = Set.of( MDOType.COMMON_MODULE, MDOType.ENUM, @@ -53,18 +54,50 @@ public class BslContext { MDOType.INFORMATION_REGISTER ); - private static final Set VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH = Set.of( - BSLParser.LINE_COMMENT, - BSLParser.WHITE_SPACE, - BSLParser.AMPERSAND - ); - public BslContext(Path path, Filter filter) { this.filter = filter; configuration = Configuration.create(path); current = this; } + public static List getComments(List tokens, Token token) { + List comments = new ArrayList<>(); + fillCommentsCollection(tokens, token, comments); + return comments; + } + + private static void fillCommentsCollection(List tokens, Token currentToken, List lines) { + + int index = currentToken.getTokenIndex(); + + if (index == 0) { + return; + } + + var previousToken = tokens.get(index - 1); + + if (abortSearchComments(previousToken, currentToken)) { + return; + } + + fillCommentsCollection(tokens, previousToken, lines); + int type = previousToken.getType(); + if (type == BSLParser.LINE_COMMENT) { + lines.add(previousToken); + } + } + + private static boolean abortSearchComments(Token previousToken, Token currentToken) { + int type = previousToken.getType(); + return !VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH.contains(type) || isBlankLine(previousToken, currentToken); + } + + private static boolean isBlankLine(Token previousToken, Token currentToken) { + return previousToken.getType() == BSLParser.WHITE_SPACE + && (previousToken.getTokenIndex() == 0 + || (previousToken.getLine() + 1) != currentToken.getLine()); + } + public Stream getModules() { return configuration.getOrderedTopMDObjects().get(MDOType.COMMON_MODULE).stream() .map(MDCommonModule.class::cast) @@ -264,44 +297,6 @@ private boolean regionFilter(MethodSymbol m) { return false; } - public static List getComments(List tokens, Token token) { - List comments = new ArrayList<>(); - fillCommentsCollection(tokens, token, comments); - return comments; - } - - private static void fillCommentsCollection(List tokens, Token currentToken, List lines) { - - int index = currentToken.getTokenIndex(); - - if (index == 0) { - return; - } - - var previousToken = tokens.get(index - 1); - - if (abortSearchComments(previousToken, currentToken)) { - return; - } - - fillCommentsCollection(tokens, previousToken, lines); - int type = previousToken.getType(); - if (type == BSLParser.LINE_COMMENT) { - lines.add(previousToken); - } - } - - private static boolean abortSearchComments(Token previousToken, Token currentToken) { - int type = previousToken.getType(); - return !VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH.contains(type) || isBlankLine(previousToken, currentToken); - } - - private static boolean isBlankLine(Token previousToken, Token currentToken) { - return previousToken.getType() == BSLParser.WHITE_SPACE - && (previousToken.getTokenIndex() == 0 - || (previousToken.getLine() + 1) != currentToken.getLine()); - } - public MethodInfo getMethodInfo(String link) { if (Strings.isNullOrEmpty(link)) { return null; diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java index defbdce..5e433fa 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java @@ -25,10 +25,10 @@ public class MethodSymbol { Optional fullDescription; List parameters; + Range range; @Setter @NonFinal RegionSymbol region; - Range range; public String getDescription() { return fullDescription.map(MethodDescription::getPurposeDescription).orElse(""); diff --git a/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java b/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java index ffb3e7e..06c990e 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java +++ b/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java @@ -39,11 +39,11 @@ public void copy() { .forEach(destinationModel.getPages()::add); } - public boolean contains(Path path){ + public boolean contains(Path path) { return destinationModel.getPages() .stream() .map(Page::getPath) - .anyMatch(it->it.equals(path)); + .anyMatch(it -> it.equals(path)); } private Page createDestinationPage(Page localPage, Path local, Path dest) { diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java index 79e02c1..e7717f7 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java @@ -9,7 +9,6 @@ import ru.alkoleft.bsl.doc.render.handlebars.RenderContext; import java.nio.file.Path; -import java.util.Collections; import java.util.List; @Slf4j diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java index b889861..5a3d709 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java @@ -8,8 +8,8 @@ import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.options.RenderOptions; -import ru.alkoleft.bsl.doc.render.handlebars.helpers.Links; import ru.alkoleft.bsl.doc.render.handlebars.helpers.Debugger; +import ru.alkoleft.bsl.doc.render.handlebars.helpers.Links; import ru.alkoleft.bsl.doc.render.handlebars.helpers.Shifter; import ru.alkoleft.bsl.doc.render.handlebars.helpers.SingleLine; diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/SingleLine.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/SingleLine.java index 9e5833e..0fea76e 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/SingleLine.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/SingleLine.java @@ -14,7 +14,7 @@ public Object apply(Object context, Options options) throws IOException { String content; if (options.tagType == TagType.SECTION) { content = options.fn().toString(); - }else{ + } else { content = context.toString(); } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/processor/AppendProcessor.java b/src/main/java/ru/alkoleft/bsl/doc/render/processor/AppendProcessor.java index 4a60f07..34f9439 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/processor/AppendProcessor.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/processor/AppendProcessor.java @@ -1,8 +1,5 @@ package ru.alkoleft.bsl.doc.render.processor; -import ru.alkoleft.bsl.doc.manual.ManualContent; -import ru.alkoleft.bsl.doc.render.Render; - import java.nio.file.Path; public class AppendProcessor extends OutputProcessor { diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Item.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Item.java index c71fd0d..9fb1d2f 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/Item.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/Item.java @@ -1,6 +1,5 @@ package ru.alkoleft.bsl.doc.structure; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java b/src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java index 780a2ff..e3f63bb 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java @@ -13,9 +13,9 @@ public interface StructureBuilder { @UtilityClass class Factory { public StructureBuilder builder(RenderOptions options) { - if(options.isSubsystemHierarchy()){ + if (options.isSubsystemHierarchy()) { return new SubsystemsStructureBuilder(); - }else { + } else { return new FlatStructureBuilder(); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/StructureVisitor.java b/src/main/java/ru/alkoleft/bsl/doc/structure/StructureVisitor.java index b8d7c3e..861ce98 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/StructureVisitor.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/StructureVisitor.java @@ -1,7 +1,5 @@ package ru.alkoleft.bsl.doc.structure; -import java.util.List; - public interface StructureVisitor { void visit(SubsystemItem item, int index); From 1b8ddf4e50eac44d3e04a9c0bd83446ca7327eeb Mon Sep 17 00:00:00 2001 From: alkoleft Date: Fri, 13 Oct 2023 02:07:35 +0300 Subject: [PATCH 14/27] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=D0=BE=20=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80?= =?UTF-8?q?=D0=BE=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Рефакторинг * Вычисление подчиненных страниц для подсистем с учетом ручных --- .../bsl/doc/commands/RenderCommand.java | 11 ++-- .../processor/MarkdownTitleCleaner.java | 12 ---- .../processor/MarkdownTitleProcessor.java | 33 ++++++++++ .../doc/content/processor/TitleCleaner.java | 15 ----- .../doc/content/processor/TitleProcessor.java | 27 ++++++++ .../bsl/doc/manual/ManualContent.java | 4 ++ .../alkoleft/bsl/doc/model/ContentModel.java | 21 ++++++ .../bsl/doc/model/ContentModelBuilder.java | 17 +---- .../java/ru/alkoleft/bsl/doc/model/Page.java | 11 ++++ .../ru/alkoleft/bsl/doc/model/PageType.java | 3 +- .../bsl/doc/options/OutputOptions.java | 8 +++ .../alkoleft/bsl/doc/render/BaseRender.java | 26 ++++++++ .../ru/alkoleft/bsl/doc/render/BslRender.java | 37 +++++++++++ .../alkoleft/bsl/doc/render/PathResolver.java | 44 +++++++++++++ .../ru/alkoleft/bsl/doc/render/Render.java | 54 --------------- .../bsl/doc/render/StructureRender.java | 65 ++++++++++++------- .../bsl/doc/render/contexts/BaseContext.java | 22 +++++++ .../doc/render/contexts/ContextFactory.java | 15 ++--- .../doc/render/contexts/ModuleContext.java | 19 ++++-- .../doc/render/contexts/SubsystemContext.java | 37 ++++++++--- .../doc/render/processor/MergeProcessor.java | 11 ++-- .../doc/render/processor/OutputProcessor.java | 6 +- .../bsl/doc/structure/SubsystemItem.java | 4 ++ .../resources/confluence-md/subsystem.hbs | 6 +- .../bsl/doc/commands/RenderCommandTest.java | 7 +- 25 files changed, 348 insertions(+), 167 deletions(-) delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleProcessor.java delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleCleaner.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleProcessor.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/BaseRender.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/BslRender.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/PathResolver.java delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/Render.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/contexts/BaseContext.java diff --git a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java index 097c4e0..e92b9e6 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java +++ b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java @@ -8,11 +8,12 @@ import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.bsl.Filter; import ru.alkoleft.bsl.doc.bsl.symbols.RegionSymbol; +import ru.alkoleft.bsl.doc.content.processor.TitleProcessor; import ru.alkoleft.bsl.doc.manual.ManualContent; import ru.alkoleft.bsl.doc.options.MergeStrategy; import ru.alkoleft.bsl.doc.options.OutputFormat; import ru.alkoleft.bsl.doc.options.RenderOptions; -import ru.alkoleft.bsl.doc.render.Render; +import ru.alkoleft.bsl.doc.render.BaseRender; import ru.alkoleft.bsl.doc.render.StructureRender; import ru.alkoleft.bsl.doc.render.handlebars.RenderContext; import ru.alkoleft.bsl.doc.render.processor.OutputProcessor; @@ -61,6 +62,7 @@ public void run() { log.debug("Merge manual: " + mergeStrategy); var bslContext = new BslContext(sources, filter); + TitleProcessor.Factory.create(options.getOutputFormat()); var manual = new ManualContent(manualDocumentation, destination); manual.buildModel(options.getOutputFormat()); @@ -69,9 +71,10 @@ public void run() { var structure = StructureBuilder.Factory.build(bslContext, options); StructureBuilder.Factory.print(structure); - var renderContext = RenderContext.Factory.create(options); var processor = OutputProcessor.Factory.create(mergeStrategy); - processor.init(new Render(renderContext), options.getOutputFormat(), manual); - new StructureRender(processor).render(structure, destination); + BaseRender.setContext(RenderContext.Factory.create(options)); + processor.init(options.getOutputFormat(), manual); + var render = new StructureRender(processor, manual.getContentModel()); + render.render(structure, destination); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java b/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java deleted file mode 100644 index 739ceda..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleCleaner.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.alkoleft.bsl.doc.content.processor; - -import java.util.stream.Collectors; - -public class MarkdownTitleCleaner implements TitleCleaner { - @Override - public String cleanTitle(String content) { - return content.lines() - .filter(it -> !it.startsWith("# ")) - .collect(Collectors.joining("\n")); - } -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleProcessor.java b/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleProcessor.java new file mode 100644 index 0000000..b4ae405 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/content/processor/MarkdownTitleProcessor.java @@ -0,0 +1,33 @@ +package ru.alkoleft.bsl.doc.content.processor; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Collectors; + +public class MarkdownTitleProcessor implements TitleProcessor { + @Override + public String cleanTitle(String content) { + return content.lines() + .filter(it -> !it.startsWith("# ")) + .collect(Collectors.joining("\n")); + } + + @Override + public String getTitle(String content) { + return null; + } + + @Override + public String getTitle(Path path) { + try (var lines = Files.lines(path)) { + return lines + .filter(it -> it.startsWith("# ")) + .findFirst() + .map(it -> it.substring(2).trim()).orElse(null); + } catch (IOException e) { + // nothing + } + return ""; + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleCleaner.java b/src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleCleaner.java deleted file mode 100644 index 7a7de2e..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleCleaner.java +++ /dev/null @@ -1,15 +0,0 @@ -package ru.alkoleft.bsl.doc.content.processor; - -import lombok.experimental.UtilityClass; -import ru.alkoleft.bsl.doc.options.OutputFormat; - -public interface TitleCleaner { - String cleanTitle(String content); - - @UtilityClass - class Factory { - public TitleCleaner create(OutputFormat format) { - return new MarkdownTitleCleaner(); - } - } -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleProcessor.java b/src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleProcessor.java new file mode 100644 index 0000000..0d16aff --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/content/processor/TitleProcessor.java @@ -0,0 +1,27 @@ +package ru.alkoleft.bsl.doc.content.processor; + +import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.options.OutputFormat; + +import java.nio.file.Path; + +public interface TitleProcessor { + static TitleProcessor getInstance() { + return Factory.instance; + } + + String cleanTitle(String content); + + String getTitle(String content); + + String getTitle(Path path); + + @UtilityClass + class Factory { + TitleProcessor instance; + + public TitleProcessor create(OutputFormat format) { + return instance = new MarkdownTitleProcessor(); + } + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java b/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java index 06c990e..c0b5ef1 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java +++ b/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java @@ -46,6 +46,10 @@ public boolean contains(Path path) { .anyMatch(it -> it.equals(path)); } + public ContentModel getContentModel() { + return destinationModel; + } + private Page createDestinationPage(Page localPage, Path local, Path dest) { var destPath = dest.resolve(local.relativize(localPage.getPath())); return new Page(destPath, localPage.getTitle(), localPage.getType()); diff --git a/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java index e0c50d7..24717ab 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java +++ b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java @@ -2,10 +2,31 @@ import lombok.Value; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @Value public class ContentModel { List pages = new ArrayList<>(); + + public void append(Path path, PageType type) { + pages.add(new Page(path, null, type)); + } + + public List getChildrenPages(Path path) { + return pages.stream() + .filter(it -> isChild(it, path)) + .collect(Collectors.toList()); + } + + boolean isChild(Page page, Path path) { + var pagePath = page.getPath(); + if (pagePath.getFileName().toString().startsWith("index.")) { + return pagePath.getParent().getParent().equals(path); + } else { + return pagePath.getParent().equals(path); + } + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/model/ContentModelBuilder.java b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModelBuilder.java index 04aeefc..ab490cc 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/model/ContentModelBuilder.java +++ b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModelBuilder.java @@ -1,11 +1,10 @@ package ru.alkoleft.bsl.doc.model; -import lombok.SneakyThrows; import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.content.processor.TitleProcessor; import ru.alkoleft.bsl.doc.indexer.FileIndexer; import ru.alkoleft.bsl.doc.options.OutputFormat; -import java.nio.file.Files; import java.nio.file.Path; @UtilityClass @@ -14,21 +13,11 @@ public ContentModel build(Path location, OutputFormat format) { var model = new ContentModel(); try (var files = new FileIndexer(format.getExtension()).pagePaths(location)) { - files.map(it -> new Page(it, it.getFileName().getName(0).toString(), PageType.UNKNOWN)) - .peek(it -> it.setTitle(extractTitle(it.getPath()))) + files.map(it -> new Page(it, it.getFileName().getName(0).toString(), PageType.MANUAL)) + .peek(it -> it.setTitle(TitleProcessor.getInstance().getTitle(it.getPath()))) .forEach(model.getPages()::add); } return model; } - - @SneakyThrows - private String extractTitle(Path path) { - try (var lines = Files.lines(path)) { - return lines - .filter(it -> it.startsWith("# ")) - .findFirst() - .map(it -> it.substring(2).trim()).orElse(null); - } - } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/model/Page.java b/src/main/java/ru/alkoleft/bsl/doc/model/Page.java index 8a0d4eb..b0cd1a2 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/model/Page.java +++ b/src/main/java/ru/alkoleft/bsl/doc/model/Page.java @@ -2,6 +2,7 @@ import lombok.AllArgsConstructor; import lombok.Data; +import ru.alkoleft.bsl.doc.content.processor.TitleProcessor; import java.nio.file.Path; @@ -11,4 +12,14 @@ public class Page { private Path path; private String title; private PageType type; + + public String getTitle() { + if (title != null) { + return title; + } else if (path == null) { + return null; + } + + return title = TitleProcessor.getInstance().getTitle(path); + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/model/PageType.java b/src/main/java/ru/alkoleft/bsl/doc/model/PageType.java index d4c2f88..0e55542 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/model/PageType.java +++ b/src/main/java/ru/alkoleft/bsl/doc/model/PageType.java @@ -3,5 +3,6 @@ public enum PageType { UNKNOWN, SUBSYSTEM, - MODULE + MODULE, + MANUAL } diff --git a/src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java b/src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java new file mode 100644 index 0000000..0395900 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java @@ -0,0 +1,8 @@ +package ru.alkoleft.bsl.doc.options; + +import java.nio.file.Path; + +public class OutputOptions { + OutputFormat format; + Path destination; +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/BaseRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/BaseRender.java new file mode 100644 index 0000000..04e2c81 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/BaseRender.java @@ -0,0 +1,26 @@ +package ru.alkoleft.bsl.doc.render; + +import com.github.jknack.handlebars.Context; +import lombok.Getter; +import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.render.handlebars.RenderContext; + +import java.nio.file.Path; + +@UtilityClass +public class BaseRender { + @Getter + RenderContext renderContext; + + public void setContext(RenderContext renderContext) { + BaseRender.renderContext = renderContext; + } + + public void renderToFile(String templateName, Context context, Path output) { + renderContext.renderToFile(templateName, context, output); + } + + public String render(String templateName, Context context) { + return renderContext.render(templateName, context); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/BslRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/BslRender.java new file mode 100644 index 0000000..3db87fc --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/BslRender.java @@ -0,0 +1,37 @@ +package ru.alkoleft.bsl.doc.render; + +import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import lombok.SneakyThrows; +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; +import ru.alkoleft.bsl.doc.bsl.ModuleInfo; +import ru.alkoleft.bsl.doc.render.contexts.ContextFactory; +import ru.alkoleft.bsl.doc.render.contexts.ModuleContext; +import ru.alkoleft.bsl.doc.render.contexts.SubsystemContext; + +@Slf4j +@UtilityClass +public class BslRender { + + @SneakyThrows + public String renderModule(ModuleInfo module, int index) { + return renderModule(ContextFactory.create(module, index)); + } + + @SneakyThrows + public String renderModule(ModuleContext module) { + log.debug("Render module '{}'", module.getName()); + return BaseRender.render("module", ContextFactory.createContext(module)); + } + + @SneakyThrows + public String renderSubsystem(MDSubsystem subsystem, int level) { + return renderSubsystem(ContextFactory.create(subsystem, 0, level)); + } + + @SneakyThrows + public String renderSubsystem(SubsystemContext subsystem) { + log.debug("Render subsystem '{}'", subsystem.getName()); + return BaseRender.render("subsystem", ContextFactory.createContext(subsystem)); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/PathResolver.java b/src/main/java/ru/alkoleft/bsl/doc/render/PathResolver.java new file mode 100644 index 0000000..6161cca --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/PathResolver.java @@ -0,0 +1,44 @@ +package ru.alkoleft.bsl.doc.render; + +import com.github._1c_syntax.utils.Lazy; +import lombok.AllArgsConstructor; +import ru.alkoleft.bsl.doc.options.OutputFormat; + +import java.nio.file.Path; +import java.util.Stack; + +@AllArgsConstructor +public class PathResolver { + + private final Path destination; + private final OutputFormat format; + private final Stack paths = new Stack<>(); + private final Lazy currentPath = new Lazy<>(this::computeCurrentPath); + + public void entrance(String path) { + paths.push(path); + currentPath.clear(); + } + + public void exit() { + paths.pop(); + currentPath.clear(); + } + + public Path getCurrentPath() { + return currentPath.getOrCompute(); + } + + public Path getFilePath(String name) { + return getCurrentPath().resolve(name + "." + format.getExtension()); + } + + private Path computeCurrentPath() { + Path result = destination; + var iterator = paths.elements().asIterator(); + while (iterator.hasNext()) { + result = result.resolve(iterator.next()); + } + return result; + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java b/src/main/java/ru/alkoleft/bsl/doc/render/Render.java deleted file mode 100644 index e7717f7..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/render/Render.java +++ /dev/null @@ -1,54 +0,0 @@ -package ru.alkoleft.bsl.doc.render; - -import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; -import lombok.Getter; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import ru.alkoleft.bsl.doc.bsl.ModuleInfo; -import ru.alkoleft.bsl.doc.render.contexts.ContextFactory; -import ru.alkoleft.bsl.doc.render.handlebars.RenderContext; - -import java.nio.file.Path; -import java.util.List; - -@Slf4j -public class Render { - @Getter - RenderContext renderContext; - - public Render(RenderContext renderContext) { - this.renderContext = renderContext; - } - - @SneakyThrows - public void render(ModuleInfo module, Path outputPath, int index) { - log.debug("Render module '{}' to '{}'", module.getOwner().getName(), outputPath); - - var context = ContextFactory.create(module, index); - renderContext.renderToFile("module", context, outputPath); - } - - @SneakyThrows - public String render(ModuleInfo module, int index) { - log.debug("Render module '{}'", module.getOwner().getName()); - - var context = ContextFactory.create(module, index); - return renderContext.render("module", context); - } - - @SneakyThrows - public void render(MDSubsystem subsystem, Path path, int level, List childrenItems) { - log.debug("Render subsystem '{}' to '{}'", subsystem.getName(), path); - - var context = ContextFactory.create(subsystem, childrenItems, 0, level); - renderContext.renderToFile("subsystem", context, path); - } - - @SneakyThrows - public String render(MDSubsystem subsystem, int level, List childrenItems) { - log.debug("Render subsystem '{}'", subsystem.getName()); - - var context = ContextFactory.create(subsystem, childrenItems, 0, level); - return renderContext.render("subsystem", context); - } -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java index d32c31f..a1410d6 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java @@ -1,8 +1,10 @@ package ru.alkoleft.bsl.doc.render; -import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; import lombok.SneakyThrows; import ru.alkoleft.bsl.doc.bsl.BslContext; +import ru.alkoleft.bsl.doc.model.ContentModel; +import ru.alkoleft.bsl.doc.model.PageType; +import ru.alkoleft.bsl.doc.render.contexts.ContextFactory; import ru.alkoleft.bsl.doc.render.processor.OutputProcessor; import ru.alkoleft.bsl.doc.structure.Item; import ru.alkoleft.bsl.doc.structure.MDObjectItem; @@ -15,26 +17,26 @@ import java.util.ArrayList; import java.util.List; import java.util.Stack; -import java.util.stream.Collectors; public class StructureRender implements StructureVisitor { private final OutputProcessor outputProcessor; - private final Stack paths = new Stack<>(); private final Stack> children = new Stack<>(); + private final ContentModel contentModel; private boolean withRoot = false; private int subsystemLevel = 0; + private PathResolver pathResolver; - public StructureRender(OutputProcessor outputProcessor) { + public StructureRender(OutputProcessor outputProcessor, ContentModel contentModel) { this.outputProcessor = outputProcessor; + this.contentModel = contentModel; } public void render(List structure, Path destination) { - paths.clear(); + pathResolver = new PathResolver(destination, outputProcessor.getFormat()); children.clear(); subsystemLevel = 0; withRoot = structure.size() > 1; - paths.push(destination); children.push(new ArrayList<>()); for (int i = 0; i < structure.size(); i++) { structure.get(i).accept(this, i); @@ -46,28 +48,27 @@ public void visit(SubsystemItem item, int index) { var isRoot = subsystemLevel == 0; subsystemLevel++; children.push(new ArrayList<>()); - Path path; if (!withRoot && isRoot) { - path = paths.peek(); item.accentChildren(this); + renderSubsystemPage(item); } else { - path = paths.peek().resolve(item.getName()); - paths.push(path); + pathResolver.entrance(item.getName()); item.accentChildren(this); - paths.pop(); + renderSubsystemPage(item); + pathResolver.exit(); } subsystemLevel--; - var childrenItems = children.pop().stream() - .map(it -> it.toString().substring(path.toString().length() + 1)) - .collect(Collectors.toList()); - if (!childrenItems.isEmpty()) { - var itemPath = path.resolve("index.md"); - if (outputProcessor.needRender(itemPath)) { - var content = outputProcessor.getRender().render((MDSubsystem) item.getObject(), subsystemLevel, childrenItems); - outputProcessor.save(itemPath, content); - } - children.peek().add(itemPath); - } +// var childrenItems = children.pop().stream() +// .map(it -> it.toString().substring(path.toString().length() + 1)) +// .collect(Collectors.toList()); +// if (!childrenItems.isEmpty()) { +// var itemPath = path.resolve("index.md"); +// if (outputProcessor.needRender(itemPath)) { +// var content = outputProcessor.getRender().render((MDSubsystem) item.getObject(), subsystemLevel, childrenItems); +// outputProcessor.save(itemPath, content); +// } +// children.peek().add(itemPath); +// } } @Override @@ -77,14 +78,17 @@ public void visit(ModuleItem item, int index) { if (moduleContext.isEmpty()) { return; } - var path = paths.peek().resolve(item.getModule().getOwner().getName() + ".md"); + var path = pathResolver.getFilePath(item.getModule().getOwner().getName()); if (!Files.exists(path.getParent())) { Files.createDirectories(path.getParent()); } children.peek().add(path); if (outputProcessor.needRender(path)) { - var content = outputProcessor.getRender().render(moduleContext, index); + var context = ContextFactory.create(moduleContext, index); + + var content = BslRender.renderModule(moduleContext, index); outputProcessor.save(path, content); + contentModel.append(path, PageType.MODULE); } } @@ -92,4 +96,17 @@ public void visit(ModuleItem item, int index) { public void visit(MDObjectItem item, int index) { item.accentChildren(this); } + + private void renderSubsystemPage(SubsystemItem item) { + var path = pathResolver.getFilePath("index"); + + if (outputProcessor.needRender(path)) { + var context = ContextFactory.create(item.getSubsystem(), 0, subsystemLevel); + context.setContentModel(contentModel); + context.setOutputPath(path.getParent()); + var content = BslRender.renderSubsystem(context); + outputProcessor.save(path, content); + contentModel.append(path, PageType.SUBSYSTEM); + } + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/BaseContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/BaseContext.java new file mode 100644 index 0000000..c6ed9ef --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/BaseContext.java @@ -0,0 +1,22 @@ +package ru.alkoleft.bsl.doc.render.contexts; + + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +import java.nio.file.Path; + + +@Getter +@AllArgsConstructor +@EqualsAndHashCode +public class BaseContext { + private final int index; + private final String name; + private final String present; + private final String description; + @Setter + private Path outputPath; +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java index 23d5dab..a53efd6 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java @@ -12,13 +12,11 @@ import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.bsl.ModuleInfo; -import java.util.List; - @UtilityClass public class ContextFactory { - public Context create(ModuleInfo module, int index) { - var context = ModuleContext.builder() + public ModuleContext create(ModuleInfo module, int index) { + return ModuleContext.builder() .index(index) .name(module.getOwner().getName()) .present(getPresent(module.getOwner())) @@ -28,19 +26,16 @@ public Context create(ModuleInfo module, int index) { .methods(module.getMethods()) .description(module.getDescription()) .build(); - return createContext(context); } - public Context create(MDSubsystem subsystem, List childrenItems, int index, int level) { - var context = SubsystemContext.builder() + public SubsystemContext create(MDSubsystem subsystem, int index, int level) { + return SubsystemContext.builder() .index(index) .name(subsystem.getName()) .present(getPresent(subsystem)) .description(subsystem.getComment()) - .children(childrenItems) .level(level) .build(); - return createContext(context); } private String getPresent(AbstractMDObjectBase object) { @@ -51,7 +46,7 @@ private String getPresent(AbstractMDObjectBase object) { } } - private Context createContext(Object obj) { + public Context createContext(Object obj) { return Context.newBuilder(obj) .resolver( MapValueResolver.INSTANCE, diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java index e0a45bc..d978482 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java @@ -1,20 +1,27 @@ package ru.alkoleft.bsl.doc.render.contexts; import lombok.Builder; +import lombok.EqualsAndHashCode; import lombok.Value; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; +import java.nio.file.Path; import java.util.List; -@Builder +@EqualsAndHashCode(callSuper = true) @Value -public class ModuleContext { - int index; - String name; - String present; - String description; +public class ModuleContext extends BaseContext { boolean isCommonModule; String ownerType; String moduleType; List methods; + + @Builder + public ModuleContext(Path outputPath, int index, String name, String present, String description, boolean isCommonModule, String ownerType, String moduleType, List methods) { + super(outputPath, index, name, present, description); + this.isCommonModule = isCommonModule; + this.ownerType = ownerType; + this.moduleType = moduleType; + this.methods = methods; + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java index e867862..8c666f5 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java @@ -1,17 +1,34 @@ package ru.alkoleft.bsl.doc.render.contexts; import lombok.Builder; -import lombok.Value; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import ru.alkoleft.bsl.doc.model.ContentModel; +import ru.alkoleft.bsl.doc.model.Page; +import java.nio.file.Path; +import java.util.Collections; import java.util.List; -@Builder -@Value -public class SubsystemContext { - int index; - String name; - String present; - String description; - List children; - int level; +@EqualsAndHashCode(callSuper = true) +@Getter +public class SubsystemContext extends BaseContext { + private final int level; + @Setter + ContentModel contentModel; + + @Builder + public SubsystemContext(Path outputPath, int index, String name, String present, String description, int level) { + super(outputPath, index, name, present, description); + this.level = level; + } + + public List getChildren() { + if (contentModel != null) { + return contentModel.getChildrenPages(getOutputPath()); + } else { + return Collections.emptyList(); + } + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/processor/MergeProcessor.java b/src/main/java/ru/alkoleft/bsl/doc/render/processor/MergeProcessor.java index 681a0d6..7ab5358 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/processor/MergeProcessor.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/processor/MergeProcessor.java @@ -2,10 +2,9 @@ import com.github.jknack.handlebars.internal.Files; import lombok.SneakyThrows; -import ru.alkoleft.bsl.doc.content.processor.TitleCleaner; +import ru.alkoleft.bsl.doc.content.processor.TitleProcessor; import ru.alkoleft.bsl.doc.manual.ManualContent; import ru.alkoleft.bsl.doc.options.OutputFormat; -import ru.alkoleft.bsl.doc.render.Render; import java.nio.charset.StandardCharsets; import java.nio.file.Path; @@ -13,12 +12,12 @@ public class MergeProcessor extends OutputProcessor { private static final Pattern replacePattern = Pattern.compile("^.*generated_content.*$", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); - TitleCleaner titleCleaner; + TitleProcessor titleCleaner; @Override - public void init(Render render, OutputFormat format, ManualContent manualContent) { - super.init(render, format, manualContent); - titleCleaner = TitleCleaner.Factory.create(format); + public void init(OutputFormat format, ManualContent manualContent) { + super.init(format, manualContent); + titleCleaner = TitleProcessor.getInstance(); } @SneakyThrows diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/processor/OutputProcessor.java b/src/main/java/ru/alkoleft/bsl/doc/render/processor/OutputProcessor.java index 16bf0d7..0e10905 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/processor/OutputProcessor.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/processor/OutputProcessor.java @@ -6,15 +6,12 @@ import ru.alkoleft.bsl.doc.manual.ManualContent; import ru.alkoleft.bsl.doc.options.MergeStrategy; import ru.alkoleft.bsl.doc.options.OutputFormat; -import ru.alkoleft.bsl.doc.render.Render; import java.nio.file.Files; import java.nio.file.Path; @Getter public class OutputProcessor { - @Setter - protected Render render; @Setter protected OutputFormat format; @Setter @@ -29,8 +26,7 @@ public void save(Path itemPath, String content) { Files.writeString(itemPath, content); } - public void init(Render render, OutputFormat format, ManualContent manualContent) { - this.render = render; + public void init(OutputFormat format, ManualContent manualContent) { this.format = format; this.manualContent = manualContent; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java index c206deb..74b750c 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java @@ -11,4 +11,8 @@ public SubsystemItem(MDSubsystem subsystem) { public void accept(StructureVisitor visitor, int index) { visitor.visit(this, index); } + + public MDSubsystem getSubsystem() { + return (MDSubsystem) getObject(); + } } diff --git a/src/main/resources/confluence-md/subsystem.hbs b/src/main/resources/confluence-md/subsystem.hbs index 9dec684..e9dd78b 100644 --- a/src/main/resources/confluence-md/subsystem.hbs +++ b/src/main/resources/confluence-md/subsystem.hbs @@ -1,8 +1,8 @@ # {{#great level 1}}Подсистема {{/great}}{{present}} - +{{#if description}} {{description}} - +{{/if}} Содержимое: {{#each children as | item|}} -* [{{item}}]({{item}}) +* [{{item.title}}]({{item.path}}) {{/each}} \ No newline at end of file diff --git a/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java index b672337..aa4da15 100644 --- a/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java +++ b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java @@ -6,6 +6,7 @@ import ru.alkoleft.bsl.doc.options.MergeStrategy; import ru.alkoleft.bsl.doc.options.OutputFormat; +import java.net.URISyntaxException; import java.nio.file.Path; import java.util.List; @@ -14,14 +15,14 @@ class RenderCommandTest { RenderCommand cmd; @BeforeEach - void setUp() { + void setUp() throws URISyntaxException { cmd = new RenderCommand(); - cmd.sources = Path.of("/home/common/develop/repos/open-source/bsldoc/src/test/resources/configuration"); + cmd.sources = Path.of(getClass().getClassLoader().getResource("configuration").toURI()); cmd.destination = Path.of("/tmp/bsl-doc-fixture"); cmd.format = OutputFormat.ConfluenceMarkdown; cmd.onlySubsystems = List.of("ППИ"); cmd.regions = List.of(RegionSymbol.PUBLIC_REGION_RU); - cmd.manualDocumentation = Path.of("/home/common/develop/repos/open-source/bsldoc/src/test/resources/docs"); + cmd.manualDocumentation = Path.of(getClass().getClassLoader().getResource("docs").toURI()); cmd.mergeStrategy = MergeStrategy.MERGE; } From bd92d1d798ead4c747a20c597634c64b78b90a04 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Tue, 17 Oct 2023 23:48:49 +0300 Subject: [PATCH 15/27] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/alkoleft/bsl/doc/AutodocManager.java | 75 +++++++++++++++++++ .../ru/alkoleft/bsl/doc/bsl/BslContext.java | 12 +-- .../bsl/doc/commands/RenderCommand.java | 64 ++++++++-------- .../bsl/doc/manual/ManualContent.java | 3 + ...Strategy.java => ManualMergeStrategy.java} | 2 +- .../bsl/doc/options/OutputOptions.java | 8 +- .../bsl/doc/options/RenderOptions.java | 11 --- .../ru/alkoleft/bsl/doc/render/BslRender.java | 6 -- .../bsl/doc/render/StructureRender.java | 33 +++----- .../doc/render/contexts/ContextFactory.java | 1 + .../doc/render/contexts/ModuleContext.java | 4 +- .../doc/render/contexts/SubsystemContext.java | 22 +++++- .../doc/render/handlebars/RenderContext.java | 6 +- .../render/handlebars/helpers/MdoPresent.java | 29 +++++++ .../AppendStrategy.java} | 4 +- .../MergeStrategy.java} | 4 +- .../OutputStrategy.java} | 43 ++++++----- .../render/{processor => output}/Writer.java | 2 +- .../alkoleft/bsl/doc/structure/Factory.java | 14 ++-- .../bsl/doc/structure/StructureBuilder.java | 55 ++++++-------- .../structure/SubsystemsStructureBuilder.java | 3 +- .../resources/confluence-md/subsystem.hbs | 8 +- .../bsl/doc/commands/RenderCommandTest.java | 35 +++++---- .../ManagerModule.bsl" | 13 ++++ ...\276\321\207\320\275\320\270\320\2721.mdo" | 33 ++++++++ .../ObjectModule.bsl" | 13 ++++ ...\276\321\207\320\275\320\270\320\2722.mdo" | 33 ++++++++ .../src/Configuration/Configuration.mdo | 5 ++ ...1\202\320\260\320\275\321\202\320\260.mdo" | 23 ++++++ ...\202\320\260\320\275\321\202\320\2601.mdo" | 23 ++++++ ...\202\320\260\320\275\321\202\320\2602.mdo" | 23 ++++++ .../CommandInterface.cmi" | 0 .../CommandInterface.cmi" | 0 ...0\274\320\265\320\275\321\202\321\213.mdo" | 11 +++ .../CommandInterface.cmi" | 0 ...1\207\320\275\320\270\320\272\320\270.mdo" | 14 ++++ ...0\260\320\264\320\275\321\213\320\265.mdo" | 15 ++++ ...0\262\320\260\320\275\320\270\321\217.mdo" | 12 --- ...0\275\320\272\321\206\320\270\320\270.mdo" | 12 --- .../CommandInterface.cmi" | 2 + ...0\270\321\201\320\275\321\213\320\265.mdo" | 6 +- .../\320\237\320\237\320\230.mdo" | 3 +- .../index.md" | 0 43 files changed, 479 insertions(+), 206 deletions(-) create mode 100644 src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java rename src/main/java/ru/alkoleft/bsl/doc/options/{MergeStrategy.java => ManualMergeStrategy.java} (69%) delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/options/RenderOptions.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/MdoPresent.java rename src/main/java/ru/alkoleft/bsl/doc/render/{processor/AppendProcessor.java => output/AppendStrategy.java} (57%) rename src/main/java/ru/alkoleft/bsl/doc/render/{processor/MergeProcessor.java => output/MergeStrategy.java} (91%) rename src/main/java/ru/alkoleft/bsl/doc/render/{processor/OutputProcessor.java => output/OutputStrategy.java} (54%) rename src/main/java/ru/alkoleft/bsl/doc/render/{processor => output}/Writer.java (79%) create mode 100644 "src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721/ManagerModule.bsl" create mode 100644 "src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721.mdo" create mode 100644 "src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722/ObjectModule.bsl" create mode 100644 "src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722.mdo" create mode 100644 "src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\260/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\260.mdo" create mode 100644 "src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2601/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2601.mdo" create mode 100644 "src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2602/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2602.mdo" rename "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/CommandInterface.cmi" => "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/CommandInterface.cmi" (100%) rename "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/CommandInterface.cmi" => "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213/CommandInterface.cmi" (100%) create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213/\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213.mdo" rename "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/CommandInterface.cmi" => "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\272\320\270/CommandInterface.cmi" (100%) create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\272\320\270/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\272\320\270.mdo" create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265.mdo" delete mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" delete mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" create mode 100644 "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/CommandInterface.cmi" rename "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" => "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265.mdo" (72%) rename "src/test/resources/docs/\320\240\320\260\320\267\320\264\320\265\320\2731/index.md" => "src/test/resources/docs/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/index.md" (100%) diff --git a/src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java b/src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java new file mode 100644 index 0000000..4498987 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java @@ -0,0 +1,75 @@ +package ru.alkoleft.bsl.doc; + +import lombok.Builder; +import lombok.SneakyThrows; +import org.apache.commons.io.file.PathUtils; +import ru.alkoleft.bsl.doc.bsl.BslContext; +import ru.alkoleft.bsl.doc.bsl.Filter; +import ru.alkoleft.bsl.doc.content.processor.TitleProcessor; +import ru.alkoleft.bsl.doc.manual.ManualContent; +import ru.alkoleft.bsl.doc.options.ManualMergeStrategy; +import ru.alkoleft.bsl.doc.options.OutputOptions; +import ru.alkoleft.bsl.doc.render.BaseRender; +import ru.alkoleft.bsl.doc.render.StructureRender; +import ru.alkoleft.bsl.doc.render.handlebars.RenderContext; +import ru.alkoleft.bsl.doc.render.output.OutputStrategy; +import ru.alkoleft.bsl.doc.structure.StructureBuilder; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class AutodocManager { + + private final OutputOptions outputOptions; + private final Path destination; + private final ManualMergeStrategy manualMergeStrategy; + private final ManualContent manualContent; + private final BslContext bslContext; + + @Builder + public AutodocManager(Filter filter, OutputOptions outputOptions, Path sources, Path destination, Path manualDocumentation, ManualMergeStrategy manualMergeStrategy) { + this.destination = destination; + this.outputOptions = outputOptions; + this.manualMergeStrategy = manualMergeStrategy; + manualContent = new ManualContent(manualDocumentation, destination); + bslContext = new BslContext(sources, filter); + + TitleProcessor.Factory.create(outputOptions.getOutputFormat()); + } + + public void loadData() { + manualContent.buildModel(outputOptions.getOutputFormat()); + } + + public void generateDocumentation() { + manualContent.copy(); + + var structure = StructureBuilder.builder(outputOptions).build(bslContext); + StructureBuilder.print(structure); + + var processor = OutputStrategy.create(manualMergeStrategy); + processor.init(outputOptions.getOutputFormat(), manualContent); + var render = new StructureRender(processor, manualContent.getContentModel()); + + BaseRender.setContext(RenderContext.Factory.create(outputOptions)); + render.render(structure, destination); + } + + @SneakyThrows + public void clearOutput() { + if (Files.exists(destination)) { + Files.walk(destination) + .filter(it -> it != destination) + .forEach(this::deletePath); + } + } + + private void deletePath(Path path) { + try { + PathUtils.delete(path); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java index ec1ad8f..d5b82e8 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java @@ -43,16 +43,8 @@ public class BslContext { @Getter Filter filter; List modules = Collections.emptyList(); - Set topObjectsType = Set.of( - MDOType.COMMON_MODULE, - MDOType.ENUM, - MDOType.CATALOG, - MDOType.DOCUMENT, - MDOType.ACCOUNTING_REGISTER, - MDOType.ACCUMULATION_REGISTER, - MDOType.CALCULATION_REGISTER, - MDOType.INFORMATION_REGISTER - ); + + Set topObjectsType = Set.copyOf(MDOType.valuesWithoutChildren()); public BslContext(Path path, Filter filter) { this.filter = filter; diff --git a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java index e92b9e6..56c51f1 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java +++ b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java @@ -1,44 +1,43 @@ package ru.alkoleft.bsl.doc.commands; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import picocli.CommandLine.Command; import picocli.CommandLine.Option; import picocli.CommandLine.Parameters; -import ru.alkoleft.bsl.doc.bsl.BslContext; +import ru.alkoleft.bsl.doc.AutodocManager; import ru.alkoleft.bsl.doc.bsl.Filter; import ru.alkoleft.bsl.doc.bsl.symbols.RegionSymbol; -import ru.alkoleft.bsl.doc.content.processor.TitleProcessor; -import ru.alkoleft.bsl.doc.manual.ManualContent; -import ru.alkoleft.bsl.doc.options.MergeStrategy; +import ru.alkoleft.bsl.doc.options.ManualMergeStrategy; import ru.alkoleft.bsl.doc.options.OutputFormat; -import ru.alkoleft.bsl.doc.options.RenderOptions; -import ru.alkoleft.bsl.doc.render.BaseRender; -import ru.alkoleft.bsl.doc.render.StructureRender; -import ru.alkoleft.bsl.doc.render.handlebars.RenderContext; -import ru.alkoleft.bsl.doc.render.processor.OutputProcessor; -import ru.alkoleft.bsl.doc.structure.StructureBuilder; +import ru.alkoleft.bsl.doc.options.OutputOptions; import java.nio.file.Path; import java.util.List; @Slf4j @Command(helpCommand = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor public class RenderCommand implements Runnable { @Parameters(description = "source") - Path sources; + private Path sources; @Parameters(description = "destination") - Path destination; + private Path destination; @Option(names = {"-f", "--format"}, defaultValue = "Markdown") - OutputFormat format; + private OutputFormat format; @Option(names = {"-s", "--only-subsystems"}) - List onlySubsystems; + private List onlySubsystems; @Option(names = {"-r", "--regions"}, split = " ", defaultValue = RegionSymbol.PUBLIC_REGION_RU + " " + RegionSymbol.PUBLIC_REGION_EN) - List regions; + private List regions; @Option(names = {"-m", "--manual-docs"}, description = "Path to manual documentations") - Path manualDocumentation; + private Path manualDocumentation; @Option(names = {"-ms", "--merge-strategy"}, description = "Merge strategy for manual and generated documentation", defaultValue = "NONE") - MergeStrategy mergeStrategy; + private ManualMergeStrategy manualMergeStrategy; @SneakyThrows @Override @@ -49,7 +48,7 @@ public void run() { regions.forEach(filterBuilder::region); onlySubsystems.forEach(filterBuilder::rootSubsystem); - var optionsBuilder = RenderOptions.builder() + var optionsBuilder = OutputOptions.builder() .outputFormat(format) .subsystemHierarchy(true); @@ -58,23 +57,22 @@ public void run() { log.debug("Filter: " + filter.toString()); log.debug("Options: " + options.toString()); + log.debug("Sources: " + sources); log.debug("Manual: " + manualDocumentation); - log.debug("Merge manual: " + mergeStrategy); + log.debug("Output: " + destination); + log.debug("Merge manual: " + manualMergeStrategy); - var bslContext = new BslContext(sources, filter); - TitleProcessor.Factory.create(options.getOutputFormat()); + var manager = AutodocManager.builder() + .filter(filter) + .outputOptions(options) + .manualDocumentation(manualDocumentation) + .mergeStrategy(manualMergeStrategy) + .destination(destination) + .sources(sources) + .build(); - var manual = new ManualContent(manualDocumentation, destination); - manual.buildModel(options.getOutputFormat()); - manual.copy(); - - var structure = StructureBuilder.Factory.build(bslContext, options); - StructureBuilder.Factory.print(structure); - - var processor = OutputProcessor.Factory.create(mergeStrategy); - BaseRender.setContext(RenderContext.Factory.create(options)); - processor.init(options.getOutputFormat(), manual); - var render = new StructureRender(processor, manual.getContentModel()); - render.render(structure, destination); + manager.loadData(); + manager.clearOutput(); + manager.generateDocumentation(); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java b/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java index c0b5ef1..9f661c8 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java +++ b/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java @@ -40,6 +40,9 @@ public void copy() { } public boolean contains(Path path) { + if (destinationModel == null) { + return false; + } return destinationModel.getPages() .stream() .map(Page::getPath) diff --git a/src/main/java/ru/alkoleft/bsl/doc/options/MergeStrategy.java b/src/main/java/ru/alkoleft/bsl/doc/options/ManualMergeStrategy.java similarity index 69% rename from src/main/java/ru/alkoleft/bsl/doc/options/MergeStrategy.java rename to src/main/java/ru/alkoleft/bsl/doc/options/ManualMergeStrategy.java index fbc04f9..9d17a64 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/options/MergeStrategy.java +++ b/src/main/java/ru/alkoleft/bsl/doc/options/ManualMergeStrategy.java @@ -1,6 +1,6 @@ package ru.alkoleft.bsl.doc.options; -public enum MergeStrategy { +public enum ManualMergeStrategy { NONE, REPLACE, APPEND, diff --git a/src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java b/src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java index 0395900..56c6d45 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java +++ b/src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java @@ -1,8 +1,14 @@ package ru.alkoleft.bsl.doc.options; +import lombok.Builder; +import lombok.Value; + import java.nio.file.Path; +@Builder +@Value public class OutputOptions { - OutputFormat format; + OutputFormat outputFormat; + boolean subsystemHierarchy; Path destination; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/options/RenderOptions.java b/src/main/java/ru/alkoleft/bsl/doc/options/RenderOptions.java deleted file mode 100644 index 5428aee..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/options/RenderOptions.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.alkoleft.bsl.doc.options; - -import lombok.Builder; -import lombok.Value; - -@Builder -@Value -public class RenderOptions { - OutputFormat outputFormat; - boolean subsystemHierarchy; -} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/BslRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/BslRender.java index 3db87fc..3d055d5 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/BslRender.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/BslRender.java @@ -1,6 +1,5 @@ package ru.alkoleft.bsl.doc.render; -import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; import lombok.SneakyThrows; import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; @@ -24,11 +23,6 @@ public String renderModule(ModuleContext module) { return BaseRender.render("module", ContextFactory.createContext(module)); } - @SneakyThrows - public String renderSubsystem(MDSubsystem subsystem, int level) { - return renderSubsystem(ContextFactory.create(subsystem, 0, level)); - } - @SneakyThrows public String renderSubsystem(SubsystemContext subsystem) { log.debug("Render subsystem '{}'", subsystem.getName()); diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java index a1410d6..3e88e06 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java @@ -5,7 +5,7 @@ import ru.alkoleft.bsl.doc.model.ContentModel; import ru.alkoleft.bsl.doc.model.PageType; import ru.alkoleft.bsl.doc.render.contexts.ContextFactory; -import ru.alkoleft.bsl.doc.render.processor.OutputProcessor; +import ru.alkoleft.bsl.doc.render.output.OutputStrategy; import ru.alkoleft.bsl.doc.structure.Item; import ru.alkoleft.bsl.doc.structure.MDObjectItem; import ru.alkoleft.bsl.doc.structure.ModuleItem; @@ -16,23 +16,25 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Stack; public class StructureRender implements StructureVisitor { - private final OutputProcessor outputProcessor; + private final OutputStrategy outputStrategy; private final Stack> children = new Stack<>(); private final ContentModel contentModel; private boolean withRoot = false; private int subsystemLevel = 0; private PathResolver pathResolver; - public StructureRender(OutputProcessor outputProcessor, ContentModel contentModel) { - this.outputProcessor = outputProcessor; - this.contentModel = contentModel; + public StructureRender(OutputStrategy outputStrategy, ContentModel contentModel) { + this.outputStrategy = outputStrategy; + + this.contentModel = Objects.requireNonNullElseGet(contentModel, ContentModel::new); } public void render(List structure, Path destination) { - pathResolver = new PathResolver(destination, outputProcessor.getFormat()); + pathResolver = new PathResolver(destination, outputStrategy.getFormat()); children.clear(); subsystemLevel = 0; withRoot = structure.size() > 1; @@ -58,17 +60,6 @@ public void visit(SubsystemItem item, int index) { pathResolver.exit(); } subsystemLevel--; -// var childrenItems = children.pop().stream() -// .map(it -> it.toString().substring(path.toString().length() + 1)) -// .collect(Collectors.toList()); -// if (!childrenItems.isEmpty()) { -// var itemPath = path.resolve("index.md"); -// if (outputProcessor.needRender(itemPath)) { -// var content = outputProcessor.getRender().render((MDSubsystem) item.getObject(), subsystemLevel, childrenItems); -// outputProcessor.save(itemPath, content); -// } -// children.peek().add(itemPath); -// } } @Override @@ -83,11 +74,11 @@ public void visit(ModuleItem item, int index) { Files.createDirectories(path.getParent()); } children.peek().add(path); - if (outputProcessor.needRender(path)) { + if (outputStrategy.needRender(path)) { var context = ContextFactory.create(moduleContext, index); var content = BslRender.renderModule(moduleContext, index); - outputProcessor.save(path, content); + outputStrategy.save(path, content); contentModel.append(path, PageType.MODULE); } } @@ -100,12 +91,12 @@ public void visit(MDObjectItem item, int index) { private void renderSubsystemPage(SubsystemItem item) { var path = pathResolver.getFilePath("index"); - if (outputProcessor.needRender(path)) { + if (outputStrategy.needRender(path)) { var context = ContextFactory.create(item.getSubsystem(), 0, subsystemLevel); context.setContentModel(contentModel); context.setOutputPath(path.getParent()); var content = BslRender.renderSubsystem(context); - outputProcessor.save(path, content); + outputStrategy.save(path, content); contentModel.append(path, PageType.SUBSYSTEM); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java index a53efd6..9a64138 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java @@ -30,6 +30,7 @@ public ModuleContext create(ModuleInfo module, int index) { public SubsystemContext create(MDSubsystem subsystem, int index, int level) { return SubsystemContext.builder() + .subsystem(subsystem) .index(index) .name(subsystem.getName()) .present(getPresent(subsystem)) diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java index d978482..1407730 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ModuleContext.java @@ -17,8 +17,8 @@ public class ModuleContext extends BaseContext { List methods; @Builder - public ModuleContext(Path outputPath, int index, String name, String present, String description, boolean isCommonModule, String ownerType, String moduleType, List methods) { - super(outputPath, index, name, present, description); + public ModuleContext(int index, String name, String present, String description, Path outputPath, boolean isCommonModule, String ownerType, String moduleType, List methods) { + super(index, name, present, description, outputPath); this.isCommonModule = isCommonModule; this.ownerType = ownerType; this.moduleType = moduleType; diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java index 8c666f5..5394a1d 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java @@ -1,30 +1,44 @@ package ru.alkoleft.bsl.doc.render.contexts; +import com.github._1c_syntax.mdclasses.mdo.MDConstant; +import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.model.ContentModel; import ru.alkoleft.bsl.doc.model.Page; import java.nio.file.Path; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; @EqualsAndHashCode(callSuper = true) @Getter public class SubsystemContext extends BaseContext { private final int level; + private final MDSubsystem subsystem; @Setter - ContentModel contentModel; + private ContentModel contentModel; @Builder - public SubsystemContext(Path outputPath, int index, String name, String present, String description, int level) { - super(outputPath, index, name, present, description); + public SubsystemContext(int index, String name, String present, String description, Path outputPath, int level, MDSubsystem subsystem) { + super(index, name, present, description, outputPath); this.level = level; + this.subsystem = subsystem; } - public List getChildren() { + public List getConstants() { + var c = BslContext.getCurrent().getSubsystemObjects(subsystem) + .filter(MDConstant.class::isInstance) + .map(MDConstant.class::cast) + .collect(Collectors.toList()); + return c; + } + + public List getChildrenPages() { if (contentModel != null) { return contentModel.getChildrenPages(getOutputPath()); } else { diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java index 5a3d709..6c28f3e 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java @@ -7,9 +7,10 @@ import lombok.SneakyThrows; import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.bsl.BslContext; -import ru.alkoleft.bsl.doc.options.RenderOptions; +import ru.alkoleft.bsl.doc.options.OutputOptions; import ru.alkoleft.bsl.doc.render.handlebars.helpers.Debugger; import ru.alkoleft.bsl.doc.render.handlebars.helpers.Links; +import ru.alkoleft.bsl.doc.render.handlebars.helpers.MdoPresent; import ru.alkoleft.bsl.doc.render.handlebars.helpers.Shifter; import ru.alkoleft.bsl.doc.render.handlebars.helpers.SingleLine; @@ -30,6 +31,7 @@ private RenderContext(String path) { this.path = path; handlebars = new Handlebars().with(value -> value); handlebars.registerHelper("links", linksRender = new Links()); + handlebars.registerHelper("mdo-present", new MdoPresent()); handlebars.registerHelper("shift", new Shifter()); handlebars.registerHelper("debug", new Debugger()); handlebars.registerHelper("single-line", new SingleLine()); @@ -69,7 +71,7 @@ private Template getTemplate(String name) throws IOException { @UtilityClass public static class Factory { - public RenderContext create(RenderOptions options) { + public RenderContext create(OutputOptions options) { return new RenderContext(options.getOutputFormat().getPath()); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/MdoPresent.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/MdoPresent.java new file mode 100644 index 0000000..a040101 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/MdoPresent.java @@ -0,0 +1,29 @@ +package ru.alkoleft.bsl.doc.render.handlebars.helpers; + +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; +import com.github.jknack.handlebars.Helper; +import com.github.jknack.handlebars.Options; +import ru.alkoleft.bsl.doc.render.contexts.SubsystemContext; + +import java.io.IOException; + +public class MdoPresent implements Helper { + @Override + public Object apply(Object context, Options options) throws IOException { + if (context instanceof AbstractMDObjectBase) { + return getPresent((AbstractMDObjectBase) context); + } else if (context instanceof SubsystemContext) { + return getPresent(((SubsystemContext) context).getSubsystem()); + } else { + return context.toString(); + } + } + + private String getPresent(AbstractMDObjectBase object) { + if (object.getSynonyms().isEmpty()) { + return object.getName(); + } else { + return object.getSynonyms().get(0).getContent(); + } + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/processor/AppendProcessor.java b/src/main/java/ru/alkoleft/bsl/doc/render/output/AppendStrategy.java similarity index 57% rename from src/main/java/ru/alkoleft/bsl/doc/render/processor/AppendProcessor.java rename to src/main/java/ru/alkoleft/bsl/doc/render/output/AppendStrategy.java index 34f9439..1894e52 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/processor/AppendProcessor.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/output/AppendStrategy.java @@ -1,8 +1,8 @@ -package ru.alkoleft.bsl.doc.render.processor; +package ru.alkoleft.bsl.doc.render.output; import java.nio.file.Path; -public class AppendProcessor extends OutputProcessor { +public class AppendStrategy extends OutputStrategy { @Override public boolean needRender(Path location) { return !manualContent.contains(location); diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/processor/MergeProcessor.java b/src/main/java/ru/alkoleft/bsl/doc/render/output/MergeStrategy.java similarity index 91% rename from src/main/java/ru/alkoleft/bsl/doc/render/processor/MergeProcessor.java rename to src/main/java/ru/alkoleft/bsl/doc/render/output/MergeStrategy.java index 7ab5358..cce11be 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/processor/MergeProcessor.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/output/MergeStrategy.java @@ -1,4 +1,4 @@ -package ru.alkoleft.bsl.doc.render.processor; +package ru.alkoleft.bsl.doc.render.output; import com.github.jknack.handlebars.internal.Files; import lombok.SneakyThrows; @@ -10,7 +10,7 @@ import java.nio.file.Path; import java.util.regex.Pattern; -public class MergeProcessor extends OutputProcessor { +public class MergeStrategy extends OutputStrategy { private static final Pattern replacePattern = Pattern.compile("^.*generated_content.*$", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); TitleProcessor titleCleaner; diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/processor/OutputProcessor.java b/src/main/java/ru/alkoleft/bsl/doc/render/output/OutputStrategy.java similarity index 54% rename from src/main/java/ru/alkoleft/bsl/doc/render/processor/OutputProcessor.java rename to src/main/java/ru/alkoleft/bsl/doc/render/output/OutputStrategy.java index 0e10905..e7accdf 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/processor/OutputProcessor.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/output/OutputStrategy.java @@ -1,17 +1,17 @@ -package ru.alkoleft.bsl.doc.render.processor; +package ru.alkoleft.bsl.doc.render.output; import lombok.Getter; import lombok.Setter; import lombok.SneakyThrows; import ru.alkoleft.bsl.doc.manual.ManualContent; -import ru.alkoleft.bsl.doc.options.MergeStrategy; +import ru.alkoleft.bsl.doc.options.ManualMergeStrategy; import ru.alkoleft.bsl.doc.options.OutputFormat; import java.nio.file.Files; import java.nio.file.Path; @Getter -public class OutputProcessor { +public class OutputStrategy { @Setter protected OutputFormat format; @Setter @@ -21,9 +21,20 @@ public boolean needRender(Path location) { return true; } - @SneakyThrows - public void save(Path itemPath, String content) { - Files.writeString(itemPath, content); + public static OutputStrategy create(ManualMergeStrategy strategy) { + OutputStrategy processor; + switch (strategy) { + case APPEND: + processor = new AppendStrategy(); + break; + case MERGE: + processor = new MergeStrategy(); + break; + default: + processor = new OutputStrategy(); + break; + } + return processor; } public void init(OutputFormat format, ManualContent manualContent) { @@ -31,21 +42,9 @@ public void init(OutputFormat format, ManualContent manualContent) { this.manualContent = manualContent; } - public static class Factory { - public static OutputProcessor create(MergeStrategy strategy) { - OutputProcessor processor; - switch (strategy) { - case APPEND: - processor = new AppendProcessor(); - break; - case MERGE: - processor = new MergeProcessor(); - break; - default: - processor = new OutputProcessor(); - break; - } - return processor; - } + @SneakyThrows + public void save(Path itemPath, String content) { + Files.createDirectories(itemPath.getParent()); + Files.writeString(itemPath, content); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/processor/Writer.java b/src/main/java/ru/alkoleft/bsl/doc/render/output/Writer.java similarity index 79% rename from src/main/java/ru/alkoleft/bsl/doc/render/processor/Writer.java rename to src/main/java/ru/alkoleft/bsl/doc/render/output/Writer.java index a160fed..6ed0bac 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/processor/Writer.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/output/Writer.java @@ -1,4 +1,4 @@ -package ru.alkoleft.bsl.doc.render.processor; +package ru.alkoleft.bsl.doc.render.output; import ru.alkoleft.bsl.doc.options.OutputFormat; diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java index 1f4de10..5cc0880 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java @@ -24,19 +24,17 @@ public Item createMDObjectItem(AbstractMDObjectBSL owner) { return item; } - private void fillChildrenObjects(Item item, BslContext context) { - context.getSubsystemObjects((MDSubsystem) item.getObject()) + private void fillChildrenObjects(SubsystemItem item, BslContext context) { + context.getSubsystemObjects(item.getSubsystem()) .map(Factory::createMDObjectItem) .filter(it -> !it.getChildren().isEmpty()) .forEach(item.getChildren()::add); } - private void fillChildrenSubsystems(Item subsystemItem, BslContext context) { - context.getChildrenSubsystems((MDSubsystem) subsystemItem.getObject()) - .forEach(it -> { - var item = createSubSystemItem(it, context); - subsystemItem.getChildren().add(item); - }); + private void fillChildrenSubsystems(SubsystemItem item, BslContext context) { + context.getChildrenSubsystems(item.getSubsystem()) + .map(it -> createSubSystemItem(it, context)) + .forEach(item.getChildren()::add); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java b/src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java index e3f63bb..5c5dfe3 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/StructureBuilder.java @@ -1,8 +1,7 @@ package ru.alkoleft.bsl.doc.structure; -import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.bsl.BslContext; -import ru.alkoleft.bsl.doc.options.RenderOptions; +import ru.alkoleft.bsl.doc.options.OutputOptions; import java.util.List; @@ -10,40 +9,34 @@ public interface StructureBuilder { List build(BslContext context); - @UtilityClass - class Factory { - public StructureBuilder builder(RenderOptions options) { - if (options.isSubsystemHierarchy()) { - return new SubsystemsStructureBuilder(); - } else { - return new FlatStructureBuilder(); - } - } - - public List build(BslContext context, RenderOptions options) { - return builder(options).build(context); + static StructureBuilder builder(OutputOptions options) { + if (options.isSubsystemHierarchy()) { + return new SubsystemsStructureBuilder(); + } else { + return new FlatStructureBuilder(); } + } - public void print(List structure) { - print(structure, ""); - } + static void print(List structure) { + print(structure, ""); + } - private void print(List structure, String prefix) { - Item item; - for (int index = 0; index < structure.size(); index++) { - item = structure.get(index); - if (index == structure.size() - 1) { - System.out.printf("%s└── %s\n", prefix, item.getPresent()); - if (!item.getChildren().isEmpty()) { - print(item.getChildren(), prefix + " "); - } - } else { - System.out.printf("%s├── %s\n", prefix, item.getPresent()); - if (!item.getChildren().isEmpty()) { - print(item.getChildren(), prefix + "│   "); - } + private static void print(List structure, String prefix) { + Item item; + for (int index = 0; index < structure.size(); index++) { + item = structure.get(index); + if (index == structure.size() - 1) { + System.out.printf("%s└── %s\n", prefix, item.getPresent()); + if (!item.getChildren().isEmpty()) { + print(item.getChildren(), prefix + " "); + } + } else { + System.out.printf("%s├── %s\n", prefix, item.getPresent()); + if (!item.getChildren().isEmpty()) { + print(item.getChildren(), prefix + "│   "); } } } + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java index bed83cf..d5ceefa 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java @@ -1,6 +1,5 @@ package ru.alkoleft.bsl.doc.structure; - import ru.alkoleft.bsl.doc.bsl.BslContext; import java.util.List; @@ -12,7 +11,7 @@ public List build(BslContext context) { return context.getRootSubsystems() .filter(it -> context.getFilter().getRootSubsystems().contains(it.getName())) - .map(it -> ru.alkoleft.bsl.doc.structure.Factory.createSubSystemItem(it, context)) + .map(it -> Factory.createSubSystemItem(it, context)) .collect(Collectors.toList()); } } diff --git a/src/main/resources/confluence-md/subsystem.hbs b/src/main/resources/confluence-md/subsystem.hbs index e9dd78b..afb5bfd 100644 --- a/src/main/resources/confluence-md/subsystem.hbs +++ b/src/main/resources/confluence-md/subsystem.hbs @@ -2,7 +2,13 @@ {{#if description}} {{description}} {{/if}} + +Константы: +{{#each constants as | item|}} +* {{mdo-present item}} ({{item.name}}) +{{/each}} + Содержимое: -{{#each children as | item|}} +{{#each childrenPages as | item|}} * [{{item.title}}]({{item.path}}) {{/each}} \ No newline at end of file diff --git a/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java index aa4da15..475f009 100644 --- a/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java +++ b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java @@ -1,33 +1,32 @@ package ru.alkoleft.bsl.doc.commands; -import org.junit.jupiter.api.BeforeEach; +import lombok.SneakyThrows; import org.junit.jupiter.api.Test; import ru.alkoleft.bsl.doc.bsl.symbols.RegionSymbol; -import ru.alkoleft.bsl.doc.options.MergeStrategy; +import ru.alkoleft.bsl.doc.options.ManualMergeStrategy; import ru.alkoleft.bsl.doc.options.OutputFormat; -import java.net.URISyntaxException; import java.nio.file.Path; import java.util.List; class RenderCommandTest { - RenderCommand cmd; - - @BeforeEach - void setUp() throws URISyntaxException { - cmd = new RenderCommand(); - cmd.sources = Path.of(getClass().getClassLoader().getResource("configuration").toURI()); - cmd.destination = Path.of("/tmp/bsl-doc-fixture"); - cmd.format = OutputFormat.ConfluenceMarkdown; - cmd.onlySubsystems = List.of("ППИ"); - cmd.regions = List.of(RegionSymbol.PUBLIC_REGION_RU); - cmd.manualDocumentation = Path.of(getClass().getClassLoader().getResource("docs").toURI()); - cmd.mergeStrategy = MergeStrategy.MERGE; - } - @Test void run() { - cmd.run(); + RenderCommand.builder() + .sources(getResource("configuration")) + .destination(Path.of("/tmp/bsl-doc-fixture")) + .format(OutputFormat.ConfluenceMarkdown) + .onlySubsystems(List.of("ППИ")) + .regions(List.of(RegionSymbol.PUBLIC_REGION_RU)) + .manualDocumentation(getResource("docs")) + .manualMergeStrategy(ManualMergeStrategy.MERGE) + .build() + .run(); + } + + @SneakyThrows + private Path getResource(String name) { + return Path.of(getClass().getClassLoader().getResource(name).toURI()); } } \ No newline at end of file diff --git "a/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721/ManagerModule.bsl" "b/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721/ManagerModule.bsl" new file mode 100644 index 0000000..4765a70 --- /dev/null +++ "b/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721/ManagerModule.bsl" @@ -0,0 +1,13 @@ +#Область ПрограммныйИнтерфейс + +// Процедура1. +// Устаревший. +// +// Параметры: +// П1 П1 +// П2 П2 +Процедура Процедура1(П1, П2) Экспорт + +КонецПроцедуры + +#КонецОбласти \ No newline at end of file diff --git "a/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721.mdo" "b/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721.mdo" new file mode 100644 index 0000000..8ad2ff6 --- /dev/null +++ "b/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2721.mdo" @@ -0,0 +1,33 @@ + + + + + + + + + + Справочник1 + + ru + Справочник1 + + true + Catalog.Справочник1.StandardAttribute.Code + Catalog.Справочник1.StandardAttribute.Description + DontUse + Use + Managed + Use + 2 + true + 9 + 25 + String + Variable + true + true + AsDescription + InDialog + BothWays + diff --git "a/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722/ObjectModule.bsl" "b/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722/ObjectModule.bsl" new file mode 100644 index 0000000..4765a70 --- /dev/null +++ "b/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722/ObjectModule.bsl" @@ -0,0 +1,13 @@ +#Область ПрограммныйИнтерфейс + +// Процедура1. +// Устаревший. +// +// Параметры: +// П1 П1 +// П2 П2 +Процедура Процедура1(П1, П2) Экспорт + +КонецПроцедуры + +#КонецОбласти \ No newline at end of file diff --git "a/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722.mdo" "b/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722.mdo" new file mode 100644 index 0000000..c6caceb --- /dev/null +++ "b/src/test/resources/configuration/src/Catalogs/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\2722.mdo" @@ -0,0 +1,33 @@ + + + + + + + + + + Справочник2 + + ru + Справочник2 + + true + Catalog.Справочник2.StandardAttribute.Code + Catalog.Справочник2.StandardAttribute.Description + DontUse + Use + Managed + Use + 2 + true + 9 + 25 + String + Variable + true + true + AsDescription + InDialog + BothWays + diff --git a/src/test/resources/configuration/src/Configuration/Configuration.mdo b/src/test/resources/configuration/src/Configuration/Configuration.mdo index 0670b82..69a0b86 100644 --- a/src/test/resources/configuration/src/Configuration/Configuration.mdo +++ b/src/test/resources/configuration/src/Configuration/Configuration.mdo @@ -42,4 +42,9 @@ Subsystem.ППИ CommonModule.Преобразования CommonModule.СтроковыеФункции + Constant.Константа + Constant.Константа1 + Constant.Константа2 + Catalog.Справочник1 + Catalog.Справочник2 diff --git "a/src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\260/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\260.mdo" "b/src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\260/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\260.mdo" new file mode 100644 index 0000000..c5cfc4a --- /dev/null +++ "b/src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\260/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\260.mdo" @@ -0,0 +1,23 @@ + + + + + + + + Константа + + ru + Константа + + + String + + 10 + + + true + + + Managed + diff --git "a/src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2601/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2601.mdo" "b/src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2601/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2601.mdo" new file mode 100644 index 0000000..34a3141 --- /dev/null +++ "b/src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2601/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2601.mdo" @@ -0,0 +1,23 @@ + + + + + + + + Константа1 + + ru + Константа 1 + + + String + + 10 + + + true + + + Managed + diff --git "a/src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2602/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2602.mdo" "b/src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2602/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2602.mdo" new file mode 100644 index 0000000..53b83bd --- /dev/null +++ "b/src/test/resources/configuration/src/Constants/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2602/\320\232\320\276\320\275\321\201\321\202\320\260\320\275\321\202\320\2602.mdo" @@ -0,0 +1,23 @@ + + + + + + + + Константа2 + + ru + Константа 2 + + + String + + 10 + + + true + + + Managed + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/CommandInterface.cmi" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/CommandInterface.cmi" similarity index 100% rename from "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/CommandInterface.cmi" rename to "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/CommandInterface.cmi" diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/CommandInterface.cmi" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213/CommandInterface.cmi" similarity index 100% rename from "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/CommandInterface.cmi" rename to "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213/CommandInterface.cmi" diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213/\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213/\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213.mdo" new file mode 100644 index 0000000..ff1e502 --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213/\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202\321\213.mdo" @@ -0,0 +1,11 @@ + + + Документы + + ru + Документы + + true + true + Subsystem.ППИ.Subsystem.Прикладные + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/CommandInterface.cmi" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\272\320\270/CommandInterface.cmi" similarity index 100% rename from "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/CommandInterface.cmi" rename to "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\272\320\270/CommandInterface.cmi" diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\272\320\270/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\272\320\270.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\272\320\270/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\272\320\270.mdo" new file mode 100644 index 0000000..860a5b2 --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/Subsystems/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\272\320\270/\320\241\320\277\321\200\320\260\320\262\320\276\321\207\320\275\320\270\320\272\320\270.mdo" @@ -0,0 +1,14 @@ + + + Справочники + + ru + Справочники + + true + true + Catalog.Справочник1 + Catalog.Справочник2 + Constant.Константа + Subsystem.ППИ.Subsystem.Прикладные + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265.mdo" new file mode 100644 index 0000000..9f6bb13 --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265.mdo" @@ -0,0 +1,15 @@ + + + Прикладные + + ru + Прикладные + + true + true + Constant.Константа1 + Constant.Константа2 + Документы + Справочники + Subsystem.ППИ + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" deleted file mode 100644 index 20ddb73..0000000 --- "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217/\320\237\321\200\320\265\320\276\320\261\321\200\320\260\320\267\320\276\320\262\320\260\320\275\320\270\321\217.mdo" +++ /dev/null @@ -1,12 +0,0 @@ - - - Преобразования - - ru - Преобразования - - true - true - CommonModule.Преобразования - Subsystem.ППИ.Subsystem.Раздел1 - diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" deleted file mode 100644 index 9b0b7f6..0000000 --- "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/Subsystems/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270.mdo" +++ /dev/null @@ -1,12 +0,0 @@ - - - СтроковыеФункции - - ru - Строковые функции - - true - true - CommonModule.СтроковыеФункции - Subsystem.ППИ.Subsystem.Раздел1 - diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/CommandInterface.cmi" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/CommandInterface.cmi" new file mode 100644 index 0000000..0cf6de8 --- /dev/null +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/CommandInterface.cmi" @@ -0,0 +1,2 @@ + + diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265.mdo" similarity index 72% rename from "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" rename to "src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265.mdo" index 2c90f94..7fc6cd1 100644 --- "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\240\320\260\320\267\320\264\320\265\320\2731/\320\240\320\260\320\267\320\264\320\265\320\2731.mdo" +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265.mdo" @@ -1,13 +1,13 @@ - Раздел1 + Сервисные ru Раздел 1 true true - СтроковыеФункции - Преобразования + CommonModule.Преобразования + CommonModule.СтроковыеФункции Subsystem.ППИ diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/\320\237\320\237\320\230.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/\320\237\320\237\320\230.mdo" index 0b64e96..cc6b7e4 100644 --- "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/\320\237\320\237\320\230.mdo" +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/\320\237\320\237\320\230.mdo" @@ -7,5 +7,6 @@ true true - Раздел1 + Прикладные + Сервисные diff --git "a/src/test/resources/docs/\320\240\320\260\320\267\320\264\320\265\320\2731/index.md" "b/src/test/resources/docs/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/index.md" similarity index 100% rename from "src/test/resources/docs/\320\240\320\260\320\267\320\264\320\265\320\2731/index.md" rename to "src/test/resources/docs/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/index.md" From b83df1e8968f063d987ef177bbe25240ea77ce17 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Wed, 18 Oct 2023 00:29:29 +0300 Subject: [PATCH 16/27] Refactoring --- .../ru/alkoleft/bsl/doc/bsl/BslContext.java | 246 ++---------------- .../java/ru/alkoleft/bsl/doc/bsl/Filter.java | 1 + .../bsl/doc/bsl/helpers/BslFilter.java | 75 ++++++ .../bsl/doc/bsl/helpers/ModuleComputer.java | 108 ++++++++ .../doc/bsl/helpers/ModuleContextBuilder.java | 58 +++++ .../bsl/doc/commands/RenderCommand.java | 2 +- .../bsl/doc/render/StructureRender.java | 2 +- .../alkoleft/bsl/doc/structure/Factory.java | 3 +- .../structure/SubsystemsStructureBuilder.java | 3 +- .../ru/alkoleft/bsl/doc/structure/Utils.java | 21 -- 10 files changed, 274 insertions(+), 245 deletions(-) create mode 100644 src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/BslFilter.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleComputer.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleContextBuilder.java delete mode 100644 src/main/java/ru/alkoleft/bsl/doc/structure/Utils.java diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java index d5b82e8..26efe28 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java @@ -1,26 +1,19 @@ package ru.alkoleft.bsl.doc.bsl; -import com.github._1c_syntax.bsl.parser.BSLParser; -import com.github._1c_syntax.bsl.parser.BSLTokenizer; import com.github._1c_syntax.bsl.types.MDOType; import com.github._1c_syntax.mdclasses.Configuration; import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; -import com.github._1c_syntax.mdclasses.mdo.MDCommonModule; import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; import com.google.common.base.Strings; import io.vavr.control.Either; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.antlr.v4.runtime.Token; -import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; -import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbolComputer; +import ru.alkoleft.bsl.doc.bsl.helpers.BslFilter; +import ru.alkoleft.bsl.doc.bsl.helpers.ModuleContextBuilder; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -30,87 +23,42 @@ @Slf4j public class BslContext { - - private static final Set VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH = Set.of( - BSLParser.LINE_COMMENT, - BSLParser.WHITE_SPACE, - BSLParser.AMPERSAND - ); @Getter private static BslContext current; @Getter - Configuration configuration; - @Getter - Filter filter; - List modules = Collections.emptyList(); - - Set topObjectsType = Set.copyOf(MDOType.valuesWithoutChildren()); + private final Configuration configuration; + private final Set topObjectsType = Set.copyOf(MDOType.valuesWithoutChildren()); + private final ModuleContextBuilder builder; + private List modules = Collections.emptyList(); public BslContext(Path path, Filter filter) { - this.filter = filter; + BslFilter.setFilter(filter); + builder = new ModuleContextBuilder(); configuration = Configuration.create(path); current = this; } - public static List getComments(List tokens, Token token) { - List comments = new ArrayList<>(); - fillCommentsCollection(tokens, token, comments); - return comments; - } - - private static void fillCommentsCollection(List tokens, Token currentToken, List lines) { - - int index = currentToken.getTokenIndex(); - - if (index == 0) { - return; - } - - var previousToken = tokens.get(index - 1); - - if (abortSearchComments(previousToken, currentToken)) { - return; - } - - fillCommentsCollection(tokens, previousToken, lines); - int type = previousToken.getType(); - if (type == BSLParser.LINE_COMMENT) { - lines.add(previousToken); - } - } - - private static boolean abortSearchComments(Token previousToken, Token currentToken) { - int type = previousToken.getType(); - return !VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH.contains(type) || isBlankLine(previousToken, currentToken); - } - - private static boolean isBlankLine(Token previousToken, Token currentToken) { - return previousToken.getType() == BSLParser.WHITE_SPACE - && (previousToken.getTokenIndex() == 0 - || (previousToken.getLine() + 1) != currentToken.getLine()); - } - public Stream getModules() { - return configuration.getOrderedTopMDObjects().get(MDOType.COMMON_MODULE).stream() - .map(MDCommonModule.class::cast) - .map(it -> it.getModules().get(0)); + return configuration.getChildren().stream() + .filter(AbstractMDObjectBSL.class::isInstance) + .map(AbstractMDObjectBSL.class::cast) + .flatMap(it -> it.getModules().stream()) + .filter(BslFilter::checkModule); } - public Stream getModulesInfo() { - var stream = modules.stream(); - - if (!filter.getModules().isEmpty()) { - stream = stream.filter(m -> filter.getModules().contains(m.getName())); - } - - return stream - .map(this::buildModuleContext) - .filter(ModuleInfo::isNotEmpty); + public ModuleInfo getModuleContext(MDOModule module) { + return builder.buildFilteredModuleContext(module); } - public Stream getRootSubsystems() { - return configuration.getOrderedTopMDObjects().get(MDOType.SUBSYSTEM).stream() + public Stream getRootSubsystems(boolean filtered) { + var stream = configuration.getOrderedTopMDObjects().get(MDOType.SUBSYSTEM) + .stream() .map(MDSubsystem.class::cast); + + if (filtered) { + stream = stream.filter(BslFilter::checkRootSubsystem); + } + return stream; } public Stream getChildrenSubsystems(MDSubsystem parent) { @@ -121,24 +69,6 @@ public Stream getChildrenSubsystems(MDSubsystem parent) { .map(MDSubsystem.class::cast); } - public Stream getSubsystems() { - return getRootSubsystems() - .flatMap(this::getRecursiveChildrenSubsystems); - } - - private Stream getRecursiveChildrenSubsystems(MDSubsystem parent) { - if (parent.getChildren().isEmpty()) { - return Stream.of(parent); - } - - return Stream.concat(Stream.of(parent), parent.getChildren().stream() - .filter(Either::isRight) - .map(Either::get) - .filter(MDSubsystem.class::isInstance) - .map(MDSubsystem.class::cast) - .flatMap(this::getRecursiveChildrenSubsystems)); - } - public boolean contains(String name) { return modules.stream().anyMatch(it -> it.getName().equalsIgnoreCase(name)); } @@ -162,133 +92,11 @@ boolean isTopObject(AbstractMDObjectBase obj) { } public void load() { - modules = configuration.getOrderedTopMDObjects().get(MDOType.COMMON_MODULE).stream() - .map(MDCommonModule.class::cast) - .map(this::buildModuleContext) + modules = getModules() + .map(builder::buildModuleContext) .collect(Collectors.toList()); } - public ModuleInfo buildModuleContext(MDCommonModule module) { - var bslModules = module.getModules(); - var bslModule = bslModules.get(0); - return buildModuleContext(bslModule); - } - - public ModuleInfo buildFilteredModuleContext(MDOModule bslModule) { - return buildModuleContext(buildModuleContext(bslModule)); - } - - public ModuleInfo buildModuleContext(MDOModule bslModule) { - var owner = (AbstractMDObjectBSL) bslModule.getOwner(); - log.debug("Parse module: " + owner.getName() + "." + bslModule.getModuleType()); - var srcPath = Path.of(bslModule.getUri()); - List methods; - String description; - try { - var content = Files.readString(srcPath); - MethodSymbolComputer computer = new MethodSymbolComputer(); - var tokenizer = new BSLTokenizer(content); - methods = computer.compute(tokenizer); - description = computeModuleDescription(tokenizer); - } catch (Exception e) { - throw new RuntimeException(owner.getMdoReference().getMdoRef() + ". Module parsing error", e); - } - - return ModuleInfo.builder() - .owner(owner) - .module(bslModule) - .methods(methods) - .description(description) - .build(); - } - - private String computeModuleDescription(BSLTokenizer tokenizer) { - var token = tokenizer.getAst().getStart(); - - var isDescription = false; - List comments = null; - while (token != null && !isDescription) { - comments = getComments(tokenizer.getTokens(), token); - isDescription = !comments.isEmpty() && comments.stream().map(Token::getText).map(it -> it.substring(2)).map(String::trim).noneMatch(it -> it.contains("Copyright") || it.contains("Экспортные")); - token = comments.isEmpty() ? null : comments.get(0); - } - if (isDescription) { - var lines = comments.stream() - .map(Token::getText) - .map(it -> it.substring(2)) - .filter(it -> it.isEmpty() || !it.matches("/+")) - .collect(Collectors.toList()); - - var chars = lines.get(0).toCharArray(); - - for (int i = 1; i < lines.size(); i++) { - var line = lines.get(i); - - for (int j = 0; j < chars.length; j++) { - if (line.length() <= j || line.charAt(j) != chars[j]) { - chars = Arrays.copyOf(chars, j); - break; - } - } - if (chars.length == 0) { - break; - } - } - - if (chars.length > 0) { - char[] finalChars = chars; - return lines.stream() - .map(it -> it.substring(finalChars.length)) - .collect(Collectors.joining("\n")); - } else { - return String.join("\n", lines); - } - } else { - return ""; - } - } - - private ModuleInfo buildModuleContext(ModuleInfo module) { - - var stream = module.getMethods().stream(); - - if (filter.isExport()) { - stream = stream.filter(MethodSymbol::isExport); - } - - if (!filter.getRegions().isEmpty()) { - stream = stream.filter(this::regionFilter); - } - - return ModuleInfo.builder() - .module(module.getModule()) - .owner(module.getOwner()) - .description(module.getDescription()) - .methods(stream.collect(Collectors.toList())) - .build(); - } - - private boolean checkModule(ModuleInfo module) { - return true; - } - - private boolean checkMethod(MethodSymbol method) { - return (!filter.isExport() || method.isExport()) - && (filter.getRegions().isEmpty() || regionFilter(method)); - } - - private boolean regionFilter(MethodSymbol m) { - var region = m.getRegion(); - - while (region != null) { - if (filter.getRegions().contains(region.getName())) { - return true; - } - region = region.getParent(); - } - return false; - } - public MethodInfo getMethodInfo(String link) { if (Strings.isNullOrEmpty(link)) { return null; @@ -299,7 +107,6 @@ public MethodInfo getMethodInfo(String link) { public MethodInfo getMethodInfo(Links.Link link) { - if (link == null || link.getOwnerName() == null || link.getMethodName() == null) { return null; } @@ -310,7 +117,8 @@ public MethodInfo getMethodInfo(Links.Link link) { return MethodInfo.builder() .module(module.orElse(null)) .method(method.orElse(null)) - .publishing(module.isPresent() && method.isPresent() && checkModule(module.get()) && checkMethod(method.get())) + .publishing(module.isPresent() && method.isPresent() && BslFilter.checkModule(module.get()) && BslFilter.checkMethod(method.get())) .build(); } + } diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java index b35d1bb..1e8cf77 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/Filter.java @@ -10,6 +10,7 @@ @Builder public class Filter { boolean isExport; + boolean onlyCommonAndManagerModules = false; @Singular List regions; @Singular diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/BslFilter.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/BslFilter.java new file mode 100644 index 0000000..d3c60c1 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/BslFilter.java @@ -0,0 +1,75 @@ +package ru.alkoleft.bsl.doc.bsl.helpers; + +import com.github._1c_syntax.bsl.types.ModuleType; +import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; +import lombok.Getter; +import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.bsl.Filter; +import ru.alkoleft.bsl.doc.bsl.ModuleInfo; +import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; + +import java.util.Set; +import java.util.stream.Stream; + +@UtilityClass +public class BslFilter { + + private final Set moduleTypes = Set.of( + ModuleType.CommonModule, + ModuleType.ValueManagerModule, + ModuleType.ManagerModule + ); + + @Getter + private Filter filter; + + public static void setFilter(Filter filter) { + BslFilter.filter = filter; + } + + public boolean checkMethod(MethodSymbol method) { + return (!filter.isExport() || method.isExport()) + && (filter.getRegions().isEmpty() || checkRegion(method)); + } + + public Stream setFilter(Stream stream) { + if (filter.isExport()) { + stream = stream.filter(MethodSymbol::isExport); + } + + if (!filter.getRegions().isEmpty()) { + stream = stream.filter(BslFilter::checkRegion); + } + + return stream; + } + + public boolean checkModule(ModuleInfo module) { + return true; + } + + public boolean checkModule(MDOModule module) { + return !filter.isOnlyCommonAndManagerModules() || moduleTypes.contains(module.getModuleType()); + } + + public boolean checkRegion(MethodSymbol m) { + var region = m.getRegion(); + + while (region != null) { + if (filter.getRegions().contains(region.getName())) { + return true; + } + region = region.getParent(); + } + return false; + } + + public boolean checkRootSubsystem(MDSubsystem subsystem) { + if (filter.getRootSubsystems().isEmpty()) { + return true; + } else { + return filter.getRootSubsystems().contains(subsystem.getName()); + } + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleComputer.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleComputer.java new file mode 100644 index 0000000..8efce6c --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleComputer.java @@ -0,0 +1,108 @@ +package ru.alkoleft.bsl.doc.bsl.helpers; + +import com.github._1c_syntax.bsl.parser.BSLParser; +import com.github._1c_syntax.bsl.parser.BSLTokenizer; +import lombok.experimental.UtilityClass; +import org.antlr.v4.runtime.Token; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@UtilityClass +public class ModuleComputer { + + private final Set VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH = Set.of( + BSLParser.LINE_COMMENT, + BSLParser.WHITE_SPACE, + BSLParser.AMPERSAND + ); + + public String computeModuleDescription(BSLTokenizer tokenizer) { + var token = tokenizer.getAst().getStart(); + + var isDescription = false; + List comments = null; + while (token != null && !isDescription) { + comments = getComments(tokenizer.getTokens(), token); + isDescription = !comments.isEmpty() && comments.stream().map(Token::getText).map(it -> it.substring(2)).map(String::trim).noneMatch(it -> it.contains("Copyright") || it.contains("Экспортные")); + token = comments.isEmpty() ? null : comments.get(0); + } + if (isDescription) { + var lines = comments.stream() + .map(Token::getText) + .map(it -> it.substring(2)) + .filter(it -> it.isEmpty() || !it.matches("/+")) + .collect(Collectors.toList()); + + var chars = lines.get(0).toCharArray(); + + for (int i = 1; i < lines.size(); i++) { + var line = lines.get(i); + + for (int j = 0; j < chars.length; j++) { + if (line.length() <= j || line.charAt(j) != chars[j]) { + chars = Arrays.copyOf(chars, j); + break; + } + } + if (chars.length == 0) { + break; + } + } + + if (chars.length > 0) { + char[] finalChars = chars; + return lines.stream() + .map(it -> it.substring(finalChars.length)) + .collect(Collectors.joining("\n")); + } else { + return String.join("\n", lines); + } + } else { + return ""; + } + } + + private List getComments(List tokens, Token token) { + List comments = new ArrayList<>(); + fillCommentsCollection(tokens, token, comments); + return comments; + } + + private void fillCommentsCollection(List tokens, Token currentToken, List lines) { + + int index = currentToken.getTokenIndex(); + + if (index == 0) { + return; + } + + var previousToken = tokens.get(index - 1); + + if (abortSearchComments(previousToken, currentToken)) { + return; + } + + fillCommentsCollection(tokens, previousToken, lines); + int type = previousToken.getType(); + if (type == BSLParser.LINE_COMMENT) { + lines.add(previousToken); + } + } + + private boolean abortSearchComments(Token previousToken, Token currentToken) { + int type = previousToken.getType(); + return !VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH.contains(type) || isBlankLine(previousToken, currentToken); + } + + private boolean isBlankLine(Token previousToken, Token currentToken) { + return previousToken.getType() == BSLParser.WHITE_SPACE + && (previousToken.getTokenIndex() == 0 + || (previousToken.getLine() + 1) != currentToken.getLine()); + } + + +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleContextBuilder.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleContextBuilder.java new file mode 100644 index 0000000..2e9ff78 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleContextBuilder.java @@ -0,0 +1,58 @@ +package ru.alkoleft.bsl.doc.bsl.helpers; + +import com.github._1c_syntax.bsl.parser.BSLTokenizer; +import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; +import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; +import lombok.extern.slf4j.Slf4j; +import ru.alkoleft.bsl.doc.bsl.ModuleInfo; +import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; +import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbolComputer; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.stream.Collectors; + +@Slf4j +public class ModuleContextBuilder { + public ModuleInfo buildModuleContext(MDOModule bslModule) { + var owner = (AbstractMDObjectBSL) bslModule.getOwner(); + log.debug("Parse module: " + owner.getName() + "." + bslModule.getModuleType()); + var srcPath = Path.of(bslModule.getUri()); + List methods; + String description; + try { + var content = Files.readString(srcPath); + MethodSymbolComputer computer = new MethodSymbolComputer(); + var tokenizer = new BSLTokenizer(content); + methods = computer.compute(tokenizer); + description = ModuleComputer.computeModuleDescription(tokenizer); + } catch (Exception e) { + throw new RuntimeException(owner.getMdoReference().getMdoRef() + ". Module parsing error", e); + } + + return ModuleInfo.builder() + .owner(owner) + .module(bslModule) + .methods(methods) + .description(description) + .build(); + } + + public ModuleInfo buildFilteredModuleContext(MDOModule bslModule) { + return buildModuleContext(buildModuleContext(bslModule)); + } + + public ModuleInfo buildModuleContext(ModuleInfo module) { + + var stream = BslFilter.setFilter(module.getMethods().stream()); + + return ModuleInfo.builder() + .module(module.getModule()) + .owner(module.getOwner()) + .description(module.getDescription()) + .methods(stream.collect(Collectors.toList())) + .build(); + } + +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java index 56c51f1..1ccb790 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java +++ b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java @@ -66,7 +66,7 @@ public void run() { .filter(filter) .outputOptions(options) .manualDocumentation(manualDocumentation) - .mergeStrategy(manualMergeStrategy) + .manualMergeStrategy(manualMergeStrategy) .destination(destination) .sources(sources) .build(); diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java index 3e88e06..72f1ce1 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java @@ -65,7 +65,7 @@ public void visit(SubsystemItem item, int index) { @Override @SneakyThrows public void visit(ModuleItem item, int index) { - var moduleContext = BslContext.getCurrent().buildFilteredModuleContext(item.getModule()); + var moduleContext = BslContext.getCurrent().getModuleContext(item.getModule()); if (moduleContext.isEmpty()) { return; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java index 5cc0880..5a37cd7 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java @@ -4,6 +4,7 @@ import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.bsl.BslContext; +import ru.alkoleft.bsl.doc.bsl.helpers.BslFilter; @UtilityClass public class Factory { @@ -18,7 +19,7 @@ public Item createMDObjectItem(AbstractMDObjectBSL owner) { var item = new MDObjectItem(owner); owner.getModules() .stream() - .filter(Utils::isManagerModule) + .filter(BslFilter::checkModule) .map(ModuleItem::new) .forEach(item.getChildren()::add); return item; diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java index d5ceefa..687a9b4 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemsStructureBuilder.java @@ -9,8 +9,7 @@ public class SubsystemsStructureBuilder implements StructureBuilder { public List build(BslContext context) { - return context.getRootSubsystems() - .filter(it -> context.getFilter().getRootSubsystems().contains(it.getName())) + return context.getRootSubsystems(true) .map(it -> Factory.createSubSystemItem(it, context)) .collect(Collectors.toList()); } diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Utils.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Utils.java deleted file mode 100644 index acf749d..0000000 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/Utils.java +++ /dev/null @@ -1,21 +0,0 @@ -package ru.alkoleft.bsl.doc.structure; - -import com.github._1c_syntax.bsl.types.ModuleType; -import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; -import lombok.experimental.UtilityClass; - -import java.util.Set; - -@UtilityClass -public class Utils { - - Set moduleTypes = Set.of( - ModuleType.CommonModule, - ModuleType.ValueManagerModule, - ModuleType.ManagerModule - ); - - public boolean isManagerModule(MDOModule module) { - return moduleTypes.contains(module.getModuleType()); - } -} From 9347f1daa46b27e819ea99ea6e71a66c7e9a19ed Mon Sep 17 00:00:00 2001 From: alkoleft Date: Wed, 18 Oct 2023 01:03:58 +0300 Subject: [PATCH 17/27] Render template optomize --- .../doc/render/handlebars/RenderContext.java | 25 ++++++++++++++----- src/main/resources/confluence-md/module.hbs | 6 ++--- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java index 6c28f3e..00da7a2 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java @@ -3,9 +3,12 @@ import com.github.jknack.handlebars.Context; import com.github.jknack.handlebars.Handlebars; import com.github.jknack.handlebars.Template; +import com.github.jknack.handlebars.cache.ConcurrentMapTemplateCache; import com.github.jknack.handlebars.helper.ConditionalHelpers; +import com.github.jknack.handlebars.io.URLTemplateLoader; import lombok.SneakyThrows; import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.options.OutputOptions; import ru.alkoleft.bsl.doc.render.handlebars.helpers.Debugger; @@ -17,19 +20,29 @@ import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; +import java.net.URL; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; +@Slf4j public class RenderContext { - private final String path; + private final URL baseURL; private final Handlebars handlebars; private final Map loadedTemplates = new HashMap<>(); private final Links linksRender; private RenderContext(String path) { - this.path = path; - handlebars = new Handlebars().with(value -> value); + this.baseURL = getClass().getClassLoader().getResource(path); + handlebars = new Handlebars() + .with(new URLTemplateLoader() { + @Override + protected URL getResource(String location) throws IOException { + return new URL(baseURL + location); + } + }) + .with(new ConcurrentMapTemplateCache()); + handlebars.registerHelper("links", linksRender = new Links()); handlebars.registerHelper("mdo-present", new MdoPresent()); handlebars.registerHelper("shift", new Shifter()); @@ -59,12 +72,12 @@ public String render(String templateName, Context context) { return writer.toString(); } - private Template getTemplate(String name) throws IOException { + @SneakyThrows + private Template getTemplate(String name) { if (loadedTemplates.containsKey(name)) { return loadedTemplates.get(name); } - var location = String.format("%s/%s", path, name); - var template = handlebars.compile(location); + var template = handlebars.compile(name); loadedTemplates.put(name, template); return template; } diff --git a/src/main/resources/confluence-md/module.hbs b/src/main/resources/confluence-md/module.hbs index edfdd75..c089090 100644 --- a/src/main/resources/confluence-md/module.hbs +++ b/src/main/resources/confluence-md/module.hbs @@ -15,12 +15,12 @@ {{#each parameters as | parameter|}} * `{{parameter.name}}`{{#if required}} (**Обязательный**){{/if}} {{~#eq parameter.types.size 1~}} - {{~#each parameter.types as | type typeIndex|}} - {{#with type~}}{{#shift 3}}{{#block "confluence-md/value-definition"}}{{/block}}{{/shift}}{{~/with}} + {{~#each parameter.types as | type typeIndex|}} - {{#with type~}}{{#shift 3}}{{block "value-definition"}}{{/shift}}{{~/with}} {{~else}} - {{links description}} {{~/each}} {{else}} {{~#each parameter.types as | type typeIndex|}} - * {{#with type}}{{#shift 3}}{{#block "confluence-md/value-definition"}}{{/block}}{{/shift}}{{~/with}} + * {{#with type}}{{#shift 3}}{{block "value-definition"}}{{/shift}}{{~/with}} {{~else}} - {{links description}} {{~/each}} {{/eq}} @@ -30,7 +30,7 @@ *Возвращаемое значение* -{{#with returnedValue}}{{#block "confluence-md/value-definition"}}{{/block}}{{~/with}} +{{#with returnedValue}}{{block "value-definition"}}{{~/with}} {{~/if}} {{~#if examples}} From 6ba3c044b4262e2bec4509414202054e43a6cfaf Mon Sep 17 00:00:00 2001 From: alkoleft Date: Thu, 19 Oct 2023 02:43:58 +0300 Subject: [PATCH 18/27] migrate to new mdclasses and bsl-parser --- build.gradle.kts | 15 ++- .../ru/alkoleft/bsl/doc/bsl/BslContext.java | 57 ++++------- .../java/ru/alkoleft/bsl/doc/bsl/Links.java | 2 +- .../ru/alkoleft/bsl/doc/bsl/ModuleInfo.java | 8 +- .../bsl/doc/bsl/helpers/BslFilter.java | 9 +- .../bsl/doc/bsl/helpers/MDOHelper.java | 33 +++++++ .../bsl/doc/bsl/helpers/ModuleComputer.java | 52 +--------- .../doc/bsl/helpers/ModuleContextBuilder.java | 9 +- .../alkoleft/bsl/doc/bsl/helpers/Strings.java | 10 ++ .../bsl/doc/bsl/symbols/MethodSymbol.java | 10 +- .../doc/bsl/symbols/MethodSymbolComputer.java | 17 ++-- .../doc/bsl/symbols/ParameterDefinition.java | 9 +- .../doc/bsl/symbols/ParameterDescription.java | 2 +- .../alkoleft/bsl/doc/bsl/symbols/Trees.java | 94 +++++++++++++++++++ .../bsl/doc/bsl/symbols/TypeDescription.java | 2 +- .../alkoleft/bsl/doc/render/PathResolver.java | 3 +- .../bsl/doc/render/StructureRender.java | 3 +- .../doc/render/contexts/ContextFactory.java | 23 ++--- .../doc/render/contexts/SubsystemContext.java | 17 ++-- .../render/handlebars/helpers/MdoPresent.java | 17 +--- .../alkoleft/bsl/doc/structure/Factory.java | 21 +++-- .../bsl/doc/structure/MDObjectItem.java | 10 +- .../bsl/doc/structure/ModuleItem.java | 8 +- .../bsl/doc/structure/SubsystemItem.java | 8 +- .../bsl/doc/commands/RenderCommandTest.java | 13 +++ 25 files changed, 261 insertions(+), 191 deletions(-) create mode 100644 src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/MDOHelper.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/Strings.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/Trees.java diff --git a/build.gradle.kts b/build.gradle.kts index 5a9ce7c..565da56 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,6 +16,7 @@ repositories { mavenLocal() mavenCentral() maven(url = "https://jitpack.io") + maven(url = "https://s01.oss.sonatype.org/content/repositories/snapshots/") } java { @@ -33,14 +34,10 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-websocket") implementation("info.picocli:picocli-spring-boot-starter:4.7.1") - implementation("io.github.1c-syntax", "bsl-language-server", "0.20.0") - - implementation("com.github.1c-syntax", "mdclasses", "0.10.3") - implementation("io.github.1c-syntax", "bsl-common-library", "f6714e4e") - implementation("io.github.1c-syntax", "supportconf", "0.1.1") { - exclude("io.github.1c-syntax", "bsl-common-library") - } - implementation("com.github.1c-syntax", "bsl-parser", "167aaad827322e09ccde4658a71152dad234de4b") { + implementation("com.github.1c-syntax", "mdclasses", "develop-SNAPSHOT") + implementation("com.github.1c-syntax", "utils", "0.5.1") + implementation("io.github.1c-syntax", "supportconf", "0.12.1") + implementation("com.github.1c-syntax", "bsl-parser", "develop-SNAPSHOT") { exclude("com.tunnelvisionlabs", "antlr4-annotations") exclude("com.ibm.icu", "*") exclude("org.antlr", "ST4") @@ -49,6 +46,8 @@ dependencies { exclude("org.glassfish", "javax.json") } + implementation("commons-io", "commons-io", "2.14.0") + // template engine implementation("com.github.jknack:handlebars:4.3.1") diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java index 26efe28..1e2f7f1 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java @@ -1,13 +1,11 @@ package ru.alkoleft.bsl.doc.bsl; -import com.github._1c_syntax.bsl.types.MDOType; -import com.github._1c_syntax.mdclasses.Configuration; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; -import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; -import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; -import com.google.common.base.Strings; -import io.vavr.control.Either; +import com.github._1c_syntax.bsl.mdclasses.CF; +import com.github._1c_syntax.bsl.mdclasses.MDClasses; +import com.github._1c_syntax.bsl.mdo.MD; +import com.github._1c_syntax.bsl.mdo.Module; +import com.github._1c_syntax.bsl.mdo.ModuleOwner; +import com.github._1c_syntax.bsl.mdo.Subsystem; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import ru.alkoleft.bsl.doc.bsl.helpers.BslFilter; @@ -17,7 +15,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -26,34 +23,31 @@ public class BslContext { @Getter private static BslContext current; @Getter - private final Configuration configuration; - private final Set topObjectsType = Set.copyOf(MDOType.valuesWithoutChildren()); + private final CF configuration; private final ModuleContextBuilder builder; private List modules = Collections.emptyList(); public BslContext(Path path, Filter filter) { BslFilter.setFilter(filter); builder = new ModuleContextBuilder(); - configuration = Configuration.create(path); + configuration = (CF) MDClasses.createConfiguration(path); current = this; } - public Stream getModules() { + public Stream getModules() { return configuration.getChildren().stream() - .filter(AbstractMDObjectBSL.class::isInstance) - .map(AbstractMDObjectBSL.class::cast) + .filter(ModuleOwner.class::isInstance) + .map(ModuleOwner.class::cast) .flatMap(it -> it.getModules().stream()) .filter(BslFilter::checkModule); } - public ModuleInfo getModuleContext(MDOModule module) { + public ModuleInfo getModuleContext(Module module) { return builder.buildFilteredModuleContext(module); } - public Stream getRootSubsystems(boolean filtered) { - var stream = configuration.getOrderedTopMDObjects().get(MDOType.SUBSYSTEM) - .stream() - .map(MDSubsystem.class::cast); + public Stream getRootSubsystems(boolean filtered) { + var stream = configuration.getSubsystems().stream(); if (filtered) { stream = stream.filter(BslFilter::checkRootSubsystem); @@ -61,12 +55,8 @@ public Stream getRootSubsystems(boolean filtered) { return stream; } - public Stream getChildrenSubsystems(MDSubsystem parent) { - return parent.getChildren().stream() - .filter(Either::isRight) - .map(Either::get) - .filter(MDSubsystem.class::isInstance) - .map(MDSubsystem.class::cast); + public Stream getChildrenSubsystems(Subsystem parent) { + return parent.getSubsystems().stream(); } public boolean contains(String name) { @@ -77,18 +67,9 @@ public Optional getModule(String name) { return modules.stream().filter(it -> it.getName().equalsIgnoreCase(name)).findAny(); } - public Stream getSubsystemObjects(MDSubsystem subsystem) { + public Stream getSubsystemObjects(Subsystem subsystem) { - return configuration.getChildren() - .stream() - .filter(AbstractMDObjectBSL.class::isInstance) - .filter(this::isTopObject) - .filter(it -> it.getIncludedSubsystems().contains(subsystem)) - .map(AbstractMDObjectBSL.class::cast); - } - - boolean isTopObject(AbstractMDObjectBase obj) { - return topObjectsType.contains(obj.getMdoType()); + return subsystem.getChildren().stream(); } public void load() { @@ -98,7 +79,7 @@ public void load() { } public MethodInfo getMethodInfo(String link) { - if (Strings.isNullOrEmpty(link)) { + if (link == null || link.isEmpty()) { return null; } var linkInfo = Links.parseLink(link, false); diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/Links.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/Links.java index 2f2abbb..2f2ab6f 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/Links.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/Links.java @@ -1,9 +1,9 @@ package ru.alkoleft.bsl.doc.bsl; -import com.google.common.base.Strings; import lombok.AllArgsConstructor; import lombok.Value; import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.bsl.helpers.Strings; import java.util.regex.Pattern; diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleInfo.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleInfo.java index 5afe01c..b68d0e2 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleInfo.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/ModuleInfo.java @@ -1,7 +1,7 @@ package ru.alkoleft.bsl.doc.bsl; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; -import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; +import com.github._1c_syntax.bsl.mdo.MD; +import com.github._1c_syntax.bsl.mdo.Module; import lombok.Builder; import lombok.Value; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; @@ -12,8 +12,8 @@ @Builder @Value public class ModuleInfo { - AbstractMDObjectBSL owner; - MDOModule module; + MD owner; + Module module; List methods; String description; diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/BslFilter.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/BslFilter.java index d3c60c1..4ee6e9c 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/BslFilter.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/BslFilter.java @@ -1,8 +1,9 @@ package ru.alkoleft.bsl.doc.bsl.helpers; +import com.github._1c_syntax.bsl.mdo.Module; +import com.github._1c_syntax.bsl.mdo.Subsystem; import com.github._1c_syntax.bsl.types.ModuleType; -import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; -import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; +import com.github._1c_syntax.bsl.mdo.Module; import lombok.Getter; import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.bsl.Filter; @@ -49,7 +50,7 @@ public boolean checkModule(ModuleInfo module) { return true; } - public boolean checkModule(MDOModule module) { + public boolean checkModule(Module module) { return !filter.isOnlyCommonAndManagerModules() || moduleTypes.contains(module.getModuleType()); } @@ -65,7 +66,7 @@ public boolean checkRegion(MethodSymbol m) { return false; } - public boolean checkRootSubsystem(MDSubsystem subsystem) { + public boolean checkRootSubsystem(Subsystem subsystem) { if (filter.getRootSubsystems().isEmpty()) { return true; } else { diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/MDOHelper.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/MDOHelper.java new file mode 100644 index 0000000..dee6e13 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/MDOHelper.java @@ -0,0 +1,33 @@ +package ru.alkoleft.bsl.doc.bsl.helpers; + +import com.github._1c_syntax.bsl.mdo.CommonModule; +import com.github._1c_syntax.bsl.mdo.MD; +import com.github._1c_syntax.bsl.mdo.Module; +import com.github._1c_syntax.bsl.mdo.children.ObjectModule; +import com.github._1c_syntax.bsl.types.MdoReference; +import lombok.experimental.UtilityClass; +import ru.alkoleft.bsl.doc.bsl.BslContext; + +@UtilityClass +public class MDOHelper { + + public MD getOwner(Module module) { + if (module instanceof ObjectModule) { + var reference = ((ObjectModule) module).getOwner(); + return BslContext.getCurrent().getConfiguration().findChild(reference).orElse(null); + } else if (module instanceof CommonModule) { + return ((CommonModule) module); + } else { + return null; + } + } + + public String getPresent(MD object) { + if (object.getSynonym().getContent().isEmpty()) { + return object.getName(); + } + var content = object.getSynonym().getContent(); + var itr = content.values().iterator(); + return itr.next(); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleComputer.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleComputer.java index 8efce6c..3c8b895 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleComputer.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleComputer.java @@ -1,32 +1,24 @@ package ru.alkoleft.bsl.doc.bsl.helpers; -import com.github._1c_syntax.bsl.parser.BSLParser; import com.github._1c_syntax.bsl.parser.BSLTokenizer; import lombok.experimental.UtilityClass; import org.antlr.v4.runtime.Token; +import ru.alkoleft.bsl.doc.bsl.symbols.Trees; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Set; import java.util.stream.Collectors; @UtilityClass public class ModuleComputer { - private final Set VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH = Set.of( - BSLParser.LINE_COMMENT, - BSLParser.WHITE_SPACE, - BSLParser.AMPERSAND - ); - public String computeModuleDescription(BSLTokenizer tokenizer) { var token = tokenizer.getAst().getStart(); var isDescription = false; List comments = null; while (token != null && !isDescription) { - comments = getComments(tokenizer.getTokens(), token); + comments = Trees.getComments(tokenizer.getTokens(), token); isDescription = !comments.isEmpty() && comments.stream().map(Token::getText).map(it -> it.substring(2)).map(String::trim).noneMatch(it -> it.contains("Copyright") || it.contains("Экспортные")); token = comments.isEmpty() ? null : comments.get(0); } @@ -65,44 +57,4 @@ public String computeModuleDescription(BSLTokenizer tokenizer) { return ""; } } - - private List getComments(List tokens, Token token) { - List comments = new ArrayList<>(); - fillCommentsCollection(tokens, token, comments); - return comments; - } - - private void fillCommentsCollection(List tokens, Token currentToken, List lines) { - - int index = currentToken.getTokenIndex(); - - if (index == 0) { - return; - } - - var previousToken = tokens.get(index - 1); - - if (abortSearchComments(previousToken, currentToken)) { - return; - } - - fillCommentsCollection(tokens, previousToken, lines); - int type = previousToken.getType(); - if (type == BSLParser.LINE_COMMENT) { - lines.add(previousToken); - } - } - - private boolean abortSearchComments(Token previousToken, Token currentToken) { - int type = previousToken.getType(); - return !VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH.contains(type) || isBlankLine(previousToken, currentToken); - } - - private boolean isBlankLine(Token previousToken, Token currentToken) { - return previousToken.getType() == BSLParser.WHITE_SPACE - && (previousToken.getTokenIndex() == 0 - || (previousToken.getLine() + 1) != currentToken.getLine()); - } - - } diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleContextBuilder.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleContextBuilder.java index 2e9ff78..a5d1be7 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleContextBuilder.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/ModuleContextBuilder.java @@ -1,8 +1,7 @@ package ru.alkoleft.bsl.doc.bsl.helpers; +import com.github._1c_syntax.bsl.mdo.Module; import com.github._1c_syntax.bsl.parser.BSLTokenizer; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; -import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; import lombok.extern.slf4j.Slf4j; import ru.alkoleft.bsl.doc.bsl.ModuleInfo; import ru.alkoleft.bsl.doc.bsl.symbols.MethodSymbol; @@ -15,8 +14,8 @@ @Slf4j public class ModuleContextBuilder { - public ModuleInfo buildModuleContext(MDOModule bslModule) { - var owner = (AbstractMDObjectBSL) bslModule.getOwner(); + public ModuleInfo buildModuleContext(Module bslModule) { + var owner = MDOHelper.getOwner(bslModule); log.debug("Parse module: " + owner.getName() + "." + bslModule.getModuleType()); var srcPath = Path.of(bslModule.getUri()); List methods; @@ -39,7 +38,7 @@ public ModuleInfo buildModuleContext(MDOModule bslModule) { .build(); } - public ModuleInfo buildFilteredModuleContext(MDOModule bslModule) { + public ModuleInfo buildFilteredModuleContext(Module bslModule) { return buildModuleContext(buildModuleContext(bslModule)); } diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/Strings.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/Strings.java new file mode 100644 index 0000000..1cc7870 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/helpers/Strings.java @@ -0,0 +1,10 @@ +package ru.alkoleft.bsl.doc.bsl.helpers; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class Strings { + public boolean isNullOrEmpty(String value) { + return value == null || value.isEmpty(); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java index 5e433fa..09e247d 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbol.java @@ -1,14 +1,14 @@ package ru.alkoleft.bsl.doc.bsl.symbols; -import com.github._1c_syntax.bsl.languageserver.context.symbol.description.MethodDescription; -import com.google.common.base.Strings; +import com.github._1c_syntax.bsl.parser.description.MethodDescription; +import com.github._1c_syntax.bsl.parser.description.support.SimpleRange; import lombok.Builder; import lombok.Setter; import lombok.Value; import lombok.experimental.NonFinal; import lombok.extern.slf4j.Slf4j; -import org.eclipse.lsp4j.Range; import ru.alkoleft.bsl.doc.bsl.BslContext; +import ru.alkoleft.bsl.doc.bsl.helpers.Strings; import java.util.Collections; import java.util.List; @@ -25,7 +25,7 @@ public class MethodSymbol { Optional fullDescription; List parameters; - Range range; + SimpleRange range; @Setter @NonFinal RegionSymbol region; @@ -48,7 +48,7 @@ public TypeDescription getReturnedValue() { } } - private TypeDescription createTypeDescription(com.github._1c_syntax.bsl.languageserver.context.symbol.description.TypeDescription baseDescription) { + private TypeDescription createTypeDescription(com.github._1c_syntax.bsl.parser.description.support.TypeDescription baseDescription) { TypeDescription result = null; if (!Strings.isNullOrEmpty(baseDescription.getLink())) { var methodInfo = BslContext.getCurrent().getMethodInfo(baseDescription.getLink()); diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbolComputer.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbolComputer.java index 9c0dca9..ad961e3 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbolComputer.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/MethodSymbolComputer.java @@ -1,8 +1,8 @@ package ru.alkoleft.bsl.doc.bsl.symbols; -import com.github._1c_syntax.bsl.languageserver.context.symbol.description.MethodDescription; -import com.github._1c_syntax.bsl.languageserver.utils.Ranges; -import com.github._1c_syntax.bsl.languageserver.utils.Trees; +import com.github._1c_syntax.bsl.parser.description.BSLDescriptionReader; +import com.github._1c_syntax.bsl.parser.description.MethodDescription; +import com.github._1c_syntax.bsl.parser.description.support.SimpleRange; import com.github._1c_syntax.bsl.parser.BSLParser; import com.github._1c_syntax.bsl.parser.BSLParserBaseVisitor; import com.github._1c_syntax.bsl.parser.BSLTokenizer; @@ -10,7 +10,6 @@ import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.TerminalNode; -import org.eclipse.lsp4j.Range; import java.util.ArrayList; import java.util.Collection; @@ -36,7 +35,7 @@ public List compute(BSLTokenizer tokenizer) { // Используется постпривязка регионов, тк порядок обхода не соответствует порядку следования объект (в метод заходит раньше региона) for (var region : regionData) { for (var method : methods) { - if (Ranges.containsRange(region.range, method.getRange())) { + if (SimpleRange.containsRange(region.range, method.getRange())) { method.setRegion(region.region); } } @@ -68,7 +67,7 @@ public ParseTree visitRegionEnd(BSLParser.RegionEndContext ctx) { var regionData = regions.pop(); log.debug("End region: " + regionData.region.getName()); regionData.end = ctx; - regionData.range = Ranges.create(regionData.start, regionData.end); + regionData.range = SimpleRange.create(regionData.start.start, regionData.end.stop); } return super.visitRegionEnd(ctx); } @@ -105,7 +104,7 @@ private void handleMethod(TerminalNode startNode, Token subName, BSLParser.Param .fullDescription(description) .deprecated(deprecated) .parameters(createParameters(paramList, description)) - .range(Ranges.create(startNode)) + .range(SimpleRange.create(startNode.getSymbol(), startNode.getSymbol())) .build(); methods.add(method); } @@ -196,13 +195,13 @@ private Optional createDescription(Token token) { return Optional.empty(); } - return Optional.of(new MethodDescription(comments)); + return Optional.of(BSLDescriptionReader.parseMethodDescription(comments)); } private static class RegionData { RegionSymbol region; BSLParser.RegionStartContext start; BSLParser.RegionEndContext end; - Range range; + SimpleRange range; } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDefinition.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDefinition.java index 289c9e4..8657414 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDefinition.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDefinition.java @@ -1,6 +1,6 @@ package ru.alkoleft.bsl.doc.bsl.symbols; -import com.github._1c_syntax.bsl.languageserver.context.symbol.description.TypeDescription; +import com.github._1c_syntax.bsl.parser.description.support.TypeDescription; import lombok.Builder; import lombok.Value; @@ -18,13 +18,10 @@ public class ParameterDefinition { boolean byValue; public String getDescription() { - if (description.isEmpty()) { - return ""; - } - return description.get().getTypes() + return description.map(parameterDescription -> parameterDescription.getTypes() .stream() .findFirst() - .map(TypeDescription::getDescription).orElse(""); + .map(TypeDescription::getDescription).orElse("")).orElse(""); } public List getTypes() { diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDescription.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDescription.java index 85c7e57..81423e8 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDescription.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/ParameterDescription.java @@ -1,6 +1,6 @@ package ru.alkoleft.bsl.doc.bsl.symbols; -import com.github._1c_syntax.bsl.languageserver.context.symbol.description.TypeDescription; +import com.github._1c_syntax.bsl.parser.description.support.TypeDescription; import lombok.AllArgsConstructor; import lombok.Value; diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/Trees.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/Trees.java new file mode 100644 index 0000000..460d029 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/Trees.java @@ -0,0 +1,94 @@ +/* + * This file is a part of BSL Language Server. + * + * Copyright (c) 2018-2023 + * Alexey Sosnoviy , Nikita Fedkin and contributors + * + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * BSL Language Server is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * BSL Language Server is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with BSL Language Server. + */ + +// from https://github.com/1c-syntax/bsl-language-server/blob/develop/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/Trees.java + +package ru.alkoleft.bsl.doc.bsl.symbols; + +import com.github._1c_syntax.bsl.parser.BSLParser; +import lombok.experimental.UtilityClass; +import org.antlr.v4.runtime.Token; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +@UtilityClass +public class Trees { + private static final Set VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH = Set.of( + BSLParser.ANNOTATION_ATCLIENT_SYMBOL, + BSLParser.ANNOTATION_ATSERVERNOCONTEXT_SYMBOL, + BSLParser.ANNOTATION_ATCLIENTATSERVERNOCONTEXT_SYMBOL, + BSLParser.ANNOTATION_ATCLIENTATSERVER_SYMBOL, + BSLParser.ANNOTATION_ATSERVER_SYMBOL, + BSLParser.ANNOTATION_CUSTOM_SYMBOL, + BSLParser.ANNOTATION_UNKNOWN, + BSLParser.LINE_COMMENT, + BSLParser.WHITE_SPACE, + BSLParser.AMPERSAND + ); + + /** + * Поиск комментариев назад от указанного токена + * + * @param tokens - список токенов DocumentContext + * @param token - токен, для которого требуется найти комментарии + * @return - список найденных комментариев lines + */ + public static List getComments(List tokens, Token token) { + List comments = new ArrayList<>(); + fillCommentsCollection(tokens, token, comments); + return comments; + } + + private static void fillCommentsCollection(List tokens, Token currentToken, List lines) { + + int index = currentToken.getTokenIndex(); + + if (index == 0) { + return; + } + + var previousToken = tokens.get(index - 1); + + if (abortSearchComments(previousToken, currentToken)) { + return; + } + + fillCommentsCollection(tokens, previousToken, lines); + int type = previousToken.getType(); + if (type == BSLParser.LINE_COMMENT) { + lines.add(previousToken); + } + } + + private static boolean abortSearchComments(Token previousToken, Token currentToken) { + int type = previousToken.getType(); + return !VALID_TOKEN_TYPES_FOR_COMMENTS_SEARCH.contains(type) || isBlankLine(previousToken, currentToken); + } + + private static boolean isBlankLine(Token previousToken, Token currentToken) { + return previousToken.getType() == BSLParser.WHITE_SPACE + && (previousToken.getTokenIndex() == 0 + || (previousToken.getLine() + 1) != currentToken.getLine()); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/TypeDescription.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/TypeDescription.java index f55df7c..91a6ac5 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/TypeDescription.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/TypeDescription.java @@ -1,6 +1,6 @@ package ru.alkoleft.bsl.doc.bsl.symbols; -import com.github._1c_syntax.bsl.languageserver.context.symbol.description.ParameterDescription; +import com.github._1c_syntax.bsl.parser.description.support.ParameterDescription; import lombok.AllArgsConstructor; import lombok.Value; diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/PathResolver.java b/src/main/java/ru/alkoleft/bsl/doc/render/PathResolver.java index 6161cca..d5dc9cf 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/PathResolver.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/PathResolver.java @@ -1,9 +1,8 @@ package ru.alkoleft.bsl.doc.render; -import com.github._1c_syntax.utils.Lazy; import lombok.AllArgsConstructor; import ru.alkoleft.bsl.doc.options.OutputFormat; - +import com.github._1c_syntax.utils.Lazy; import java.nio.file.Path; import java.util.Stack; diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java index 72f1ce1..1106d3a 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java @@ -2,6 +2,7 @@ import lombok.SneakyThrows; import ru.alkoleft.bsl.doc.bsl.BslContext; +import ru.alkoleft.bsl.doc.bsl.helpers.MDOHelper; import ru.alkoleft.bsl.doc.model.ContentModel; import ru.alkoleft.bsl.doc.model.PageType; import ru.alkoleft.bsl.doc.render.contexts.ContextFactory; @@ -69,7 +70,7 @@ public void visit(ModuleItem item, int index) { if (moduleContext.isEmpty()) { return; } - var path = pathResolver.getFilePath(item.getModule().getOwner().getName()); + var path = pathResolver.getFilePath(MDOHelper.getOwner(item.getModule()).getName()); if (!Files.exists(path.getParent())) { Files.createDirectories(path.getParent()); } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java index 9a64138..f83c6b6 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/ContextFactory.java @@ -1,9 +1,9 @@ package ru.alkoleft.bsl.doc.render.contexts; +import com.github._1c_syntax.bsl.mdo.CommonModule; +import com.github._1c_syntax.bsl.mdo.MD; +import com.github._1c_syntax.bsl.mdo.Subsystem; import com.github._1c_syntax.bsl.types.ModuleType; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; -import com.github._1c_syntax.mdclasses.mdo.MDCommonModule; -import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; import com.github.jknack.handlebars.Context; import com.github.jknack.handlebars.context.FieldValueResolver; import com.github.jknack.handlebars.context.JavaBeanValueResolver; @@ -11,6 +11,7 @@ import com.github.jknack.handlebars.context.MethodValueResolver; import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.bsl.ModuleInfo; +import ru.alkoleft.bsl.doc.bsl.helpers.MDOHelper; @UtilityClass public class ContextFactory { @@ -19,8 +20,8 @@ public ModuleContext create(ModuleInfo module, int index) { return ModuleContext.builder() .index(index) .name(module.getOwner().getName()) - .present(getPresent(module.getOwner())) - .isCommonModule(module.getOwner() instanceof MDCommonModule) + .present(MDOHelper.getPresent(module.getOwner())) + .isCommonModule(module.getOwner() instanceof CommonModule) .ownerType(module.getOwner().getMdoType().getNameRu()) .moduleType(getPresent(module.getModule().getModuleType())) .methods(module.getMethods()) @@ -28,25 +29,17 @@ public ModuleContext create(ModuleInfo module, int index) { .build(); } - public SubsystemContext create(MDSubsystem subsystem, int index, int level) { + public SubsystemContext create(Subsystem subsystem, int index, int level) { return SubsystemContext.builder() .subsystem(subsystem) .index(index) .name(subsystem.getName()) - .present(getPresent(subsystem)) + .present(MDOHelper.getPresent(subsystem)) .description(subsystem.getComment()) .level(level) .build(); } - private String getPresent(AbstractMDObjectBase object) { - if (object.getSynonyms().isEmpty()) { - return object.getName(); - } else { - return object.getSynonyms().get(0).getContent(); - } - } - public Context createContext(Object obj) { return Context.newBuilder(obj) .resolver( diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java index 5394a1d..ed2d789 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/SubsystemContext.java @@ -1,7 +1,7 @@ package ru.alkoleft.bsl.doc.render.contexts; -import com.github._1c_syntax.mdclasses.mdo.MDConstant; -import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import com.github._1c_syntax.bsl.mdo.Constant; +import com.github._1c_syntax.bsl.mdo.Subsystem; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -19,23 +19,22 @@ @Getter public class SubsystemContext extends BaseContext { private final int level; - private final MDSubsystem subsystem; + private final Subsystem subsystem; @Setter private ContentModel contentModel; @Builder - public SubsystemContext(int index, String name, String present, String description, Path outputPath, int level, MDSubsystem subsystem) { + public SubsystemContext(int index, String name, String present, String description, Path outputPath, int level, Subsystem subsystem) { super(index, name, present, description, outputPath); this.level = level; this.subsystem = subsystem; } - public List getConstants() { - var c = BslContext.getCurrent().getSubsystemObjects(subsystem) - .filter(MDConstant.class::isInstance) - .map(MDConstant.class::cast) + public List getConstants() { + return BslContext.getCurrent().getSubsystemObjects(subsystem) + .filter(Constant.class::isInstance) + .map(Constant.class::cast) .collect(Collectors.toList()); - return c; } public List getChildrenPages() { diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/MdoPresent.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/MdoPresent.java index a040101..f969caf 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/MdoPresent.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/MdoPresent.java @@ -1,8 +1,9 @@ package ru.alkoleft.bsl.doc.render.handlebars.helpers; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; +import com.github._1c_syntax.bsl.mdo.MD; import com.github.jknack.handlebars.Helper; import com.github.jknack.handlebars.Options; +import ru.alkoleft.bsl.doc.bsl.helpers.MDOHelper; import ru.alkoleft.bsl.doc.render.contexts.SubsystemContext; import java.io.IOException; @@ -10,20 +11,12 @@ public class MdoPresent implements Helper { @Override public Object apply(Object context, Options options) throws IOException { - if (context instanceof AbstractMDObjectBase) { - return getPresent((AbstractMDObjectBase) context); + if (context instanceof MD) { + return MDOHelper.getPresent((MD) context); } else if (context instanceof SubsystemContext) { - return getPresent(((SubsystemContext) context).getSubsystem()); + return MDOHelper.getPresent(((SubsystemContext) context).getSubsystem()); } else { return context.toString(); } } - - private String getPresent(AbstractMDObjectBase object) { - if (object.getSynonyms().isEmpty()) { - return object.getName(); - } else { - return object.getSynonyms().get(0).getContent(); - } - } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java b/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java index 5a37cd7..52f6492 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/Factory.java @@ -1,27 +1,30 @@ package ru.alkoleft.bsl.doc.structure; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBSL; -import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import com.github._1c_syntax.bsl.mdo.MD; +import com.github._1c_syntax.bsl.mdo.ModuleOwner; +import com.github._1c_syntax.bsl.mdo.Subsystem; import lombok.experimental.UtilityClass; import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.bsl.helpers.BslFilter; @UtilityClass public class Factory { - public Item createSubSystemItem(MDSubsystem subsystem, BslContext context) { + public Item createSubSystemItem(Subsystem subsystem, BslContext context) { var item = new SubsystemItem(subsystem); fillChildrenSubsystems(item, context); fillChildrenObjects(item, context); return item; } - public Item createMDObjectItem(AbstractMDObjectBSL owner) { + public Item createMDObjectItem(MD owner) { var item = new MDObjectItem(owner); - owner.getModules() - .stream() - .filter(BslFilter::checkModule) - .map(ModuleItem::new) - .forEach(item.getChildren()::add); + if (owner instanceof ModuleOwner) { + ((ModuleOwner) owner).getModules() + .stream() + .filter(BslFilter::checkModule) + .map(ModuleItem::new) + .forEach(item.getChildren()::add); + } return item; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/MDObjectItem.java b/src/main/java/ru/alkoleft/bsl/doc/structure/MDObjectItem.java index f05d016..8cc6ddc 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/MDObjectItem.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/MDObjectItem.java @@ -1,15 +1,15 @@ package ru.alkoleft.bsl.doc.structure; -import com.github._1c_syntax.mdclasses.mdo.AbstractMDObjectBase; +import com.github._1c_syntax.bsl.mdo.MD; public class MDObjectItem extends Item { - public MDObjectItem(AbstractMDObjectBase object) { + public MDObjectItem(MD object) { super(object, object.getName()); } @Override public String getPresent() { - var mdo = (AbstractMDObjectBase) getObject(); + var mdo = getMDObject(); return String.format("%s.%s", mdo.getMdoType().name(), mdo.getName()); } @@ -17,4 +17,8 @@ public String getPresent() { public void accept(StructureVisitor visitor, int index) { visitor.visit(this, index); } + + public MD getMDObject() { + return (MD) getObject(); + } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/ModuleItem.java b/src/main/java/ru/alkoleft/bsl/doc/structure/ModuleItem.java index 6d703b9..9d06374 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/ModuleItem.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/ModuleItem.java @@ -1,14 +1,14 @@ package ru.alkoleft.bsl.doc.structure; -import com.github._1c_syntax.mdclasses.mdo.support.MDOModule; +import com.github._1c_syntax.bsl.mdo.Module; public class ModuleItem extends Item { - public ModuleItem(MDOModule module) { + public ModuleItem(Module module) { super(module, module.getModuleType().name()); } - public MDOModule getModule() { - return (MDOModule) getObject(); + public Module getModule() { + return (Module) getObject(); } @Override diff --git a/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java index 74b750c..debd118 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java +++ b/src/main/java/ru/alkoleft/bsl/doc/structure/SubsystemItem.java @@ -1,9 +1,9 @@ package ru.alkoleft.bsl.doc.structure; -import com.github._1c_syntax.mdclasses.mdo.MDSubsystem; +import com.github._1c_syntax.bsl.mdo.Subsystem; public class SubsystemItem extends Item { - public SubsystemItem(MDSubsystem subsystem) { + public SubsystemItem(Subsystem subsystem) { super(subsystem, subsystem.getName()); } @@ -12,7 +12,7 @@ public void accept(StructureVisitor visitor, int index) { visitor.visit(this, index); } - public MDSubsystem getSubsystem() { - return (MDSubsystem) getObject(); + public Subsystem getSubsystem() { + return (Subsystem) getObject(); } } diff --git a/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java index 475f009..04366eb 100644 --- a/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java +++ b/src/test/java/ru/alkoleft/bsl/doc/commands/RenderCommandTest.java @@ -25,6 +25,19 @@ void run() { .run(); } + @Test + void runYaxUnit() { + RenderCommand.builder() + .sources(Path.of("/home/alko/develop/bia/orais/yaxunit/exts/yaxunit")) + .destination(Path.of("/tmp/bsl-doc-yaxunit")) + .format(OutputFormat.ConfluenceMarkdown) + .onlySubsystems(List.of("ЮТДвижок")) + .regions(List.of(RegionSymbol.PUBLIC_REGION_RU)) + .manualMergeStrategy(ManualMergeStrategy.MERGE) + .build() + .run(); + } + @SneakyThrows private Path getResource(String name) { return Path.of(getClass().getClassLoader().getResource(name).toURI()); From f39f34c19634d242aaf15a4fde290799d7e01273 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Thu, 19 Oct 2023 02:45:36 +0300 Subject: [PATCH 19/27] remove spring - lightweight jar --- build.gradle.kts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 565da56..eaaf8e0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,10 +29,7 @@ java.sourceSets["main"].java { } dependencies { - // spring - implementation("org.springframework.boot:spring-boot-starter") - implementation("org.springframework.boot:spring-boot-starter-websocket") - implementation("info.picocli:picocli-spring-boot-starter:4.7.1") + implementation("info.picocli", "picocli", "4.7.5") implementation("com.github.1c-syntax", "mdclasses", "develop-SNAPSHOT") implementation("com.github.1c-syntax", "utils", "0.5.1") From 010345183368c9e8cd9d5a48006dc26189338ae1 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Thu, 19 Oct 2023 03:12:39 +0300 Subject: [PATCH 20/27] configure dependencies --- build.gradle.kts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index eaaf8e0..cc80838 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,9 +33,11 @@ dependencies { implementation("com.github.1c-syntax", "mdclasses", "develop-SNAPSHOT") implementation("com.github.1c-syntax", "utils", "0.5.1") + implementation("io.github.1c-syntax", "bsl-common-library", "0.5.0") implementation("io.github.1c-syntax", "supportconf", "0.12.1") implementation("com.github.1c-syntax", "bsl-parser", "develop-SNAPSHOT") { exclude("com.tunnelvisionlabs", "antlr4-annotations") + exclude("commons-beanutils", "commons-beanutils") exclude("com.ibm.icu", "*") exclude("org.antlr", "ST4") exclude("org.abego.treelayout", "org.abego.treelayout.core") @@ -44,6 +46,7 @@ dependencies { } implementation("commons-io", "commons-io", "2.14.0") + implementation("ch.qos.logback", "logback-classic", "1.4.11") // template engine implementation("com.github.jknack:handlebars:4.3.1") From d2fefce3f17796403bae587b398d33af694d1642 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Fri, 20 Oct 2023 00:23:43 +0300 Subject: [PATCH 21/27] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE?= =?UTF-8?q?=D0=BA=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=D0=B0=20=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BE?= =?UTF-8?q?=D1=87=D0=B5=D1=80=D0=BD=D0=B8=D1=85=20=D1=8D=D0=BB=D0=B5=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D0=BE=D0=B2=20=D0=BF=D0=BE=D0=B4=D1=81=D0=B8?= =?UTF-8?q?=D1=81=D1=82=D0=B5=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/alkoleft/bsl/doc/bsl/BslContext.java | 6 ++-- src/main/resources/confluence-md/module.hbs | 8 ++--- .../confluence-md/value-definition.hbs | 4 +-- .../Module.bsl" | 34 ++++++++++++++++++- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java index 1e2f7f1..e1d5764 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/BslContext.java @@ -68,8 +68,10 @@ public Optional getModule(String name) { } public Stream getSubsystemObjects(Subsystem subsystem) { - - return subsystem.getChildren().stream(); + return subsystem.getContent().stream() + .map(configuration::findChild) + .filter(Optional::isPresent) + .map(Optional::get); } public void load() { diff --git a/src/main/resources/confluence-md/module.hbs b/src/main/resources/confluence-md/module.hbs index c089090..3b8f949 100644 --- a/src/main/resources/confluence-md/module.hbs +++ b/src/main/resources/confluence-md/module.hbs @@ -15,12 +15,12 @@ {{#each parameters as | parameter|}} * `{{parameter.name}}`{{#if required}} (**Обязательный**){{/if}} {{~#eq parameter.types.size 1~}} - {{~#each parameter.types as | type typeIndex|}} - {{#with type~}}{{#shift 3}}{{block "value-definition"}}{{/shift}}{{~/with}} - {{~else}} - {{links description}} + {{~#each parameter.types as | type typeIndex|}} - {{#with type~}}{{#shift 3}}{{#block "value-definition"}}{{/block}}{{/shift}}{{~/with}} + {{~else}} - {{links description}} {{~/each}} {{else}} {{~#each parameter.types as | type typeIndex|}} - * {{#with type}}{{#shift 3}}{{block "value-definition"}}{{/shift}}{{~/with}} + * {{#with type}}{{#shift 3}}{{#block "value-definition"}}{{/block}}{{/shift}}{{~/with}} {{~else}} - {{links description}} {{~/each}} {{/eq}} @@ -30,7 +30,7 @@ *Возвращаемое значение* -{{#with returnedValue}}{{block "value-definition"}}{{~/with}} +{{#with returnedValue}}{{#block "value-definition"}}{{/block}}{{~/with}} {{~/if}} {{~#if examples}} diff --git a/src/main/resources/confluence-md/value-definition.hbs b/src/main/resources/confluence-md/value-definition.hbs index e25410b..221172c 100644 --- a/src/main/resources/confluence-md/value-definition.hbs +++ b/src/main/resources/confluence-md/value-definition.hbs @@ -5,7 +5,7 @@ `{{name}}` - {{description}} {{#each parameters as |parameter| }}{{#with parameter}} -{{~#shift}}* `{{name}}` - {{#each types as | type|~}}{{#with type}}{{#block "confluence-md/value-definition"}}{{/block}}{{/with}}{{~/each}}{{/shift}} +{{~#shift}}* `{{name}}` - {{#each types as | type|~}}{{#with type}}{{#block "value-definition"}}{{/block}}{{/with}}{{~/each}}{{/shift}} {{/with}}{{/each}} -{{~else}}`{{name}}` - {{#links description}}{{#block "confluence-md/value-definition"}}{{/block}}{{/links}} +{{~else}}`{{name}}` - {{#links description}}{{#block "value-definition"}}{{/block}}{{/links}} {{~/if}} \ No newline at end of file diff --git "a/src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/Module.bsl" "b/src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/Module.bsl" index 01c32bd..1cde5fd 100644 --- "a/src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/Module.bsl" +++ "b/src/test/resources/configuration/src/CommonModules/\320\241\321\202\321\200\320\276\320\272\320\276\320\262\321\213\320\265\320\244\321\203\320\275\320\272\321\206\320\270\320\270/Module.bsl" @@ -42,4 +42,36 @@ КонецФункции -#КонецОбласти \ No newline at end of file +// РазложитьСтрокуВКоллекцию +// раскладывает строку с разделителями в указанную коллекцию +// +// Параметры: +// ВходнаяСтрока - Строка - строка с разделителями +// ВидКоллекции - Строка - имя коллекции +// доступные варианты "Массив", "ФиксированныйМассив", "СписокЗначений" +// Разделитель - Строка - разделитель входной строки +// УдалятьКонцевыеПробелы - Булево - удаление концевых пробелов разложенных строк +// +// Возвращаемое значение: +// Массив, СписокЗначений, ФиксированныйМассив - "заказанная" коллекция +// +Функция РазложитьСтрокуВКоллекцию(Знач ВходнаяСтрока, ВидКоллекции = "Массив", Разделитель = ",", УдалятьКонцевыеПробелы = Ложь) Экспорт + +КонецФункции // РазложитьСтрокуВКоллекцию + +// ПолучитьПараметрыВхожденияСтроки +// Производит поиск в исходной строке вхождений искомой строки +// +// Параметры: +// ИсходнаяСтрока - Строка - Анализируемая строка +// СтрокаПоиска - Строка - Искомая строка +// +// Возвращаемое значение: +// Массив Из Структура - Результат метода: +// * НомерСимвола - Число - начало строки вхождения +// * ДлинаСтроки - Число - длина строки вхождения +// +Функция ПолучитьПараметрыВхожденияСтроки(ИсходнаяСтрока, СтрокаПоиска) Экспорт +КонецФункции + +#КонецОбласти From 4da8a8a9e442b123bcc35cff40ea241b31bf4d8c Mon Sep 17 00:00:00 2001 From: alkoleft Date: Fri, 20 Oct 2023 01:09:46 +0300 Subject: [PATCH 22/27] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20?= =?UTF-8?q?=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=D0=B0,=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=B0=20=D1=81=D0=BE=20=D1=81=D1=81=D1=8B?= =?UTF-8?q?=D0=BB=D0=BA=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alkoleft/bsl/doc/model/ContentModel.java | 12 ++++++++++- .../java/ru/alkoleft/bsl/doc/model/Links.java | 20 ++++++++++++++++++ .../bsl/doc/render/StructureRender.java | 12 +++-------- .../bsl/doc/render/contexts/BaseContext.java | 2 -- .../doc/render/handlebars/RenderContext.java | 7 +++++-- .../render/handlebars/helpers/PageLink.java | 15 +++++++++++++ src/main/resources/confluence-md/module.hbs | 21 +++++++------------ .../resources/confluence-md/subsystem.hbs | 12 +++++------ ...0\260\320\264\320\275\321\213\320\265.mdo" | 2 +- ...0\270\321\201\320\275\321\213\320\265.mdo" | 2 +- .../index.md" | 2 +- 11 files changed, 71 insertions(+), 36 deletions(-) create mode 100644 src/main/java/ru/alkoleft/bsl/doc/model/Links.java create mode 100644 src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/PageLink.java diff --git a/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java index 24717ab..0198fdf 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java +++ b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java @@ -4,6 +4,7 @@ import java.nio.file.Path; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -12,12 +13,21 @@ public class ContentModel { List pages = new ArrayList<>(); public void append(Path path, PageType type) { - pages.add(new Page(path, null, type)); + var page = pages.stream() + .filter(it -> path.equals(it.getPath())) + .findAny(); + + if (page.isEmpty()) { + pages.add(new Page(path, null, type)); + } else { + page.get().setType(type); + } } public List getChildrenPages(Path path) { return pages.stream() .filter(it -> isChild(it, path)) + .sorted(Comparator.comparing(Page::getPath)) .collect(Collectors.toList()); } diff --git a/src/main/java/ru/alkoleft/bsl/doc/model/Links.java b/src/main/java/ru/alkoleft/bsl/doc/model/Links.java new file mode 100644 index 0000000..c2b0db6 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/model/Links.java @@ -0,0 +1,20 @@ +package ru.alkoleft.bsl.doc.model; + +import lombok.Setter; +import lombok.experimental.UtilityClass; + +import java.nio.file.Path; + +@UtilityClass +public class Links { + @Setter + private Path currentPath; + + public String getPageLink(Page from, Page to) { + return from.getPath().relativize(to.getPath()).toString(); + } + + public String getPageLink(Page to) { + return currentPath.getParent().relativize(to.getPath()).toString(); + } +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java index 1106d3a..c9c2921 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java @@ -4,6 +4,7 @@ import ru.alkoleft.bsl.doc.bsl.BslContext; import ru.alkoleft.bsl.doc.bsl.helpers.MDOHelper; import ru.alkoleft.bsl.doc.model.ContentModel; +import ru.alkoleft.bsl.doc.model.Links; import ru.alkoleft.bsl.doc.model.PageType; import ru.alkoleft.bsl.doc.render.contexts.ContextFactory; import ru.alkoleft.bsl.doc.render.output.OutputStrategy; @@ -15,14 +16,11 @@ import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.Stack; public class StructureRender implements StructureVisitor { private final OutputStrategy outputStrategy; - private final Stack> children = new Stack<>(); private final ContentModel contentModel; private boolean withRoot = false; private int subsystemLevel = 0; @@ -36,11 +34,9 @@ public StructureRender(OutputStrategy outputStrategy, ContentModel contentModel) public void render(List structure, Path destination) { pathResolver = new PathResolver(destination, outputStrategy.getFormat()); - children.clear(); subsystemLevel = 0; withRoot = structure.size() > 1; - children.push(new ArrayList<>()); for (int i = 0; i < structure.size(); i++) { structure.get(i).accept(this, i); } @@ -50,7 +46,6 @@ public void render(List structure, Path destination) { public void visit(SubsystemItem item, int index) { var isRoot = subsystemLevel == 0; subsystemLevel++; - children.push(new ArrayList<>()); if (!withRoot && isRoot) { item.accentChildren(this); renderSubsystemPage(item); @@ -74,10 +69,8 @@ public void visit(ModuleItem item, int index) { if (!Files.exists(path.getParent())) { Files.createDirectories(path.getParent()); } - children.peek().add(path); if (outputStrategy.needRender(path)) { - var context = ContextFactory.create(moduleContext, index); - + Links.setCurrentPath(path); var content = BslRender.renderModule(moduleContext, index); outputStrategy.save(path, content); contentModel.append(path, PageType.MODULE); @@ -96,6 +89,7 @@ private void renderSubsystemPage(SubsystemItem item) { var context = ContextFactory.create(item.getSubsystem(), 0, subsystemLevel); context.setContentModel(contentModel); context.setOutputPath(path.getParent()); + Links.setCurrentPath(path); var content = BslRender.renderSubsystem(context); outputStrategy.save(path, content); contentModel.append(path, PageType.SUBSYSTEM); diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/BaseContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/BaseContext.java index c6ed9ef..758b2f1 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/contexts/BaseContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/contexts/BaseContext.java @@ -1,6 +1,5 @@ package ru.alkoleft.bsl.doc.render.contexts; - import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -8,7 +7,6 @@ import java.nio.file.Path; - @Getter @AllArgsConstructor @EqualsAndHashCode diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java index 00da7a2..2ea04c4 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/RenderContext.java @@ -14,6 +14,7 @@ import ru.alkoleft.bsl.doc.render.handlebars.helpers.Debugger; import ru.alkoleft.bsl.doc.render.handlebars.helpers.Links; import ru.alkoleft.bsl.doc.render.handlebars.helpers.MdoPresent; +import ru.alkoleft.bsl.doc.render.handlebars.helpers.PageLink; import ru.alkoleft.bsl.doc.render.handlebars.helpers.Shifter; import ru.alkoleft.bsl.doc.render.handlebars.helpers.SingleLine; @@ -43,13 +44,15 @@ protected URL getResource(String location) throws IOException { }) .with(new ConcurrentMapTemplateCache()); + handlebars.registerHelper("great", ConditionalHelpers.gt); + handlebars.registerHelper("eq", ConditionalHelpers.eq); + handlebars.registerHelper("links", linksRender = new Links()); handlebars.registerHelper("mdo-present", new MdoPresent()); handlebars.registerHelper("shift", new Shifter()); handlebars.registerHelper("debug", new Debugger()); handlebars.registerHelper("single-line", new SingleLine()); - handlebars.registerHelper("great", ConditionalHelpers.gt); - handlebars.registerHelper("eq", ConditionalHelpers.eq); + handlebars.registerHelper("page-link", new PageLink()); } public void setContext(BslContext context) { diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/PageLink.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/PageLink.java new file mode 100644 index 0000000..c60ad19 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/PageLink.java @@ -0,0 +1,15 @@ +package ru.alkoleft.bsl.doc.render.handlebars.helpers; + +import com.github.jknack.handlebars.Helper; +import com.github.jknack.handlebars.Options; +import ru.alkoleft.bsl.doc.model.Links; +import ru.alkoleft.bsl.doc.model.Page; + +import java.io.IOException; + +public class PageLink implements Helper { + @Override + public Object apply(Page context, Options options) throws IOException { + return Links.getPageLink(context); + } +} diff --git a/src/main/resources/confluence-md/module.hbs b/src/main/resources/confluence-md/module.hbs index 3b8f949..2b2d222 100644 --- a/src/main/resources/confluence-md/module.hbs +++ b/src/main/resources/confluence-md/module.hbs @@ -15,26 +15,23 @@ {{#each parameters as | parameter|}} * `{{parameter.name}}`{{#if required}} (**Обязательный**){{/if}} {{~#eq parameter.types.size 1~}} - {{~#each parameter.types as | type typeIndex|}} - {{#with type~}}{{#shift 3}}{{#block "value-definition"}}{{/block}}{{/shift}}{{~/with}} + {{~#each parameter.types as | type typeIndex|}} - {{#with type~}}{{#shift 1}}{{#block "value-definition"}}{{/block}}{{/shift}}{{~/with}} {{~else}} - {{links description}} {{~/each}} - {{else}} - {{~#each parameter.types as | type typeIndex|}} - * {{#with type}}{{#shift 3}}{{#block "value-definition"}}{{/block}}{{/shift}}{{~/with}} + {{~else~}} +{{~#each parameter.types as | type typeIndex|}} + * {{#with type}}{{#shift 1}}{{#block "value-definition"}}{{/block}}{{/shift}}{{~/with}} {{~else}} - {{links description}} - {{~/each}} - {{/eq}} +{{~/each}} + {{~/eq}} {{~/each}} {{~/if}} {{~#if returnedValue}} *Возвращаемое значение* - -{{#with returnedValue}}{{#block "value-definition"}}{{/block}}{{~/with}} +{{~#with returnedValue}}{{#block "value-definition"}}{{/block}}{{~/with}} {{~/if}} - {{~#if examples}} - Примеры: ```bsl @@ -42,7 +39,5 @@ {{this}} {{~/each}} ``` - {{/if}} - -{{/each}} \ No newline at end of file +{{~/each}} \ No newline at end of file diff --git a/src/main/resources/confluence-md/subsystem.hbs b/src/main/resources/confluence-md/subsystem.hbs index afb5bfd..d2a8169 100644 --- a/src/main/resources/confluence-md/subsystem.hbs +++ b/src/main/resources/confluence-md/subsystem.hbs @@ -1,14 +1,14 @@ # {{#great level 1}}Подсистема {{/great}}{{present}} {{#if description}} {{description}} -{{/if}} - -Константы: +{{~/if}} +{{~#if constants}}Константы: {{#each constants as | item|}} * {{mdo-present item}} ({{item.name}}) -{{/each}} +{{~/each}} +{{~/if}} Содержимое: {{#each childrenPages as | item|}} -* [{{item.title}}]({{item.path}}) -{{/each}} \ No newline at end of file +* [{{item.title}}]({{page-link item}}) +{{~/each}} diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265.mdo" index 9f6bb13..4049130 100644 --- "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265.mdo" +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265.mdo" @@ -3,7 +3,7 @@ Прикладные ru - Прикладные + Прикладные объекты true true diff --git "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265.mdo" "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265.mdo" index 7fc6cd1..690fea9 100644 --- "a/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265.mdo" +++ "b/src/test/resources/configuration/src/Subsystems/\320\237\320\237\320\230/Subsystems/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265/\320\241\320\265\321\200\320\262\320\270\321\201\320\275\321\213\320\265.mdo" @@ -3,7 +3,7 @@ Сервисные ru - Раздел 1 + Сервисные методы true true diff --git "a/src/test/resources/docs/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/index.md" "b/src/test/resources/docs/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/index.md" index 61b54a7..5a84a5a 100644 --- "a/src/test/resources/docs/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/index.md" +++ "b/src/test/resources/docs/\320\237\321\200\320\270\320\272\320\273\320\260\320\264\320\275\321\213\320\265/index.md" @@ -1,4 +1,4 @@ -# Раздел 1 +# Прикладные объекты Основной раздел системы From d2f007ad2f00ff7c13b471263710a9106bc45b64 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Fri, 20 Oct 2023 01:34:27 +0300 Subject: [PATCH 23/27] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D0=BD=D0=B5?= =?UTF-8?q?=D0=B4=D0=BE=D1=87=D0=B5=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alkoleft/bsl/doc/bsl/symbols/Trees.java | 8 ++++++- .../doc/render/handlebars/helpers/Links.java | 23 ++++++++++--------- src/main/resources/confluence-md/module.hbs | 2 +- .../resources/confluence-md/subsystem.hbs | 8 ++++--- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/Trees.java b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/Trees.java index 460d029..dbebb2b 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/Trees.java +++ b/src/main/java/ru/alkoleft/bsl/doc/bsl/symbols/Trees.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; @UtilityClass public class Trees { @@ -57,7 +58,12 @@ public class Trees { public static List getComments(List tokens, Token token) { List comments = new ArrayList<>(); fillCommentsCollection(tokens, token, comments); - return comments; + return comments.stream() + .filter(it -> { + var text = it.getText(); + return !text.startsWith("// @skip") && !text.startsWith("// BSLLS:"); + }) + .collect(Collectors.toList()); } private static void fillCommentsCollection(List tokens, Token currentToken, List lines) { diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Links.java b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Links.java index 67d402c..b23413c 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Links.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/handlebars/helpers/Links.java @@ -20,17 +20,18 @@ public class Links implements Helper { @Override public Object apply(String context, Options options) { - var matcher = linkPattern.matcher(context); - String result; - if (matcher.find()) { - result = matcher.replaceAll(matchResult -> replaceTo(matcher.group(0), ru.alkoleft.bsl.doc.bsl.Links.createLink(matcher.group(2), matcher.group(3)), options)); - } else { - result = context; - } - - result = handleWarning(result); - - return result; + return context; +// var matcher = linkPattern.matcher(context); +// String result; +// if (matcher.find()) { +// result = matcher.replaceAll(matchResult -> replaceTo(matcher.group(0), ru.alkoleft.bsl.doc.bsl.Links.createLink(matcher.group(2), matcher.group(3)), options)); +// } else { +// result = context; +// } +// +// result = handleWarning(result); +// +// return result; } @SneakyThrows diff --git a/src/main/resources/confluence-md/module.hbs b/src/main/resources/confluence-md/module.hbs index 2b2d222..8646cb3 100644 --- a/src/main/resources/confluence-md/module.hbs +++ b/src/main/resources/confluence-md/module.hbs @@ -29,7 +29,7 @@ {{~#if returnedValue}} *Возвращаемое значение* -{{~#with returnedValue}}{{#block "value-definition"}}{{/block}}{{~/with}} +{{#with returnedValue~}}{{#block "value-definition"}}{{/block}}{{~/with}} {{~/if}} {{~#if examples}} Примеры: diff --git a/src/main/resources/confluence-md/subsystem.hbs b/src/main/resources/confluence-md/subsystem.hbs index d2a8169..a792616 100644 --- a/src/main/resources/confluence-md/subsystem.hbs +++ b/src/main/resources/confluence-md/subsystem.hbs @@ -1,14 +1,16 @@ # {{#great level 1}}Подсистема {{/great}}{{present}} -{{#if description}} +{{~#if description}} {{description}} {{~/if}} -{{~#if constants}}Константы: +{{~#if constants}} + +## Константы {{#each constants as | item|}} * {{mdo-present item}} ({{item.name}}) {{~/each}} {{~/if}} -Содержимое: +## Содержимое {{#each childrenPages as | item|}} * [{{item.title}}]({{page-link item}}) {{~/each}} From d1934e429b1b4ddd25e6fcbad4e652d0c5c1dff7 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Fri, 20 Oct 2023 14:43:38 +0300 Subject: [PATCH 24/27] add gradle wrapper --- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59536 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 gradle/wrapper/gradle-wrapper.jar diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7454180f2ae8848c63b8b4dea2cb829da983f2fa GIT binary patch literal 59536 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL literal 0 HcmV?d00001 From 5235141fe7f05396a8d1bcc90cc81d3323f4ed77 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Fri, 20 Oct 2023 19:10:38 +0300 Subject: [PATCH 25/27] Fix log errors --- build.gradle.kts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index cc80838..511dc53 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -46,7 +46,8 @@ dependencies { } implementation("commons-io", "commons-io", "2.14.0") - implementation("ch.qos.logback", "logback-classic", "1.4.11") + implementation("ch.qos.logback:logback-core:1.2.11") + runtimeOnly("ch.qos.logback:logback-classic:1.2.11") // template engine implementation("com.github.jknack:handlebars:4.3.1") From af533537f4e967c584ea5c7316be37f6dc9f090e Mon Sep 17 00:00:00 2001 From: alkoleft Date: Fri, 20 Oct 2023 20:10:13 +0300 Subject: [PATCH 26/27] add support SUB_DIRECTORY layout for md2conf --- .../ru/alkoleft/bsl/doc/AutodocManager.java | 2 +- .../bsl/doc/commands/RenderCommand.java | 6 +++- .../alkoleft/bsl/doc/options/ChildLayout.java | 6 ++++ .../bsl/doc/options/OutputOptions.java | 1 + .../bsl/doc/render/StructureRender.java | 28 +++++++++++++++---- 5 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 src/main/java/ru/alkoleft/bsl/doc/options/ChildLayout.java diff --git a/src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java b/src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java index 4498987..84d18fa 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java +++ b/src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java @@ -50,7 +50,7 @@ public void generateDocumentation() { var processor = OutputStrategy.create(manualMergeStrategy); processor.init(outputOptions.getOutputFormat(), manualContent); - var render = new StructureRender(processor, manualContent.getContentModel()); + var render = new StructureRender(outputOptions, processor, manualContent.getContentModel()); BaseRender.setContext(RenderContext.Factory.create(outputOptions)); render.render(structure, destination); diff --git a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java index 1ccb790..5c11b8e 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java +++ b/src/main/java/ru/alkoleft/bsl/doc/commands/RenderCommand.java @@ -11,6 +11,7 @@ import ru.alkoleft.bsl.doc.AutodocManager; import ru.alkoleft.bsl.doc.bsl.Filter; import ru.alkoleft.bsl.doc.bsl.symbols.RegionSymbol; +import ru.alkoleft.bsl.doc.options.ChildLayout; import ru.alkoleft.bsl.doc.options.ManualMergeStrategy; import ru.alkoleft.bsl.doc.options.OutputFormat; import ru.alkoleft.bsl.doc.options.OutputOptions; @@ -38,6 +39,8 @@ public class RenderCommand implements Runnable { private Path manualDocumentation; @Option(names = {"-ms", "--merge-strategy"}, description = "Merge strategy for manual and generated documentation", defaultValue = "NONE") private ManualMergeStrategy manualMergeStrategy; + @Option(names = {"-cl", "--child-layout"}, description = "Child pages layout", defaultValue = "SAME_DIRECTORY") + private ChildLayout childLayout; @SneakyThrows @Override @@ -50,7 +53,8 @@ public void run() { var optionsBuilder = OutputOptions.builder() .outputFormat(format) - .subsystemHierarchy(true); + .subsystemHierarchy(true) + .childLayout(childLayout); var filter = filterBuilder.build(); var options = optionsBuilder.build(); diff --git a/src/main/java/ru/alkoleft/bsl/doc/options/ChildLayout.java b/src/main/java/ru/alkoleft/bsl/doc/options/ChildLayout.java new file mode 100644 index 0000000..f9ec591 --- /dev/null +++ b/src/main/java/ru/alkoleft/bsl/doc/options/ChildLayout.java @@ -0,0 +1,6 @@ +package ru.alkoleft.bsl.doc.options; + +public enum ChildLayout { + SUB_DIRECTORY, + SAME_DIRECTORY +} diff --git a/src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java b/src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java index 56c6d45..9e29617 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java +++ b/src/main/java/ru/alkoleft/bsl/doc/options/OutputOptions.java @@ -11,4 +11,5 @@ public class OutputOptions { OutputFormat outputFormat; boolean subsystemHierarchy; Path destination; + ChildLayout childLayout; } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java index c9c2921..0779c5a 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java @@ -6,6 +6,8 @@ import ru.alkoleft.bsl.doc.model.ContentModel; import ru.alkoleft.bsl.doc.model.Links; import ru.alkoleft.bsl.doc.model.PageType; +import ru.alkoleft.bsl.doc.options.ChildLayout; +import ru.alkoleft.bsl.doc.options.OutputOptions; import ru.alkoleft.bsl.doc.render.contexts.ContextFactory; import ru.alkoleft.bsl.doc.render.output.OutputStrategy; import ru.alkoleft.bsl.doc.structure.Item; @@ -25,11 +27,12 @@ public class StructureRender implements StructureVisitor { private boolean withRoot = false; private int subsystemLevel = 0; private PathResolver pathResolver; + private OutputOptions outputOptions; - public StructureRender(OutputStrategy outputStrategy, ContentModel contentModel) { + public StructureRender(OutputOptions outputOptions, OutputStrategy outputStrategy, ContentModel contentModel) { this.outputStrategy = outputStrategy; - this.contentModel = Objects.requireNonNullElseGet(contentModel, ContentModel::new); + this.outputOptions = outputOptions; } public void render(List structure, Path destination) { @@ -52,8 +55,13 @@ public void visit(SubsystemItem item, int index) { } else { pathResolver.entrance(item.getName()); item.accentChildren(this); - renderSubsystemPage(item); - pathResolver.exit(); + if (outputOptions.getChildLayout() == ChildLayout.SAME_DIRECTORY) { + renderSubsystemPage(item); + pathResolver.exit(); + } else { + pathResolver.exit(); + renderSubsystemPage(item); + } } subsystemLevel--; } @@ -83,16 +91,24 @@ public void visit(MDObjectItem item, int index) { } private void renderSubsystemPage(SubsystemItem item) { - var path = pathResolver.getFilePath("index"); + var path = getSubsystemPagePath(item); if (outputStrategy.needRender(path)) { var context = ContextFactory.create(item.getSubsystem(), 0, subsystemLevel); context.setContentModel(contentModel); - context.setOutputPath(path.getParent()); + if (outputOptions.getChildLayout() == ChildLayout.SAME_DIRECTORY) { + context.setOutputPath(path.getParent()); + } else { + context.setOutputPath(path.getParent().resolve(item.getName())); + } Links.setCurrentPath(path); var content = BslRender.renderSubsystem(context); outputStrategy.save(path, content); contentModel.append(path, PageType.SUBSYSTEM); } } + + private Path getSubsystemPagePath(SubsystemItem item) { + return outputOptions.getChildLayout() == ChildLayout.SAME_DIRECTORY ? pathResolver.getFilePath("index") : pathResolver.getFilePath(item.getName()); + } } From 40d776198eb7a2db206dae1b9064b4f440e3b466 Mon Sep 17 00:00:00 2001 From: alkoleft Date: Sun, 22 Oct 2023 23:19:15 +0300 Subject: [PATCH 27/27] Optimize * retrieving page title on save * decrease log * fix subsystem page title template --- .../ru/alkoleft/bsl/doc/AutodocManager.java | 7 ++++-- .../bsl/doc/manual/ManualContent.java | 6 ++--- .../alkoleft/bsl/doc/model/ContentModel.java | 12 +++++----- .../bsl/doc/render/StructureRender.java | 15 ++++++------ .../bsl/doc/render/output/AppendStrategy.java | 2 +- .../bsl/doc/render/output/MergeStrategy.java | 21 +++++------------ .../bsl/doc/render/output/OutputStrategy.java | 23 +++++++++++++++++-- .../resources/confluence-md/subsystem.hbs | 2 +- src/main/resources/logback.xml | 11 +++++++++ 9 files changed, 61 insertions(+), 38 deletions(-) create mode 100644 src/main/resources/logback.xml diff --git a/src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java b/src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java index 84d18fa..d834c41 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java +++ b/src/main/java/ru/alkoleft/bsl/doc/AutodocManager.java @@ -7,6 +7,7 @@ import ru.alkoleft.bsl.doc.bsl.Filter; import ru.alkoleft.bsl.doc.content.processor.TitleProcessor; import ru.alkoleft.bsl.doc.manual.ManualContent; +import ru.alkoleft.bsl.doc.model.ContentModel; import ru.alkoleft.bsl.doc.options.ManualMergeStrategy; import ru.alkoleft.bsl.doc.options.OutputOptions; import ru.alkoleft.bsl.doc.render.BaseRender; @@ -18,6 +19,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Objects; public class AutodocManager { @@ -49,8 +51,9 @@ public void generateDocumentation() { StructureBuilder.print(structure); var processor = OutputStrategy.create(manualMergeStrategy); - processor.init(outputOptions.getOutputFormat(), manualContent); - var render = new StructureRender(outputOptions, processor, manualContent.getContentModel()); + var contentModel = Objects.requireNonNullElseGet(manualContent.getContentModel(), ContentModel::new); + processor.init(outputOptions.getOutputFormat(), manualContent, contentModel); + var render = new StructureRender(outputOptions, processor, contentModel); BaseRender.setContext(RenderContext.Factory.create(outputOptions)); render.render(structure, destination); diff --git a/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java b/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java index 9f661c8..4919849 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java +++ b/src/main/java/ru/alkoleft/bsl/doc/manual/ManualContent.java @@ -39,14 +39,14 @@ public void copy() { .forEach(destinationModel.getPages()::add); } - public boolean contains(Path path) { + public boolean isNotContains(Path path) { if (destinationModel == null) { - return false; + return true; } return destinationModel.getPages() .stream() .map(Page::getPath) - .anyMatch(it -> it.equals(path)); + .noneMatch(it -> it.equals(path)); } public ContentModel getContentModel() { diff --git a/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java index 0198fdf..708f976 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java +++ b/src/main/java/ru/alkoleft/bsl/doc/model/ContentModel.java @@ -12,16 +12,16 @@ public class ContentModel { List pages = new ArrayList<>(); - public void append(Path path, PageType type) { + public Page append(Path path) { var page = pages.stream() .filter(it -> path.equals(it.getPath())) - .findAny(); + .findAny() + .orElse(null); - if (page.isEmpty()) { - pages.add(new Page(path, null, type)); - } else { - page.get().setType(type); + if (page == null) { + pages.add(page = new Page(path, null, PageType.UNKNOWN)); } + return page; } public List getChildrenPages(Path path) { diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java index 0779c5a..be25bec 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/StructureRender.java @@ -19,7 +19,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -import java.util.Objects; public class StructureRender implements StructureVisitor { private final OutputStrategy outputStrategy; @@ -27,18 +26,18 @@ public class StructureRender implements StructureVisitor { private boolean withRoot = false; private int subsystemLevel = 0; private PathResolver pathResolver; - private OutputOptions outputOptions; + private final OutputOptions outputOptions; public StructureRender(OutputOptions outputOptions, OutputStrategy outputStrategy, ContentModel contentModel) { this.outputStrategy = outputStrategy; - this.contentModel = Objects.requireNonNullElseGet(contentModel, ContentModel::new); + this.contentModel = contentModel; this.outputOptions = outputOptions; } public void render(List structure, Path destination) { pathResolver = new PathResolver(destination, outputStrategy.getFormat()); subsystemLevel = 0; - withRoot = structure.size() > 1; + withRoot = outputOptions.getChildLayout() == ChildLayout.SUB_DIRECTORY || structure.size() > 1; for (int i = 0; i < structure.size(); i++) { structure.get(i).accept(this, i); @@ -80,8 +79,8 @@ public void visit(ModuleItem item, int index) { if (outputStrategy.needRender(path)) { Links.setCurrentPath(path); var content = BslRender.renderModule(moduleContext, index); - outputStrategy.save(path, content); - contentModel.append(path, PageType.MODULE); + outputStrategy.save(path, content) + .setType(PageType.MODULE); } } @@ -103,8 +102,8 @@ private void renderSubsystemPage(SubsystemItem item) { } Links.setCurrentPath(path); var content = BslRender.renderSubsystem(context); - outputStrategy.save(path, content); - contentModel.append(path, PageType.SUBSYSTEM); + outputStrategy.save(path, content) + .setType(PageType.SUBSYSTEM); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/output/AppendStrategy.java b/src/main/java/ru/alkoleft/bsl/doc/render/output/AppendStrategy.java index 1894e52..cfb799b 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/output/AppendStrategy.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/output/AppendStrategy.java @@ -5,6 +5,6 @@ public class AppendStrategy extends OutputStrategy { @Override public boolean needRender(Path location) { - return !manualContent.contains(location); + return manualContent.isNotContains(location); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/output/MergeStrategy.java b/src/main/java/ru/alkoleft/bsl/doc/render/output/MergeStrategy.java index cce11be..1e8f89a 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/output/MergeStrategy.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/output/MergeStrategy.java @@ -3,8 +3,7 @@ import com.github.jknack.handlebars.internal.Files; import lombok.SneakyThrows; import ru.alkoleft.bsl.doc.content.processor.TitleProcessor; -import ru.alkoleft.bsl.doc.manual.ManualContent; -import ru.alkoleft.bsl.doc.options.OutputFormat; +import ru.alkoleft.bsl.doc.model.Page; import java.nio.charset.StandardCharsets; import java.nio.file.Path; @@ -12,24 +11,16 @@ public class MergeStrategy extends OutputStrategy { private static final Pattern replacePattern = Pattern.compile("^.*generated_content.*$", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); - TitleProcessor titleCleaner; - - @Override - public void init(OutputFormat format, ManualContent manualContent) { - super.init(format, manualContent); - titleCleaner = TitleProcessor.getInstance(); - } @SneakyThrows @Override - public void save(Path itemPath, String content) { - if (!manualContent.contains(itemPath)) { - super.save(itemPath, content); - return; + public Page save(Path itemPath, String content) { + if (manualContent.isNotContains(itemPath)) { + return super.save(itemPath, content); } var manualContent = Files.read(itemPath.toFile(), StandardCharsets.UTF_8); - content = titleCleaner.cleanTitle(content); + content = TitleProcessor.getInstance().cleanTitle(content); var result = replacePattern.matcher(manualContent).replaceFirst(content); - super.save(itemPath, result); + return super.save(itemPath, result); } } diff --git a/src/main/java/ru/alkoleft/bsl/doc/render/output/OutputStrategy.java b/src/main/java/ru/alkoleft/bsl/doc/render/output/OutputStrategy.java index e7accdf..e9db6c3 100644 --- a/src/main/java/ru/alkoleft/bsl/doc/render/output/OutputStrategy.java +++ b/src/main/java/ru/alkoleft/bsl/doc/render/output/OutputStrategy.java @@ -3,7 +3,11 @@ import lombok.Getter; import lombok.Setter; import lombok.SneakyThrows; +import ru.alkoleft.bsl.doc.bsl.helpers.Strings; +import ru.alkoleft.bsl.doc.content.processor.TitleProcessor; import ru.alkoleft.bsl.doc.manual.ManualContent; +import ru.alkoleft.bsl.doc.model.ContentModel; +import ru.alkoleft.bsl.doc.model.Page; import ru.alkoleft.bsl.doc.options.ManualMergeStrategy; import ru.alkoleft.bsl.doc.options.OutputFormat; @@ -16,11 +20,24 @@ public class OutputStrategy { protected OutputFormat format; @Setter protected ManualContent manualContent; + @Setter + protected ContentModel contentModel; public boolean needRender(Path location) { return true; } + protected Page addToContentModel(Path path, String content) { + var page = getContentModel().append(path); + + if (Strings.isNullOrEmpty(page.getTitle())) { + var title = TitleProcessor.getInstance().getTitle(content); + page.setTitle(title); + } + + return page; + } + public static OutputStrategy create(ManualMergeStrategy strategy) { OutputStrategy processor; switch (strategy) { @@ -37,14 +54,16 @@ public static OutputStrategy create(ManualMergeStrategy strategy) { return processor; } - public void init(OutputFormat format, ManualContent manualContent) { + public void init(OutputFormat format, ManualContent manualContent, ContentModel contentModel) { this.format = format; this.manualContent = manualContent; + this.contentModel = contentModel; } @SneakyThrows - public void save(Path itemPath, String content) { + public Page save(Path itemPath, String content) { Files.createDirectories(itemPath.getParent()); Files.writeString(itemPath, content); + return addToContentModel(itemPath, content); } } diff --git a/src/main/resources/confluence-md/subsystem.hbs b/src/main/resources/confluence-md/subsystem.hbs index a792616..7553a66 100644 --- a/src/main/resources/confluence-md/subsystem.hbs +++ b/src/main/resources/confluence-md/subsystem.hbs @@ -1,4 +1,4 @@ -# {{#great level 1}}Подсистема {{/great}}{{present}} +# {{#great level 2}}Подсистема {{/great}}{{present}} {{~#if description}} {{description}} {{~/if}} diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..59dc38f --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,11 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + \ No newline at end of file