Skip to content

Commit e785f69

Browse files
pavelrappojonathan-gibbonshns
committed
8276124: Provide snippet support for properties files
Co-authored-by: Jonathan Gibbons <jjg@openjdk.org> Co-authored-by: Hannes Wallnöfer <hannesw@openjdk.org> Reviewed-by: jjg
1 parent 96fe1d0 commit e785f69

File tree

4 files changed

+263
-41
lines changed

4 files changed

+263
-41
lines changed

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.HashMap;
3131
import java.util.Map;
3232
import java.util.Objects;
33+
import java.util.Optional;
3334
import java.util.stream.Collectors;
3435

3536
import javax.lang.model.element.Element;
@@ -63,6 +64,38 @@
6364
*/
6465
public class SnippetTaglet extends BaseTaglet {
6566

67+
public enum Language {
68+
69+
JAVA("java"),
70+
PROPERTIES("properties");
71+
72+
private static final Map<String, Language> languages;
73+
74+
static {
75+
Map<String, Language> tmp = new HashMap<>();
76+
for (var language : values()) {
77+
String id = Objects.requireNonNull(language.identifier);
78+
if (tmp.put(id, language) != null)
79+
throw new IllegalStateException(); // 1-1 correspondence
80+
}
81+
languages = Map.copyOf(tmp);
82+
}
83+
84+
Language(String id) {
85+
identifier = id;
86+
}
87+
88+
private final String identifier;
89+
90+
public static Optional<Language> of(String identifier) {
91+
if (identifier == null)
92+
return Optional.empty();
93+
return Optional.ofNullable(languages.get(identifier));
94+
}
95+
96+
public String getIdentifier() {return identifier;}
97+
}
98+
6699
public SnippetTaglet() {
67100
super(DocTree.Kind.SNIPPET, true, EnumSet.allOf(Taglet.Location.class));
68101
}
@@ -217,14 +250,27 @@ private Content generateContent(Element holder, DocTree tag, TagletWriter writer
217250
}
218251
}
219252

253+
String lang = null;
254+
AttributeTree langAttr = attributes.get("lang");
255+
if (langAttr != null) {
256+
lang = stringValueOf(langAttr);
257+
} else if (containsClass) {
258+
lang = "java";
259+
} else if (containsFile) {
260+
lang = languageFromFileName(fileObject.getName());
261+
}
262+
263+
Optional<Language> language = Language.of(lang);
264+
265+
220266
// TODO cache parsed external snippet (WeakHashMap)
221267

222268
StyledText inlineSnippet = null;
223269
StyledText externalSnippet = null;
224270

