Skip to content

Commit

Permalink
Sanitize generated comments (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanvanburen authored Apr 26, 2023
1 parent 7e61ceb commit c6b9ba1
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2022-2023 Buf Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package buf.evilcomments.v1;

message EvilCommentsRequest {}

message EvilCommentsResponse {}

service EvilCommentsService {
// This comment contains characters that should be escaped.
// @ is valid in KDoc, but not in proto.
// Comments in KDoc use C-style block comments, so */ and /* should be escaped.
// [ and ] characters should also be escaped.
rpc EvilComments(EvilCommentsRequest) returns (EvilCommentsResponse) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class Generator : CodeGenerator {
val interfaceBuilder = TypeSpec.interfaceBuilder(serviceClientInterfaceClassName(packageName, service))
val functionSpecs = interfaceMethods(service.methods, sourceInfo)
return interfaceBuilder
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addFunctions(functionSpecs)
.build()
}
Expand All @@ -144,7 +144,7 @@ class Generator : CodeGenerator {
val outputClassName = classNameFromType(method.outputType)
if (method.isClientStreaming && method.isServerStreaming) {
val streamingBuilder = FunSpec.builder(method.name.lowerCamelCase())
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addModifiers(KModifier.ABSTRACT)
.addModifiers(KModifier.SUSPEND)
.addParameter(headerParameterSpec)
Expand All @@ -155,7 +155,7 @@ class Generator : CodeGenerator {
functions.add(streamingBuilder.build())
} else if (method.isServerStreaming) {
val serverStreamingFunction = FunSpec.builder(method.name.lowerCamelCase())
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addModifiers(KModifier.ABSTRACT)
.addModifiers(KModifier.SUSPEND)
.addParameter(headerParameterSpec)
Expand All @@ -166,7 +166,7 @@ class Generator : CodeGenerator {
functions.add(serverStreamingFunction)
} else if (method.isClientStreaming) {
val clientStreamingFunction = FunSpec.builder(method.name.lowerCamelCase())
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addModifiers(KModifier.ABSTRACT)
.addModifiers(KModifier.SUSPEND)
.addParameter(headerParameterSpec)
Expand All @@ -178,7 +178,7 @@ class Generator : CodeGenerator {
} else {
if (configuration.generateCoroutineMethods) {
val unarySuspendFunction = FunSpec.builder(method.name.lowerCamelCase())
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addModifiers(KModifier.ABSTRACT)
.addModifiers(KModifier.SUSPEND)
.addParameter("request", inputClassName)
Expand All @@ -194,7 +194,7 @@ class Generator : CodeGenerator {
returnType = Unit::class.java.asTypeName()
)
val unaryCallbackFunction = FunSpec.builder(method.name.lowerCamelCase())
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addModifiers(KModifier.ABSTRACT)
.addParameter("request", inputClassName)
.addParameter(headerParameterSpec)
Expand Down Expand Up @@ -228,7 +228,7 @@ class Generator : CodeGenerator {
)
val functionSpecs = implementationMethods(service.methods, sourceInfo)
return classBuilder
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addFunctions(functionSpecs)
.build()
}
Expand All @@ -252,7 +252,7 @@ class Generator : CodeGenerator {
.build()
if (method.isClientStreaming && method.isServerStreaming) {
val streamingFunction = FunSpec.builder(method.name.lowerCamelCase())
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addModifiers(KModifier.OVERRIDE)
.addModifiers(KModifier.SUSPEND)
.addParameter("headers", HEADERS_CLASS_NAME)
Expand All @@ -278,7 +278,7 @@ class Generator : CodeGenerator {
functions.add(streamingFunction)
} else if (method.isServerStreaming) {
val serverStreamingFunction = FunSpec.builder(method.name.lowerCamelCase())
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addModifiers(KModifier.OVERRIDE)
.addModifiers(KModifier.SUSPEND)
.addParameter("headers", HEADERS_CLASS_NAME)
Expand All @@ -300,7 +300,7 @@ class Generator : CodeGenerator {
functions.add(serverStreamingFunction)
} else if (method.isClientStreaming) {
val clientStreamingFunction = FunSpec.builder(method.name.lowerCamelCase())
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addModifiers(KModifier.OVERRIDE)
.addModifiers(KModifier.SUSPEND)
.addParameter("headers", HEADERS_CLASS_NAME)
Expand All @@ -323,7 +323,7 @@ class Generator : CodeGenerator {
} else {
if (configuration.generateCoroutineMethods) {
val unarySuspendFunction = FunSpec.builder(method.name.lowerCamelCase())
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addModifiers(KModifier.SUSPEND)
.addModifiers(KModifier.OVERRIDE)
.addParameter("request", inputClassName)
Expand All @@ -350,7 +350,7 @@ class Generator : CodeGenerator {
returnType = Unit::class.java.asTypeName()
)
val unaryCallbackFunction = FunSpec.builder(method.name.lowerCamelCase())
.addKdoc(sourceInfo.comment())
.addKdoc(sourceInfo.comment().sanitizeKdoc())
.addModifiers(KModifier.OVERRIDE)
.addParameter("request", inputClassName)
.addParameter("headers", HEADERS_CLASS_NAME)
Expand Down Expand Up @@ -396,6 +396,18 @@ class Generator : CodeGenerator {
}
return ClassName(packageName, names.first())
}

internal fun String.sanitizeKdoc(): String {
return this
// Remove trailing whitespace on each line.
.replace("[^\\S\n]+\n".toRegex(), "\n")
.replace("\\s+$".toRegex(), "")
.replace("\\*/".toRegex(), "*/")
.replace("/\\*".toRegex(), "/*")
.replace("""[""", "[")
.replace("""]""", "]")
.replace("@", "@")
}
}

private fun serviceClientInterfaceClassName(packageName: String, service: Descriptors.ServiceDescriptor): ClassName {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import buf.evilcomments.v1.EvilCommentsServiceClient
import buf.javamultiplefiles.disabled.v1.DisabledEmptyOuterClass
import buf.javamultiplefiles.disabled.v1.DisabledEmptyServiceClient
import buf.javamultiplefiles.disabled.v1.DisabledInnerMessageServiceClient
Expand Down Expand Up @@ -107,4 +108,9 @@ class PluginGenerationTest {
}
}
}

@Test
fun evilCommentsCompiles() {
val client = EvilCommentsServiceClient(mock { })
}
}

0 comments on commit c6b9ba1

Please sign in to comment.