Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds diffLink macro to core. Fix #1539. #1540

Merged
merged 9 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -613,10 +613,9 @@ class GuideAsciidocGenerator {
}

private static String buildDiffLink(String line, GuidesOption guidesOption, Guide metadata) {

String appName = extractAppName(line) ?: DEFAULT_APP_NAME
App app = metadata.apps().find { it.name() == appName }
String link = 'https://micronaut.io/launch?' +
return 'https://micronaut.io/launch?' +
featureNames(line, app, guidesOption).collect { 'features=' + it }.join('&') +
'&lang=' + guidesOption.language.name() +
'&build=' + guidesOption.buildTool.name() +
Expand All @@ -625,10 +624,7 @@ class GuideAsciidocGenerator {
'&type=' + app.applicationType().name() +
'&package=example.micronaut' +
'&activity=diff' +
'[view the dependency and configuration changes from the specified features, window="_blank"]'

"NOTE: If you have an existing Micronaut application and want to add the functionality described here, you can " +
link + " and apply those changes to your application."
'[Diff, window="_blank"]'
}

private static String processGuideLink(String line) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package io.micronaut.guides.core;

import io.micronaut.guides.core.asciidoc.AsciidocMacro;
import io.micronaut.guides.core.asciidoc.Attribute;
import io.micronaut.http.uri.UriBuilder;
import io.micronaut.starter.application.ApplicationType;
import jakarta.inject.Singleton;
import java.net.URI;
import java.util.*;
import static io.micronaut.guides.core.MacroUtils.*;

@Singleton
public class BuildDiffLinkSubstitution implements MacroSubstitution {
private static final String QUERY_PARAMLANG = "lang";
private static final String QUERY_PARAM_BUILD = "build";
private static final String QUERY_PARAM_TEST = "test";
private static final String QUERY_PARAM_NAME = "name";
private static final String QUERY_PARAM_TYPE = "type";
private static final String QUERY_PARAM_PACKAGE = "package";
private static final String QUERY_PARAM_ACTIVITY = "activity";
private static final String QUERY_PARAM_FEATURES = "features";
public static final String MACRO_DIFF_LINK = "diffLink";
private static final String ATTRIBUTE_FEATURES = "features";
private static final String ATTRIBUTE_EXCLUDE_FEATURES = "featureExcludes";
private final GuidesConfiguration guidesConfiguration;

public BuildDiffLinkSubstitution(GuidesConfiguration config) {
this.guidesConfiguration = config;
}

@Override
public String substitute(String str, Guide guide, GuidesOption option) {
for(String line : findMacroLines(str, MACRO_DIFF_LINK)) {
Optional<AsciidocMacro> asciidocMacroOptional = AsciidocMacro.of(MACRO_DIFF_LINK, line);
if (asciidocMacroOptional.isEmpty()) {
continue;
}
AsciidocMacro asciidocMacro = asciidocMacroOptional.get();
String res = buildDiffLink(asciidocMacro, guide, option).toString() + "[Diff]";
str = str.replace(line,res);
}
return str;
}

private URI buildDiffLink(AsciidocMacro asciidocMacro, Guide guide, GuidesOption option) {
String appName = appName(asciidocMacro);
App app = app(guide, asciidocMacro);
Set<String> features = features(app, asciidocMacro, option);
UriBuilder uriBuilder = UriBuilder.of(guidesConfiguration.getProjectGeneratorUrl())
.queryParam(QUERY_PARAMLANG, option.getLanguage().name())
.queryParam(QUERY_PARAM_BUILD, option.getBuildTool().name())
.queryParam(QUERY_PARAM_TEST, option.getTestFramework().name())
.queryParam(QUERY_PARAM_NAME, appName.equals(guidesConfiguration.getDefaultAppName()) ? "micronautguide" : appName)
.queryParam(QUERY_PARAM_TYPE, app != null ? app.applicationType().name() : ApplicationType.DEFAULT.name())
.queryParam(QUERY_PARAM_PACKAGE, guidesConfiguration.getPackageName())
.queryParam(QUERY_PARAM_ACTIVITY, "diff");
features.forEach(f -> uriBuilder.queryParam(QUERY_PARAM_FEATURES, f));
return uriBuilder.build();
}

private static Set<String> features(App app, AsciidocMacro asciidocMacro, GuidesOption option) {
Set<String> features = new HashSet<>();
if (app != null) {
features.addAll(GuideUtils.getAppVisibleFeatures(app, option.getLanguage()));
}
asciidocMacro.attributes().stream()
.filter(attribute -> attribute.key().equals(ATTRIBUTE_FEATURES))
.map(Attribute::values)
.forEach(features::addAll);
asciidocMacro.attributes().stream()
.filter(attribute -> attribute.key().equals(ATTRIBUTE_EXCLUDE_FEATURES))
.map(Attribute::values)
.forEach(features::removeAll);
return features;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@Singleton
public class DependencyMacroSubstitution implements MacroSubstitution{
@Override
public String substitute(String str, String slug, GuidesOption option) {
public String substitute(String str, Guide guide, GuidesOption option) {
for(String block : findMacroGroups(str, "dependencies")){
List<String> lines = DependencyLines.asciidoc(block.replace(":dependencies:","").strip().lines().toList(), option.getBuildTool(), option.getLanguage());
str = str.replace(block,String.join("\n", lines));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ public interface GuidesConfiguration {
String getTitle();
String getLicensePath();
String getPackageName();
String getDefaultAppName();
String getProjectGeneratorUrl();
List<String> getFilesWithHeader();
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public class GuidesConfigurationProperties implements GuidesConfiguration {
private String licensePath = DEFAULT_LICENSEHEADER;
private String packageName = DEFAULT_PACKAGE_NAME;
private List<String> sourceFilesExtensions = List.of("java", "kotlin", "groovy");
private static final String DEFAULT_APP_NAME = "default";
private static final String HOMEPAGE_URL = "https://micronaut.io";
private static final String LAUNCHER_URL = HOMEPAGE_URL + "/launch";

@Override
public String getPackageName() {
Expand Down Expand Up @@ -52,6 +55,14 @@ public void setTitle(String title) {
this.title = title;
}

@Override
public String getDefaultAppName() {
return DEFAULT_APP_NAME;
}

@Override
public String getProjectGeneratorUrl() { return LAUNCHER_URL; }

@Override
public List<String> getFilesWithHeader() {
return sourceFilesExtensions;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
package io.micronaut.guides.core;

import io.micronaut.core.annotation.NonNull;
import io.micronaut.guides.core.asciidoc.AsciidocMacro;
import io.micronaut.guides.core.asciidoc.Attribute;

import java.util.List;

public interface MacroSubstitution {
String APP = "app";
String APP_NAME_DEFAULT = "default";

@NonNull
String substitute(@NonNull String str, @NonNull String slug, @NonNull GuidesOption option);
String substitute(@NonNull String str, @NonNull Guide slug, @NonNull GuidesOption option);
sdelamo marked this conversation as resolved.
Show resolved Hide resolved

default App app(Guide guide, AsciidocMacro asciidocMacro) {
final String appName = appName(asciidocMacro);
return guide.apps().stream()
.filter(a -> a.name().equals(appName))
.findFirst()
.orElseThrow(() -> new RuntimeException("app not found for app name" + appName));
}

default String appName(AsciidocMacro asciidocMacro) {
return asciidocMacro.attributes().stream()
.filter(attribute -> attribute.key().equals(APP))
.map(Attribute::values)
.filter(l -> !l.isEmpty())
.map(List::getFirst)
.findFirst()
.orElse(APP_NAME_DEFAULT);
}
}
48 changes: 48 additions & 0 deletions buildSrc/src/main/java/io/micronaut/guides/core/MacroUtils.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,62 @@
package io.micronaut.guides.core;

import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.util.StringUtils;
import io.micronaut.starter.options.Language;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public final class MacroUtils {
private MacroUtils() {
}

/*
@NonNull
public static String extractAppName(@NonNull String line) {
return extractFromParametersLine(line, "app");
}

@NonNull
static String extractFromParametersLine(@NonNull String line, @NonNull String attributeName) {
String[] attrs = line.substring(line.indexOf("[") + 1, line.indexOf("]")).split(",");
return Arrays.stream(attrs)
.filter(attr -> attr.startsWith(attributeName))
.map(attr -> attr.split("="))
.map(parts -> parts[1])
.findFirst()
.orElse("");
}

@NonNull
static List<String> featureNames(@NonNull String line,
@NonNull App app,
@NonNull GuidesOption guidesOption) {
String features = extractFromParametersLine(line, "features");
List<String> featureNames;
if (StringUtils.isNotEmpty(features)) {
featureNames = Arrays.asList(features.split("\\|"));
} else {
featureNames = new ArrayList<>(GuideUtils.getAppVisibleFeatures(app, guidesOption.getLanguage()));
}

String featureExcludes = extractFromParametersLine(line, "featureExcludes");
List<String> excludedFeatureNames;
if (featureExcludes != null && !featureExcludes.isEmpty()) {
excludedFeatureNames = Arrays.asList(featureExcludes.split("\\|"));
} else {
excludedFeatureNames = new ArrayList<>();
}
featureNames.removeAll(excludedFeatureNames);

if (guidesOption.getLanguage() == Language.GROOVY) {
featureNames.remove("graalvm");
}
return featureNames;
}
*/

@NonNull
static String getSourceDir(@NonNull String slug, @NonNull GuidesOption option) {
return slug + "-" + option.getBuildTool() + "-" + option.getLanguage();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.jetbrains.annotations.NotNull;

import java.nio.file.Path;
import java.util.List;
import java.util.Optional;

import static io.micronaut.guides.core.MacroUtils.*;
Expand Down Expand Up @@ -35,18 +36,13 @@ public GuidesConfiguration getGuidesConfiguration() {
}

@Override
public String substitute(String str, String slug, GuidesOption option) {
public String substitute(String str, Guide guide, GuidesOption option) {
String slug = guide.slug();
for (String line : findMacroLines(str, getMacroName())) {
Optional<AsciidocMacro> asciidocMacroOptional = AsciidocMacro.of(getMacroName(), line);
if (asciidocMacroOptional.isPresent()) {
AsciidocMacro asciidocMacro = asciidocMacroOptional.get();
String appName = asciidocMacro.attributes().stream()
.filter(attribute -> attribute.key().equals(APP))
.map(Attribute::values)
.filter(l -> !l.isEmpty())
.map(l -> l.get(0))
.findFirst()
.orElse(APP);
String appName = appName(asciidocMacro);

String condensedTarget = condensedTarget(asciidocMacro, option);
String[] arr;
Expand Down Expand Up @@ -105,7 +101,7 @@ protected String sourceTitle(
Classpath classpath,
String language,
String packageName) {
return (appName.equals(MacroSubstitution.APP) ? "" : (appName + "/")) + sourceConventionFolder(classpath, language) + "/"
return (appName.equals(MacroSubstitution.APP_NAME_DEFAULT) ? "" : (appName + "/")) + sourceConventionFolder(classpath, language) + "/"
+ (getFileType() == FileType.CODE ? (packageName.replace(".", "/") + "/") : "")
+ condensedTarget;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package io.micronaut.guides.core;

import io.micronaut.core.beans.BeanIntrospection;
import io.micronaut.core.io.ResourceLoader;
import io.micronaut.http.uri.UriBuilder;
import io.micronaut.json.JsonMapper;
import io.micronaut.starter.api.TestFramework;
import io.micronaut.starter.options.BuildTool;
import io.micronaut.starter.options.Language;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;

import java.io.InputStream;
import java.net.URI;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

@MicronautTest(startApplication = false)
class BuildDiffLinkSubstitutionTest {
@Inject
BuildDiffLinkSubstitution buildDiffLinkSubstitution;

@Inject
JsonMapper jsonMapper;

@Inject
ResourceLoader resourceLoader;

@Test
void testSubstitute(){
assertDoesNotThrow(() -> BeanIntrospection.getIntrospection(Guide.class));
Optional<InputStream> inputStreamOptional = resourceLoader.getResourceAsStream("classpath:metadata-diff.json");
assertTrue(inputStreamOptional.isPresent());
final InputStream inputStreamBase = inputStreamOptional.get();
Guide guide = assertDoesNotThrow(() -> jsonMapper.readValue(inputStreamBase, Guide.class));
String str = "diffLink:[app=cli]";
String resJava = buildDiffLinkSubstitution.substitute(str, guide, new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.JUNIT));
URI expectedURI = UriBuilder.of("https://micronaut.io")
.path("launch")
.queryParam("lang", "JAVA")
.queryParam("build", "GRADLE")
.queryParam("test", "JUNIT")
.queryParam("name", "cli")
.queryParam("type", "CLI")
.queryParam("package", "example.micronaut")
.queryParam("activity", "diff")
.queryParam("features", "awaitility")
.queryParam("features", "graalvm")
.queryParam("features", "mqtt")
.queryParam("features", "yaml")
.build();
String expectedJava = expectedURI.toString() + "[Diff]";
assertEquals(expectedJava, resJava);

str = "diffLink:[app=cli,featureExcludes=graalvm]";
resJava = buildDiffLinkSubstitution.substitute(str, guide, new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.JUNIT));
expectedURI = UriBuilder.of("https://micronaut.io")
.path("launch")
.queryParam("lang", "JAVA")
.queryParam("build", "GRADLE")
.queryParam("test", "JUNIT")
.queryParam("name", "cli")
.queryParam("type", "CLI")
.queryParam("package", "example.micronaut")
.queryParam("activity", "diff")
.queryParam("features", "awaitility")
.queryParam("features", "mqtt")
.queryParam("features", "yaml")
.build();
expectedJava = expectedURI.toString() + "[Diff]";
assertEquals(expectedJava, resJava);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void testSubstitute(){
dependency:micronaut-security-session[groupId=io.micronaut.security]
""";

String resJava = dependencyMacroSubstitution.substitute(str, "micronaut-jaxrs", new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.SPOCK));
String resJava = dependencyMacroSubstitution.substitute(str, GuideTestUtils.guideWithSlug("micronaut-jaxrs"), new GuidesOption(BuildTool.GRADLE, Language.JAVA, TestFramework.SPOCK));
String expectedJava = """
==== Dependencies

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.micronaut.guides.core;

import java.util.List;
import java.util.Map;

public final class GuideTestUtils {
private GuideTestUtils() {
}

public static Guide guideWithSlug(String slug) {
return new Guide("", "", List.of(), List.of(), null, 0, 0, null, null, null, "", List.of(), List.of(), List.of(), null, List.of(), slug, null, "", Map.of(), List.of());
}
}
Loading
Loading