From 047b4ff0d569e12df7e1d42626decb2b1e43cc6c Mon Sep 17 00:00:00 2001 From: Milan Pavlik Date: Thu, 19 Apr 2018 07:12:32 +0100 Subject: [PATCH] Fix replace all bug in filePathFromProtoWithoutExtension (#56) --- src/index.ts | 19 +++++++++++-------- src/service/grpcweb.ts | 6 +++--- src/ts/fileDescriptorTSD.ts | 4 ++-- src/util.ts | 10 +++++++--- test/ts_test/src/util.ts | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 test/ts_test/src/util.ts diff --git a/src/index.ts b/src/index.ts index 2d9fd001..f626d072 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,16 +1,19 @@ -/** - * This is the ProtoC compiler plugin. - * - * It only accepts stdin/stdout output according to the protocol - * specified in [plugin.proto](https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/plugin.proto). - */ import {printFileDescriptorTSD} from "./ts/fileDescriptorTSD"; import {ExportMap} from "./ExportMap"; -import {filePathFromProtoWithoutExtension, withAllStdIn} from "./util"; +import {replaceProtoSuffix, withAllStdIn} from "./util"; import {CodeGeneratorRequest, CodeGeneratorResponse} from "google-protobuf/google/protobuf/compiler/plugin_pb"; import {FileDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb"; import {generateGrpcWebService} from "./service/grpcweb"; +/** + * This is the ProtoC compiler plugin. + * + * The Protocol Buffers Compiler can be extended to [support new languages via plugins](https://developers.google.com/protocol-buffers/docs/reference/other). + * A plugin is just a program which reads a CodeGeneratorRequest protocol buffer from standard input + * and then writes a CodeGeneratorResponse protocol buffer to standard output. + * These message types are defined in [plugin.proto](https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/plugin.proto). + * + */ withAllStdIn((inputBuff: Buffer) => { try { const typedInputBuff = new Uint8Array(inputBuff.length); @@ -30,7 +33,7 @@ withAllStdIn((inputBuff: Buffer) => { }); codeGenRequest.getFileToGenerateList().forEach(fileName => { - const outputFileName = filePathFromProtoWithoutExtension(fileName); + const outputFileName = replaceProtoSuffix(fileName); const thisFile = new CodeGeneratorResponse.File(); thisFile.setName(outputFileName + ".d.ts"); thisFile.setContent(printFileDescriptorTSD(fileNameToDescriptor[fileName], exportMap)); diff --git a/src/service/grpcweb.ts b/src/service/grpcweb.ts index cbce24ed..b9aa29ae 100644 --- a/src/service/grpcweb.ts +++ b/src/service/grpcweb.ts @@ -1,4 +1,4 @@ -import {filePathToPseudoNamespace, filePathFromProtoWithoutExtension, getPathToRoot} from "../util"; +import {filePathToPseudoNamespace, replaceProtoSuffix, getPathToRoot} from "../util"; import {ExportMap} from "../ExportMap"; import {Printer} from "../Printer"; import {CodePrinter} from "../CodePrinter"; @@ -134,13 +134,13 @@ class GrpcWebServiceDescriptor { } else { return { namespace, - path: `${this.pathToRoot}${filePathFromProtoWithoutExtension(filePathFromProtoWithoutExtension(dependency))}` + path: `${this.pathToRoot}${replaceProtoSuffix(replaceProtoSuffix(dependency))}` } } }); const hostProto = { namespace: filePathToPseudoNamespace(this.filename), - path: `${this.pathToRoot}${filePathFromProtoWithoutExtension(this.filename)}`, + path: `${this.pathToRoot}${replaceProtoSuffix(this.filename)}`, }; return [ hostProto ].concat(dependencies); } diff --git a/src/ts/fileDescriptorTSD.ts b/src/ts/fileDescriptorTSD.ts index 3ecb17b5..b824a7ed 100644 --- a/src/ts/fileDescriptorTSD.ts +++ b/src/ts/fileDescriptorTSD.ts @@ -1,4 +1,4 @@ -import {filePathToPseudoNamespace, filePathFromProtoWithoutExtension, getPathToRoot} from "../util"; +import {filePathToPseudoNamespace, replaceProtoSuffix, getPathToRoot} from "../util"; import {ExportMap} from "../ExportMap"; import {Printer} from "../Printer"; import {FileDescriptorProto} from "google-protobuf/google/protobuf/descriptor_pb"; @@ -26,7 +26,7 @@ export function printFileDescriptorTSD(fileDescriptor: FileDescriptorProto, expo if (dependency in WellKnownTypesMap) { printer.printLn(`import * as ${pseudoNamespace} from "${WellKnownTypesMap[dependency]}";`); } else { - const filePath = filePathFromProtoWithoutExtension(dependency); + const filePath = replaceProtoSuffix(dependency); printer.printLn(`import * as ${pseudoNamespace} from "${upToRoot}${filePath}";`); } }); diff --git a/src/util.ts b/src/util.ts index d523085f..d8e8b524 100644 --- a/src/util.ts +++ b/src/util.ts @@ -5,7 +5,7 @@ export function filePathToPseudoNamespace(filePath: string): string { } export function snakeToCamel(str: string): string { - return str.replace(/(\_\w)/g, function(m){ + return str.replace(/(\_\w)/g, function(m) { return m[1].toUpperCase(); }); } @@ -41,8 +41,12 @@ export function withinNamespaceFromExportEntry(name: string, exportEntry: Export return exportEntry.pkg ? name.substring(exportEntry.pkg.length + 1) : name; } -export function filePathFromProtoWithoutExtension(protoFilePath: string): string { - return protoFilePath.replace(".proto", "_pb"); +export function replaceProtoSuffix(protoFilePath: string): string { + const suffix = ".proto"; + const hasProtoSuffix = protoFilePath.slice(protoFilePath.length - suffix.length) === suffix; + return hasProtoSuffix + ? protoFilePath.slice(0, -suffix.length) + "_pb" + : protoFilePath; } export function withAllStdIn(callback: (buffer: Buffer) => void): void { diff --git a/test/ts_test/src/util.ts b/test/ts_test/src/util.ts new file mode 100644 index 00000000..dc4db30f --- /dev/null +++ b/test/ts_test/src/util.ts @@ -0,0 +1,33 @@ +import {assert} from "chai"; +import {replaceProtoSuffix} from "../../../src/util"; + +describe("util", () => { + + describe("replaceProtoSuffix", () => { + [{ + in: "github.com/improbable-eng/ts-protoc-gen/test/proto/examplecom/enum_message.proto", + out: "github.com/improbable-eng/ts-protoc-gen/test/proto/examplecom/enum_message_pb", + }, { + in: "enum_message.proto", + out: "enum_message_pb", + }, { + in: "enum_message.js", + out: "enum_message.js", + }, { + in: ".proto/enum_message.proto", + out: ".proto/enum_message_pb", + }, { + in: "protos/.proto/enum_message.proto", + out: "protos/.proto/enum_message_pb", + }, { + in: "", + out: "", + }].forEach(scenario => { + it(`should map '${scenario.in}' to '${scenario.out}'`, () => { + const actual = replaceProtoSuffix(scenario.in) + assert.equal(actual, scenario.out) + }) + }) + }); + +}); \ No newline at end of file