diff options
| author | Oskari Timperi <oskari.timperi@iki.fi> | 2018-04-07 10:03:26 +0300 |
|---|---|---|
| committer | Oskari Timperi <oskari.timperi@iki.fi> | 2018-04-07 10:03:26 +0300 |
| commit | b93810afcce708a14ede034e56e1eb159aa65312 (patch) | |
| tree | a140200336f749b81a258ea80dd10cf6b451664a | |
| parent | 8400704ef7e2d0d981e8c6273ae1c7cdd0dc4d43 (diff) | |
| download | nimpb_protoc-b93810afcce708a14ede034e56e1eb159aa65312.tar.gz nimpb_protoc-b93810afcce708a14ede034e56e1eb159aa65312.zip | |
Fix default values for enums in dependencies
The compiler crashed because it didn't have a default value for an enum defined
in another file. Now the compiler finds the definition of the enum when asked
for a default value of an enum.
| -rw-r--r-- | src/nimpb_build.nim | 4 | ||||
| -rw-r--r-- | src/nimpb_buildpkg/plugin.nim | 50 |
2 files changed, 42 insertions, 12 deletions
diff --git a/src/nimpb_build.nim b/src/nimpb_build.nim index 8ab8396..3effaca 100644 --- a/src/nimpb_build.nim +++ b/src/nimpb_build.nim @@ -67,7 +67,7 @@ proc compileProtos*(protos: openArray[string], var outputFilename = myTempDir() / "file-descriptor-set" createDir(myTempDir()) - # add(args, "--include_imports") + add(args, "--include_imports") add(args, "--include_source_info") add(args, &"-o{outputFilename}") @@ -88,7 +88,7 @@ proc compileProtos*(protos: openArray[string], if rc != 0: raise newException(Exception, outp) - processFileDescriptorSet(outputFilename, outdir) + processFileDescriptorSet(outputFilename, outdir, protos) when isMainModule: diff --git a/src/nimpb_buildpkg/plugin.nim b/src/nimpb_buildpkg/plugin.nim index 9555ced..dcb90c7 100644 --- a/src/nimpb_buildpkg/plugin.nim +++ b/src/nimpb_buildpkg/plugin.nim @@ -51,6 +51,7 @@ type enums: seq[Enum] messages: seq[Message] syntax: Syntax + dependencies: seq[ProtoFile] Syntax {.pure.} = enum Proto2 @@ -180,6 +181,15 @@ proc defaultValue(ftype: google_protobuf_FieldDescriptorProto_Type): string = of google_protobuf_FieldDescriptorProtoType.TypeSInt32: result = "0" of google_protobuf_FieldDescriptorProtoType.TypeSInt64: result = "0" +proc findEnum(file: ProtoFile, typeName: string): Enum = + for e in file.enums: + if $e.names == typeName: + return e + for dep in file.dependencies: + result = findEnum(dep, typeName) + if result != nil: + break + proc defaultValue(field: Field): string = if field.defaultValue != nil: if isEnum(field): @@ -193,10 +203,11 @@ proc defaultValue(field: Field): string = elif isRepeated(field): return "@[]" elif isEnum(field): - for e in field.message.file.enums: - if $e.names == field.typeName: - result = e.defaultValue - break + let e = findEnum(field.message.file, field.typeName) + if e != nil: + result = e.defaultValue + else: + result = &"cast[{field.typeName}](0)" else: result = defaultValue(field.ftype) @@ -478,6 +489,7 @@ proc parseFile(name: string, fdesc: google_protobuf_FileDescriptorProto): ProtoF result.fdesc = fdesc result.messages = @[] result.enums = @[] + result.dependencies = @[] if hasSyntax(fdesc): if fdesc.syntax == "proto2": @@ -857,7 +869,7 @@ iterator genProcs(msg: Message): string = yield indent(&"result = read{msg.names}(pbs)", 4) yield "" -proc processFile(fdesc: google_protobuf_FileDescriptorProto): ProcessedFile = +proc processFile(fdesc: google_protobuf_FileDescriptorProto, otherFiles: TableRef[string, ProtoFile]): ProcessedFile = var (dir, name, _) = splitFile(fdesc.name) var pbfilename = (dir / name) & "_pb.nim" @@ -869,6 +881,10 @@ proc processFile(fdesc: google_protobuf_FileDescriptorProto): ProcessedFile = let parsed = parseFile(fdesc.name, fdesc) + for dep in fdesc.dependency: + if dep in otherFiles: + add(parsed.dependencies, otherFiles[dep]) + var hasMaps = false for message in parsed.messages: let tmp = fixMapEntry(parsed, message) @@ -917,15 +933,29 @@ proc processFile(fdesc: google_protobuf_FileDescriptorProto): ProcessedFile = addLine(result.data, line) addLine(result.data, "") -proc processFileDescriptorSet*(filename: string, outdir: string) = +proc processFileDescriptorSet*(filename: string, outdir: string, + protos: openArray[string]) = let s = newProtobufStream(newFileStream(filename, fmRead)) let fileSet = readgoogle_protobuf_FileDescriptorSet(s) + var otherFiles = newTable[string, ProtoFile]() + for file in fileSet.file: - let parsedFile = processFile(file) - let fullPath = outdir / parsedFile.name + add(otherFiles, file.name, parseFile(file.name, file)) + + # Protoc does not provide full paths for files in FileDescriptorSet. So it + # can be that fileSet.file.name might match any file in protos. So we will + # try to match the bare name and the named joined with the path of the first + # file. + let basePath = parentDir(protos[0]) + + for file in fileSet.file: + if (file.name in protos) or ((basePath / file.name) in protos): + let processedFile = processFile(file, otherFiles) + + let fullPath = outdir / processedFile.name - createDir(parentDir(fullPath)) + createDir(parentDir(fullPath)) - writeFile(fullPath, parsedFile.data) + writeFile(fullPath, processedFile.data) |