225271
try {
226272
if (inlineContent != null) {
227-
inlineSnippet = parse(writer.configuration().getDocResources(), inlineContent);
273+
inlineSnippet = parse(writer.configuration().getDocResources(), language, inlineContent);
228274
}
229275
} catch (ParseException e) {
230276
var path = writer.configuration().utils.getCommentHelper(holder)
@@ -239,7 +285,7 @@ private Content generateContent(Element holder, DocTree tag, TagletWriter writer
239285

240286
try {
241287
if (externalContent != null) {
242-
externalSnippet = parse(writer.configuration().getDocResources(), externalContent);
288+
externalSnippet = parse(writer.configuration().getDocResources(), language, externalContent);
243289
}
244290
} catch (ParseException e) {
245291
assert fileObject != null;
@@ -289,15 +335,6 @@ private Content generateContent(Element holder, DocTree tag, TagletWriter writer
289335
assert inlineSnippet != null || externalSnippet != null;
290336
StyledText text = inlineSnippet != null ? inlineSnippet : externalSnippet;
291337

292-
String lang = null;
293-
AttributeTree langAttr = attributes.get("lang");
294-
if (langAttr != null) {
295-
lang = stringValueOf(langAttr);
296-
} else if (containsClass) {
297-
lang = "java";
298-
} else if (containsFile) {
299-
lang = languageFromFileName(fileObject.getName());
300-
}
301338
AttributeTree idAttr = attributes.get("id");
302339
String id = idAttr == null
303340
? null
@@ -326,8 +363,8 @@ private static String diff(String inline, String external) {
326363
""".formatted(inline, external);
327364
}
328365

329-
private StyledText parse(Resources resources, String content) throws ParseException {
330-
Parser.Result result = new Parser(resources).parse(content);
366+
private StyledText parse(Resources resources, Optional<Language> language, String content) throws ParseException {
367+
Parser.Result result = new Parser(resources).parse(language, content);
331368
result.actions().forEach(Action::perform);
332369
return result.text();
333370
}

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Parser.java

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import java.util.regex.PatternSyntaxException;
4040

4141
import jdk.javadoc.internal.doclets.toolkit.Resources;
42+
import jdk.javadoc.internal.doclets.toolkit.taglets.SnippetTaglet;
4243

4344
/*
4445
* Semantics of a EOL comment; plus
@@ -76,10 +77,10 @@
7677
*/
7778
public final class Parser {
7879

79-
// next-line tag behaves as if it were specified on the next line
80-
81-
private String eolMarker;
82-
private Matcher markedUpLine;
80+
private static final Pattern JAVA_COMMENT = Pattern.compile(
81+
"^(?<payload>.*)//(?<markup>\\s*@\\s*\\w+.+?)$");
82+
private static final Pattern PROPERTIES_COMMENT = Pattern.compile(
83+
"^(?<payload>[ \t]*([#!].*)?)[#!](?<markup>\\s*@\\s*\\w+.+?)$");
8384

8485
private final Resources resources;
8586
private final MarkupParser markupParser;
@@ -93,32 +94,23 @@ public Parser(Resources resources) {
9394
this.markupParser = new MarkupParser(resources);
9495
}
9596

96-
public Result parse(String source) throws ParseException {
97-
return parse("//", source);
97+
public Result parse(Optional<SnippetTaglet.Language> language, String source) throws ParseException {
98+
SnippetTaglet.Language lang = language.orElse(SnippetTaglet.Language.JAVA);
99+
var p = switch (lang) {
100+
case JAVA -> JAVA_COMMENT;
101+
case PROPERTIES -> PROPERTIES_COMMENT;
102+
};
103+
return parse(p, source);
98104
}
99105

100106
/*
101107
* Newline characters in the returned text are of the \n form.
102108
*/
103-
public Result parse(String eolMarker, String source) throws ParseException {
104-
Objects.requireNonNull(eolMarker);
109+
private Result parse(Pattern commentPattern, String source) throws ParseException {
110+
Objects.requireNonNull(commentPattern);
105111
Objects.requireNonNull(source);
106-
if (!Objects.equals(eolMarker, this.eolMarker)) {
107-
if (eolMarker.length() < 1) {
108-
throw new IllegalArgumentException();
109-
}
110-
for (int i = 0; i < eolMarker.length(); i++) {
111-
switch (eolMarker.charAt(i)) {
112-
case '\f', '\n', '\r' -> throw new IllegalArgumentException();
113-
}
114-
}
115-
this.eolMarker = eolMarker;
116-
// capture the rightmost eolMarker (e.g. "//")
117-
// The below Pattern.compile should never throw PatternSyntaxException
118-
Pattern pattern = Pattern.compile("^(.*)(" + Pattern.quote(eolMarker)
119-
+ "(\\s*@\\s*\\w+.+?))$");
120-
this.markedUpLine = pattern.matcher(""); // reusable matcher
121-
}
112+
113+
Matcher markedUpLine = commentPattern.matcher(""); // reusable matcher
122114

123115
tags.clear();
124116
regions.clear();
@@ -151,17 +143,17 @@ record OffsetAndLine(int offset, String line) { }
151143
if (!markedUpLine.matches()) { // (1)
152144
line = rawLine + (addLineTerminator ? "\n" : "");
153145
} else {
154-
String maybeMarkup = markedUpLine.group(3);
146+
String maybeMarkup = rawLine.substring(markedUpLine.start("markup"));
155147
List<Tag> parsedTags;
156148
try {
157149
parsedTags = markupParser.parse(maybeMarkup);
158150
} catch (ParseException e) {
159151
// translate error position from markup to file line
160-
throw new ParseException(e::getMessage, markedUpLine.start(3) + e.getPosition());
152+
throw new ParseException(e::getMessage, markedUpLine.start("markup") + e.getPosition());
161153
}
162154
for (Tag t : parsedTags) {
163155
t.lineSourceOffset = next.offset();
164-
t.markupLineOffset = markedUpLine.start(3);
156+
t.markupLineOffset = markedUpLine.start("markup");
165157
}
166158
thisLineTags.addAll(parsedTags);
167159
for (var tagIterator = thisLineTags.iterator(); tagIterator.hasNext(); ) {
@@ -176,7 +168,7 @@ record OffsetAndLine(int offset, String line) { }
176168
// TODO: log this with NOTICE;
177169
line = rawLine + (addLineTerminator ? "\n" : "");
178170
} else { // (3)
179-
String payload = markedUpLine.group(1);
171+
String payload = rawLine.substring(0, markedUpLine.end("payload"));
180172
line = payload + (addLineTerminator ? "\n" : "");
181173
}
182174
}

test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ protected String getSnippetHtmlRepresentation(String pathToHtmlFile,
101101
return getSnippetHtmlRepresentation(pathToHtmlFile, content, Optional.empty(), Optional.empty());
102102
}
103103

104+
protected String getSnippetHtmlRepresentation(String pathToHtmlFile,
105+
String content,
106+
Optional<String> lang) {
107+
return getSnippetHtmlRepresentation(pathToHtmlFile, content, lang, Optional.empty());
108+
}
109+
104110
protected String getSnippetHtmlRepresentation(String pathToHtmlFile,
105111
String content,
106112
Optional<String> lang,

0 commit comments

Comments
 (0)