aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOskari Timperi <oskari.timperi@iki.fi>2018-04-07 10:03:26 +0300
committerOskari Timperi <oskari.timperi@iki.fi>2018-04-07 10:03:26 +0300
commitb93810afcce708a14ede034e56e1eb159aa65312 (patch)
treea140200336f749b81a258ea80dd10cf6b451664a
parent8400704ef7e2d0d981e8c6273ae1c7cdd0dc4d43 (diff)
downloadnimpb_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.nim4
-rw-r--r--src/nimpb_buildpkg/plugin.nim50
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)