diff --git a/kythe/cxx/doc/html_renderer.cc b/kythe/cxx/doc/html_renderer.cc index c1b89dc17a..a32fa46610 100644 --- a/kythe/cxx/doc/html_renderer.cc +++ b/kythe/cxx/doc/html_renderer.cc @@ -449,6 +449,7 @@ std::string RenderSignature(const HtmlRendererOptions& options, state.render_identifier = true; state.render_types = true; state.render_parameters = true; + state.render_modifier = true; state.linkify = linkify; state.options = &options; state.base_ticket = base_ticket; diff --git a/kythe/go/indexer/testdata/code/rendered.go b/kythe/go/indexer/testdata/code/rendered.go index 3fb66c4931..cef8097e1b 100644 --- a/kythe/go/indexer/testdata/code/rendered.go +++ b/kythe/go/indexer/testdata/code/rendered.go @@ -11,6 +11,7 @@ type S struct{} // - @M defines/binding M // - M.code/rendered/qualified_name "rendered.S.M" +// - M.code/rendered/signature "func (s *S) M()" // - M.code/rendered/callsite_signature "(s) M()" func (s *S) M() {} @@ -28,5 +29,5 @@ func (s *S) MArg(arg int) {} // - @H defines/binding H? // - H.code/rendered/callsite_signature "H(param)" -// - H.code/rendered/signature "H(param func() (string, error)) error" +// - H.code/rendered/signature "func H(param func() (string, error)) error" func H(param func() (string, error)) error { return nil } diff --git a/kythe/go/util/markedsource/markedsource.go b/kythe/go/util/markedsource/markedsource.go index b880c0bc60..7fa4653ee7 100644 --- a/kythe/go/util/markedsource/markedsource.go +++ b/kythe/go/util/markedsource/markedsource.go @@ -108,6 +108,7 @@ func RenderSignature(node *cpb.MarkedSource, format ContentType, linkify func(st cpb.MarkedSource_IDENTIFIER: true, cpb.MarkedSource_TYPE: true, cpb.MarkedSource_PARAMETER: true, + cpb.MarkedSource_MODIFIER: true, } r := &renderer{ buffer: &content{}, diff --git a/kythe/java/com/google/devtools/kythe/analyzers/java/JavaEntrySets.java b/kythe/java/com/google/devtools/kythe/analyzers/java/JavaEntrySets.java index 530db7b904..74186e7d39 100644 --- a/kythe/java/com/google/devtools/kythe/analyzers/java/JavaEntrySets.java +++ b/kythe/java/com/google/devtools/kythe/analyzers/java/JavaEntrySets.java @@ -264,9 +264,23 @@ public EntrySet newPackageNodeAndEmit(String name) { .setProperty( "code", MarkedSource.newBuilder() - .setPreText(name) - .setKind(MarkedSource.Kind.IDENTIFIER) - .build())); + .addChild( + MarkedSource.newBuilder() + .setPostChildText(" ") + .setAddFinalListToken(true) + .addChild( + MarkedSource.newBuilder() + .setPreText("package") + .setKind(MarkedSource.Kind.MODIFIER) + .build()) + .build()) + .addChild( + MarkedSource.newBuilder() + .setPreText(name) + .setKind(MarkedSource.Kind.IDENTIFIER) + .build()) + .build()) + .build()); return node; } diff --git a/kythe/java/com/google/devtools/kythe/analyzers/java/MarkedSources.java b/kythe/java/com/google/devtools/kythe/analyzers/java/MarkedSources.java index 653a7355bb..e28b422d1b 100644 --- a/kythe/java/com/google/devtools/kythe/analyzers/java/MarkedSources.java +++ b/kythe/java/com/google/devtools/kythe/analyzers/java/MarkedSources.java @@ -16,6 +16,9 @@ package com.google.devtools.kythe.analyzers.java; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Sets; import com.google.devtools.kythe.platform.java.helpers.SignatureGenerator; import com.google.devtools.kythe.proto.MarkedSource; import com.google.devtools.kythe.proto.Storage.VName; @@ -30,6 +33,7 @@ import java.util.Optional; import java.util.function.Function; import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Modifier; import org.checkerframework.checker.nullness.qual.Nullable; /** {@link MarkedSource} utility class. */ @@ -132,6 +136,21 @@ private static MarkedSource construct( @Nullable Iterable postChildren, @Nullable MarkedSource markedType) { MarkedSource.Builder markedSource = msBuilder == null ? MarkedSource.newBuilder() : msBuilder; + ImmutableSortedSet modifiers = getModifiers(sym); + MarkedSource.Builder mods = null; + if (!modifiers.isEmpty() + || ImmutableSet.of( + ElementKind.CLASS, ElementKind.ENUM, ElementKind.INTERFACE, ElementKind.PACKAGE) + .contains(sym.getKind())) { + mods = markedSource.addChildBuilder().setPostChildText(" ").setAddFinalListToken(true); + for (Modifier m : modifiers) { + mods.addChild( + MarkedSource.newBuilder() + .setKind(MarkedSource.Kind.MODIFIER) + .setPreText(m.toString()) + .build()); + } + } if (markedType != null && sym.getKind() != ElementKind.CONSTRUCTOR) { markedSource.addChild(markedType); } @@ -163,6 +182,11 @@ private static MarkedSource construct( case ENUM: case CLASS: case INTERFACE: + mods.addChild( + MarkedSource.newBuilder() + .setKind(MarkedSource.Kind.MODIFIER) + .setPreText(sym.getKind().toString().toLowerCase()) + .build()); markedSource.addChildBuilder().setKind(MarkedSource.Kind.IDENTIFIER).setPreText(identToken); if (!sym.getTypeParameters().isEmpty()) { markedSource @@ -183,6 +207,27 @@ private static MarkedSource construct( return markedSource.build(); } + private static ImmutableSortedSet getModifiers(Symbol sym) { + ImmutableSortedSet modifiers = ImmutableSortedSet.copyOf(sym.getModifiers()); + switch (sym.getKind()) { + case ENUM: + // Remove synthesized enum modifiers + return ImmutableSortedSet.copyOf( + Sets.difference(modifiers, ImmutableSet.of(Modifier.STATIC, Modifier.FINAL))); + case INTERFACE: + // Remove synthesized interface modifiers + return ImmutableSortedSet.copyOf( + Sets.difference(modifiers, ImmutableSet.of(Modifier.ABSTRACT, Modifier.STATIC))); + case ENUM_CONSTANT: + // Remove synthesized enum constantc modifiers + return ImmutableSortedSet.copyOf( + Sets.difference( + modifiers, ImmutableSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL))); + default: + return modifiers; + } + } + /** * Sets the provided {@link MarkedSource.Builder} to a CONTEXT node, populating it with the * fully-qualified parent scope for sym. Returns the identifier corresponding to sym. diff --git a/kythe/java/com/google/devtools/kythe/doc/MarkedSourceRenderer.java b/kythe/java/com/google/devtools/kythe/doc/MarkedSourceRenderer.java index 457654cedf..8d08392b5c 100644 --- a/kythe/java/com/google/devtools/kythe/doc/MarkedSourceRenderer.java +++ b/kythe/java/com/google/devtools/kythe/doc/MarkedSourceRenderer.java @@ -31,6 +31,7 @@ /** Renders MarkedSource messages into user-printable {@link SafeHtml}. */ public class MarkedSourceRenderer { private MarkedSourceRenderer() {} + /** Don't recurse more than this many times when rendering MarkedSource. */ private static final int MAX_RENDER_DEPTH = 10; @@ -61,7 +62,10 @@ public static String renderSignatureText(MarkedSource signature) { .renderText( signature, Sets.immutableEnumSet( - MarkedSource.Kind.IDENTIFIER, MarkedSource.Kind.TYPE, MarkedSource.Kind.PARAMETER), + MarkedSource.Kind.IDENTIFIER, + MarkedSource.Kind.TYPE, + MarkedSource.Kind.PARAMETER, + MarkedSource.Kind.MODIFIER), 0); } @@ -311,6 +315,7 @@ private void append(String text) { bufferIsNonempty = true; } } + /** * Escapes and adds {@code text} before the (non-empty) text that would be added by the next * call to {@link append}. @@ -321,6 +326,7 @@ private void appendFinalListToken(String text) { } prependBuffer.append(text); } + /** * Make sure there's a space between the current content of the buffer and whatever is appended * to it later on. @@ -330,14 +336,19 @@ private void appendHeuristicSpace() { appendFinalListToken(" "); } } + /** The buffer used to hold escaped HTML data. */ private SafeHtmlBuilder htmlBuffer; + /** The buffer used to hold text data. */ private StringBuilder textBuffer; + /** True if the last character in buffer is a space. */ private boolean bufferEndsInSpace; + /** True if the buffer is non-empty. */ private boolean bufferIsNonempty; + /** * Unescaped text that should be escaped and appended before any other text is appended to the * buffer. diff --git a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/MarkedSource.java b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/MarkedSource.java index bfe7e62347..08c37f6641 100644 --- a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/MarkedSource.java +++ b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/MarkedSource.java @@ -1,5 +1,6 @@ //- @pkg ref Package -//- Package code PackageId +//- Package code PackageCode +//- PackageCode child.1 PackageId //- PackageId.kind "IDENTIFIER" //- PackageId.pre_text "pkg" package pkg; @@ -10,10 +11,10 @@ //- @MarkedSource defines/binding Class //- Class childof Package //- Class code ClassId -//- ClassId child.0 ClassCxt +//- ClassId child.1 ClassCxt //- ClassCxt child.0 ClassCxtPackage //- ClassCxtPackage.pre_text "pkg" -//- ClassId child.1 ClassTok +//- ClassId child.2 ClassTok //- ClassTok.kind "IDENTIFIER" //- ClassTok.pre_text "MarkedSource" public class MarkedSource { @@ -32,13 +33,13 @@ public class MarkedSource { //- @CONSTANT defines/binding Constant //- Constant code CMS - //- CMS child.0 ConstantType + //- CMS child.1 ConstantType //- ConstantType.kind "TYPE" - //- CMS child.1 ConstantCtx + //- CMS child.2 ConstantCtx //- ConstantCtx.kind "CONTEXT" - //- CMS child.2 ConstantIdent + //- CMS child.3 ConstantIdent //- ConstantIdent.kind "IDENTIFIER" - //- CMS child.3 ConstantInit + //- CMS child.4 ConstantInit //- ConstantInit.kind "INITIALIZER" //- ConstantInit.pre_text "\"value\"" public static final String CONSTANT = "value"; @@ -65,9 +66,9 @@ public class MarkedSource { //- Ctor typed CType //- CType param.1 Class //- Ctor code CtorTypeCxtId - //- CtorTypeCxtId child.0 CtorCxt - //- CtorTypeCxtId child.1 CtorTok - //- CtorTypeCxtId child.2 CtorParams + //- CtorTypeCxtId child.1 CtorCxt + //- CtorTypeCxtId child.2 CtorTok + //- CtorTypeCxtId child.3 CtorParams //- CtorCxt child.1 CtorCxtClass //- CtorCxtClass.pre_text "MarkedSource" //- CtorTok.pre_text "MarkedSource" @@ -315,13 +316,13 @@ static class InnerStatic { //- @field defines/binding AnonField //- AnonField childof AnonClass //- AnonClass code AnonId - //- AnonId child.0 AnonCxt + //- AnonId child.1 AnonCxt //- AnonCxt.kind "CONTEXT" //- AnonCxt child.0 PkgToken //- PkgToken.pre_text pkg //- AnonCxt child.1 MksToken //- MksToken.pre_text "MarkedSource" - //- AnonId child.1 AnonToken + //- AnonId child.2 AnonToken //- AnonToken.kind "IDENTIFIER" //- AnonToken.pre_text "(anon 1)" int field; @@ -367,7 +368,7 @@ public static Object func() { //- @LocalClass defines/binding LocalClass //- LocalClass childof Func //- LocalClass code LocalClassId - //- LocalClassId child.0 LocalClassCxt + //- LocalClassId child.1 LocalClassCxt //- LocalClassCxt child.0 LocalClassCxtPackage //- LocalClassCxtPackage.pre_text "pkg" //- LocalClassCtx child.1 LocalClassOuter @@ -376,7 +377,7 @@ public static Object func() { //- LocalClassCtx child.2 LocalClassFuncOuter //- LocalClassFuncOuter.kind "IDENTIFIER" //- LocalClassFuncOuter.pre_text "func" - //- LocalClassId child.1 LocalClassName + //- LocalClassId child.2 LocalClassName //- LocalClassName.kind "IDENTIFIER" //- LocalClassName.pre_text "LocalClass" class LocalClass {} @@ -432,10 +433,10 @@ static class Generic {} //- String code StringId //- StringId.kind "BOX" - //- StringId child.0 StringCxt + //- StringId child.1 StringCxt //- StringCxt.post_child_text "." //- StringCxt.add_final_list_token true - //- StringId child.1 StringIdToken + //- StringId child.2 StringIdToken //- StringCxt.kind "CONTEXT" //- StringCxt child.0 JavaId //- JavaId.kind "IDENTIFIER" diff --git a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/RenderedCode.java b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/RenderedCode.java index 29dadc7da6..e21b18ef94 100644 --- a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/RenderedCode.java +++ b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/RenderedCode.java @@ -1,18 +1,37 @@ +// - @pkg ref Package +// - Package.code/rendered/signature "package pkg" package pkg; // - @RenderedCode defines/binding RenderedCode +// - RenderedCode.code/rendered/signature "public final class RenderedCode" // - RenderedCode.code/rendered/qualified_name "pkg.RenderedCode" public final class RenderedCode { // - @RenderedCode defines/binding Constructor // - Constructor.code/rendered/qualified_name "pkg.RenderedCode.RenderedCode" - // - Constructor.code/rendered/signature "RenderedCode()" + // - Constructor.code/rendered/signature "private RenderedCode()" // - Constructor.code/rendered/callsite_signature "RenderedCode()" private RenderedCode() {} // - @Inner defines/binding Inner // - Inner.code/rendered/qualified_name "pkg.RenderedCode.Inner" - // - Inner.code/rendered/signature "Inner" + // - Inner.code/rendered/signature "public static class Inner" // - Inner tparam.0 T // - T.code/rendered/qualified_name "pkg.RenderedCode.Inner.T" public static class Inner {} + + // - @CONSTANT defines/binding Constant + // - Constant.code/rendered/signature "public static final String CONSTANT" + public static final String CONSTANT = "blah"; + + // - @E defines/binding E + // - E.code/rendered/signature "protected enum E" + protected enum E { + // - @VALUE defines/binding Value + // - Value.code/rendered/signature "E VALUE" + VALUE + } + + // - @I defines/binding I + // - I.code/rendered/signature "interface I" + interface I {} }