protostar 0.1.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +60 -0
- data/LICENSE.txt +21 -0
- data/README.md +647 -0
- data/THIRD_PARTY_NOTICES.md +61 -0
- data/exe/protoc-gen-protostar +7 -0
- data/exe/protostar +7 -0
- data/lib/protostar/builder/generator.rb +71 -0
- data/lib/protostar/builder/sink.rb +35 -0
- data/lib/protostar/builder.rb +965 -0
- data/lib/protostar/cli.rb +267 -0
- data/lib/protostar/codec/decode_generator.rb +199 -0
- data/lib/protostar/codec/decoder.rb +296 -0
- data/lib/protostar/codec/encode_generator.rb +224 -0
- data/lib/protostar/codec/encoder.rb +121 -0
- data/lib/protostar/codec/sizer.rb +91 -0
- data/lib/protostar/codec.rb +15 -0
- data/lib/protostar/compiler/ast.rb +193 -0
- data/lib/protostar/compiler/emitters/descriptor_set.rb +57 -0
- data/lib/protostar/compiler/emitters/google_ruby.rb +103 -0
- data/lib/protostar/compiler/emitters/grpc.rb +175 -0
- data/lib/protostar/compiler/emitters/protostar_rbs.rb +252 -0
- data/lib/protostar/compiler/emitters/rbs.rb +394 -0
- data/lib/protostar/compiler/emitters/ruby.rb +503 -0
- data/lib/protostar/compiler/emitters.rb +268 -0
- data/lib/protostar/compiler/include/LICENSE +32 -0
- data/lib/protostar/compiler/include/google/protobuf/any.proto +106 -0
- data/lib/protostar/compiler/include/google/protobuf/api.proto +229 -0
- data/lib/protostar/compiler/include/google/protobuf/compiler/plugin.proto +180 -0
- data/lib/protostar/compiler/include/google/protobuf/cpp_features.proto +87 -0
- data/lib/protostar/compiler/include/google/protobuf/descriptor.proto +1532 -0
- data/lib/protostar/compiler/include/google/protobuf/duration.proto +115 -0
- data/lib/protostar/compiler/include/google/protobuf/empty.proto +51 -0
- data/lib/protostar/compiler/include/google/protobuf/field_mask.proto +243 -0
- data/lib/protostar/compiler/include/google/protobuf/java_features.proto +132 -0
- data/lib/protostar/compiler/include/google/protobuf/source_context.proto +48 -0
- data/lib/protostar/compiler/include/google/protobuf/struct.proto +111 -0
- data/lib/protostar/compiler/include/google/protobuf/timestamp.proto +145 -0
- data/lib/protostar/compiler/include/google/protobuf/type.proto +217 -0
- data/lib/protostar/compiler/include/google/protobuf/wrappers.proto +157 -0
- data/lib/protostar/compiler/lexer.rb +659 -0
- data/lib/protostar/compiler/linker.rb +894 -0
- data/lib/protostar/compiler/option_interpreter.rb +363 -0
- data/lib/protostar/compiler/parser.rb +1696 -0
- data/lib/protostar/compiler/retention.rb +104 -0
- data/lib/protostar/compiler/run.rb +184 -0
- data/lib/protostar/compiler/source_info.rb +161 -0
- data/lib/protostar/compiler/symbol_table.rb +223 -0
- data/lib/protostar/compiler/text_format.rb +340 -0
- data/lib/protostar/compiler/validator.rb +944 -0
- data/lib/protostar/compiler.rb +304 -0
- data/lib/protostar/diagnostics/codes.rb +1307 -0
- data/lib/protostar/diagnostics/formats.rb +64 -0
- data/lib/protostar/diagnostics/renderer.rb +240 -0
- data/lib/protostar/diagnostics/source.rb +153 -0
- data/lib/protostar/diagnostics.rb +117 -0
- data/lib/protostar/dsl.rb +367 -0
- data/lib/protostar/enum.rb +70 -0
- data/lib/protostar/errors.rb +23 -0
- data/lib/protostar/google/protobuf/any_pb.rb +90 -0
- data/lib/protostar/google/protobuf/api_pb.rb +199 -0
- data/lib/protostar/google/protobuf/compiler/plugin_pb.rb +168 -0
- data/lib/protostar/google/protobuf/descriptor_pb.rb +1239 -0
- data/lib/protostar/google/protobuf/duration_pb.rb +99 -0
- data/lib/protostar/google/protobuf/empty_pb.rb +36 -0
- data/lib/protostar/google/protobuf/field_mask_pb.rb +228 -0
- data/lib/protostar/google/protobuf/source_context_pb.rb +33 -0
- data/lib/protostar/google/protobuf/struct_pb.rb +91 -0
- data/lib/protostar/google/protobuf/timestamp_pb.rb +129 -0
- data/lib/protostar/google/protobuf/type_pb.rb +202 -0
- data/lib/protostar/google/protobuf/wrappers_pb.rb +125 -0
- data/lib/protostar/google_protobuf_shim.rb +24 -0
- data/lib/protostar/json/encoder.rb +340 -0
- data/lib/protostar/json/errors.rb +34 -0
- data/lib/protostar/json/parser.rb +437 -0
- data/lib/protostar/json/path.rb +39 -0
- data/lib/protostar/json.rb +95 -0
- data/lib/protostar/lint/command.rb +197 -0
- data/lib/protostar/lint/config.rb +98 -0
- data/lib/protostar/lint/context.rb +126 -0
- data/lib/protostar/lint/directives.rb +56 -0
- data/lib/protostar/lint/fixer.rb +165 -0
- data/lib/protostar/lint/naming.rb +54 -0
- data/lib/protostar/lint/rule.rb +120 -0
- data/lib/protostar/lint/rules/comment_enum.rb +31 -0
- data/lib/protostar/lint/rules/comment_enum_value.rb +32 -0
- data/lib/protostar/lint/rules/comment_field.rb +33 -0
- data/lib/protostar/lint/rules/comment_message.rb +31 -0
- data/lib/protostar/lint/rules/comment_rpc.rb +31 -0
- data/lib/protostar/lint/rules/comment_service.rb +31 -0
- data/lib/protostar/lint/rules/edition_recommended.rb +31 -0
- data/lib/protostar/lint/rules/enum_first_value_zero.rb +34 -0
- data/lib/protostar/lint/rules/enum_pascal_case.rb +25 -0
- data/lib/protostar/lint/rules/enum_value_prefix.rb +38 -0
- data/lib/protostar/lint/rules/enum_value_upper_snake_case.rb +28 -0
- data/lib/protostar/lint/rules/enum_zero_value_suffix.rb +41 -0
- data/lib/protostar/lint/rules/field_lower_snake_case.rb +34 -0
- data/lib/protostar/lint/rules/field_not_required.rb +39 -0
- data/lib/protostar/lint/rules/field_number_reuse_risk.rb +45 -0
- data/lib/protostar/lint/rules/field_numbers_hot_range.rb +44 -0
- data/lib/protostar/lint/rules/file_lower_snake_case.rb +27 -0
- data/lib/protostar/lint/rules/import_no_public.rb +29 -0
- data/lib/protostar/lint/rules/import_no_weak.rb +28 -0
- data/lib/protostar/lint/rules/import_used.rb +33 -0
- data/lib/protostar/lint/rules/message_pascal_case.rb +27 -0
- data/lib/protostar/lint/rules/no_deprecated_features.rb +50 -0
- data/lib/protostar/lint/rules/no_groups.rb +34 -0
- data/lib/protostar/lint/rules/oneof_lower_snake_case.rb +27 -0
- data/lib/protostar/lint/rules/package_defined.rb +28 -0
- data/lib/protostar/lint/rules/package_directory_match.rb +33 -0
- data/lib/protostar/lint/rules/package_lower_snake_case.rb +28 -0
- data/lib/protostar/lint/rules/package_same_directory.rb +39 -0
- data/lib/protostar/lint/rules/package_version_suffix.rb +31 -0
- data/lib/protostar/lint/rules/reserved_names_with_numbers.rb +44 -0
- data/lib/protostar/lint/rules/rpc_pascal_case.rb +25 -0
- data/lib/protostar/lint/rules/rpc_request_response_unique.rb +40 -0
- data/lib/protostar/lint/rules/rpc_request_standard_name.rb +32 -0
- data/lib/protostar/lint/rules/rpc_response_standard_name.rb +31 -0
- data/lib/protostar/lint/rules/service_pascal_case.rb +25 -0
- data/lib/protostar/lint/rules/service_suffix.rb +28 -0
- data/lib/protostar/lint/rules/syntax_specified.rb +35 -0
- data/lib/protostar/lint/runner.rb +135 -0
- data/lib/protostar/lint.rb +122 -0
- data/lib/protostar/message/accessors.rb +86 -0
- data/lib/protostar/message/coercion.rb +171 -0
- data/lib/protostar/message/field_info.rb +145 -0
- data/lib/protostar/message/reflection.rb +149 -0
- data/lib/protostar/message.rb +572 -0
- data/lib/protostar/plugin.rb +94 -0
- data/lib/protostar/schema/default_value.rb +113 -0
- data/lib/protostar/schema/descriptor.rb +41 -0
- data/lib/protostar/schema/draft/copy.rb +88 -0
- data/lib/protostar/schema/draft/resolution.rb +177 -0
- data/lib/protostar/schema/draft.rb +779 -0
- data/lib/protostar/schema/enum.rb +106 -0
- data/lib/protostar/schema/extension_range.rb +37 -0
- data/lib/protostar/schema/features.rb +153 -0
- data/lib/protostar/schema/field.rb +201 -0
- data/lib/protostar/schema/file.rb +217 -0
- data/lib/protostar/schema/freezer.rb +61 -0
- data/lib/protostar/schema/message.rb +104 -0
- data/lib/protostar/schema/oneof.rb +38 -0
- data/lib/protostar/schema/options.rb +367 -0
- data/lib/protostar/schema/pool.rb +179 -0
- data/lib/protostar/schema/proto.rb +576 -0
- data/lib/protostar/schema/resolver.rb +118 -0
- data/lib/protostar/schema/service.rb +89 -0
- data/lib/protostar/schema/source_info.rb +53 -0
- data/lib/protostar/schema.rb +65 -0
- data/lib/protostar/short_names/any.rb +7 -0
- data/lib/protostar/short_names/duration.rb +7 -0
- data/lib/protostar/short_names/empty.rb +7 -0
- data/lib/protostar/short_names/field_mask.rb +7 -0
- data/lib/protostar/short_names/struct.rb +9 -0
- data/lib/protostar/short_names/timestamp.rb +7 -0
- data/lib/protostar/short_names/wrappers.rb +15 -0
- data/lib/protostar/text/extensions.rb +114 -0
- data/lib/protostar/text/parser.rb +439 -0
- data/lib/protostar/text/printer.rb +304 -0
- data/lib/protostar/text/tokenizer.rb +116 -0
- data/lib/protostar/text.rb +67 -0
- data/lib/protostar/types.rb +152 -0
- data/lib/protostar/unknown_field.rb +58 -0
- data/lib/protostar/version.rb +5 -0
- data/lib/protostar/view/generator.rb +298 -0
- data/lib/protostar/view/map.rb +194 -0
- data/lib/protostar/view/repeated.rb +143 -0
- data/lib/protostar/view/scan.rb +183 -0
- data/lib/protostar/view.rb +283 -0
- data/lib/protostar/well_known/any.rb +52 -0
- data/lib/protostar/well_known/duration.rb +53 -0
- data/lib/protostar/well_known/list_value.rb +63 -0
- data/lib/protostar/well_known/struct.rb +55 -0
- data/lib/protostar/well_known/timestamp.rb +64 -0
- data/lib/protostar/well_known/value.rb +60 -0
- data/lib/protostar/well_known.rb +38 -0
- data/lib/protostar/wire/io_source.rb +40 -0
- data/lib/protostar/wire/reader.rb +254 -0
- data/lib/protostar/wire/writer.rb +201 -0
- data/lib/protostar/wire.rb +96 -0
- data/lib/protostar.rb +95 -0
- data/shims/google-protobuf/lib/google/protobuf/any_pb.rb +17 -0
- data/shims/google-protobuf/lib/google/protobuf/api_pb.rb +22 -0
- data/shims/google-protobuf/lib/google/protobuf/compiler/plugin_pb.rb +25 -0
- data/shims/google-protobuf/lib/google/protobuf/descriptor_pb.rb +72 -0
- data/shims/google-protobuf/lib/google/protobuf/descriptor_pool.rb +164 -0
- data/shims/google-protobuf/lib/google/protobuf/descriptors.rb +553 -0
- data/shims/google-protobuf/lib/google/protobuf/duration_pb.rb +17 -0
- data/shims/google-protobuf/lib/google/protobuf/empty_pb.rb +17 -0
- data/shims/google-protobuf/lib/google/protobuf/field_mask_pb.rb +17 -0
- data/shims/google-protobuf/lib/google/protobuf/internal/convert.rb +180 -0
- data/shims/google-protobuf/lib/google/protobuf/internal/extensions.rb +154 -0
- data/shims/google-protobuf/lib/google/protobuf/internal/json.rb +104 -0
- data/shims/google-protobuf/lib/google/protobuf/internal/well_known.rb +140 -0
- data/shims/google-protobuf/lib/google/protobuf/map.rb +216 -0
- data/shims/google-protobuf/lib/google/protobuf/message.rb +544 -0
- data/shims/google-protobuf/lib/google/protobuf/message_exts.rb +41 -0
- data/shims/google-protobuf/lib/google/protobuf/plugin_pb.rb +4 -0
- data/shims/google-protobuf/lib/google/protobuf/repeated_field.rb +366 -0
- data/shims/google-protobuf/lib/google/protobuf/source_context_pb.rb +17 -0
- data/shims/google-protobuf/lib/google/protobuf/struct_pb.rb +20 -0
- data/shims/google-protobuf/lib/google/protobuf/timestamp_pb.rb +17 -0
- data/shims/google-protobuf/lib/google/protobuf/type_pb.rb +27 -0
- data/shims/google-protobuf/lib/google/protobuf/well_known_types.rb +37 -0
- data/shims/google-protobuf/lib/google/protobuf/wrappers_pb.rb +25 -0
- data/shims/google-protobuf/lib/google/protobuf.rb +107 -0
- data/shims/google-protobuf/lib/google/protobuf_ffi.rb +5 -0
- data/shims/google-protobuf/lib/google/protobuf_native.rb +5 -0
- data/sig/protostar/google/protobuf/any_pb.rbs +77 -0
- data/sig/protostar/google/protobuf/api_pb.rbs +242 -0
- data/sig/protostar/google/protobuf/compiler/plugin_pb.rbs +264 -0
- data/sig/protostar/google/protobuf/descriptor_pb.rbs +2220 -0
- data/sig/protostar/google/protobuf/duration_pb.rbs +82 -0
- data/sig/protostar/google/protobuf/empty_pb.rbs +18 -0
- data/sig/protostar/google/protobuf/field_mask_pb.rbs +170 -0
- data/sig/protostar/google/protobuf/source_context_pb.rbs +24 -0
- data/sig/protostar/google/protobuf/struct_pb.rbs +135 -0
- data/sig/protostar/google/protobuf/timestamp_pb.rbs +102 -0
- data/sig/protostar/google/protobuf/type_pb.rbs +304 -0
- data/sig/protostar/google/protobuf/wrappers_pb.rbs +169 -0
- data/sig/protostar/lint.rbs +216 -0
- data/sig/protostar.rbs +326 -0
- metadata +366 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Protostar
|
|
4
|
+
# A pure-Ruby protoc front end: turns `.proto` source into
|
|
5
|
+
# {Protostar::Schema::File}s whose `to_proto` is what protoc 36.2 puts in a
|
|
6
|
+
# `FileDescriptorProto`, and rejects what protoc rejects with protoc's
|
|
7
|
+
# `file:line:col: message` diagnostics.
|
|
8
|
+
#
|
|
9
|
+
# compiler = Protostar::Compiler.new(include_paths: ["proto"])
|
|
10
|
+
# files = compiler.compile(["foo/bar.proto"], source_info: true)
|
|
11
|
+
class Compiler
|
|
12
|
+
# Where the bundled `google/protobuf/*.proto` imports live
|
|
13
|
+
INCLUDE_DIR = ::File.expand_path("compiler/include", __dir__)
|
|
14
|
+
|
|
15
|
+
autoload :Lexer, ::File.expand_path("compiler/lexer", __dir__)
|
|
16
|
+
autoload :AST, ::File.expand_path("compiler/ast", __dir__)
|
|
17
|
+
autoload :SourceInfo, ::File.expand_path("compiler/source_info", __dir__)
|
|
18
|
+
autoload :Parser, ::File.expand_path("compiler/parser", __dir__)
|
|
19
|
+
autoload :SymbolTable, ::File.expand_path("compiler/symbol_table", __dir__)
|
|
20
|
+
autoload :Linker, ::File.expand_path("compiler/linker", __dir__)
|
|
21
|
+
autoload :OptionInterpreter, ::File.expand_path("compiler/option_interpreter", __dir__)
|
|
22
|
+
autoload :TextFormat, ::File.expand_path("compiler/text_format", __dir__)
|
|
23
|
+
autoload :Validator, ::File.expand_path("compiler/validator", __dir__)
|
|
24
|
+
autoload :Retention, ::File.expand_path("compiler/retention", __dir__)
|
|
25
|
+
autoload :Run, ::File.expand_path("compiler/run", __dir__)
|
|
26
|
+
autoload :Emitters, ::File.expand_path("compiler/emitters", __dir__)
|
|
27
|
+
|
|
28
|
+
# One error or warning, with protoc's 1-based line and column (nil when
|
|
29
|
+
# protoc reports none). {#to_s} and {#format} print it as protoc does; the
|
|
30
|
+
# rest is for {Diagnostics::Renderer}, which prints it as rustc would.
|
|
31
|
+
class Diagnostic
|
|
32
|
+
# @return [String] the file name as imported
|
|
33
|
+
attr_reader :file
|
|
34
|
+
# @return [Integer, nil]
|
|
35
|
+
attr_reader :line
|
|
36
|
+
# @return [Integer, nil]
|
|
37
|
+
attr_reader :column
|
|
38
|
+
# @return [String]
|
|
39
|
+
attr_reader :message
|
|
40
|
+
# @return [Symbol] :error or :warning
|
|
41
|
+
attr_reader :severity
|
|
42
|
+
# @return [String, nil] the file on disk, spelled as protoc prints it: the include
|
|
43
|
+
# path as given (canonicalized) joined with {#file}; nil for in-memory and bundled files
|
|
44
|
+
attr_reader :path
|
|
45
|
+
# @return [Array<Diagnostics::Span>] the primary span first, then related ones; empty
|
|
46
|
+
# when the compiler knows only {#line} and {#column}, or nothing
|
|
47
|
+
attr_reader :spans
|
|
48
|
+
# @return [Array<String>] `help:` lines, the concrete fix in words
|
|
49
|
+
attr_reader :help
|
|
50
|
+
# @return [Array<String>] `note:` lines
|
|
51
|
+
attr_reader :notes
|
|
52
|
+
# @return [Diagnostics::Fix, nil] a mechanical fix `protostar lint --fix` can apply
|
|
53
|
+
attr_reader :fix
|
|
54
|
+
# @return [String, nil] the lint rule that found it, e.g. "FIELD_NOT_REQUIRED"
|
|
55
|
+
attr_reader :rule
|
|
56
|
+
|
|
57
|
+
def initialize(file, line, column, message, severity = :error, path: nil, spans: [], code: nil, title: nil,
|
|
58
|
+
help: [], notes: [], fix: nil, rule: nil)
|
|
59
|
+
@file = file
|
|
60
|
+
@line = line
|
|
61
|
+
@column = column
|
|
62
|
+
@message = message
|
|
63
|
+
@severity = severity
|
|
64
|
+
@path = path
|
|
65
|
+
@spans = spans.freeze
|
|
66
|
+
@code = code
|
|
67
|
+
@title = title
|
|
68
|
+
@help = help.freeze
|
|
69
|
+
@notes = notes.freeze
|
|
70
|
+
@fix = fix
|
|
71
|
+
@rule = rule
|
|
72
|
+
freeze
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @return [String, nil] the stable code `protostar lint --explain` knows, e.g. "L0201";
|
|
76
|
+
# for the compiler's messages, looked up in {Diagnostics::Codes}
|
|
77
|
+
def code
|
|
78
|
+
@code || Diagnostics::Codes.lookup(@message)&.code
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @return [String] the headline the renderer prints: a short rewording where the
|
|
82
|
+
# catalogue has one, else {#message}
|
|
83
|
+
def title
|
|
84
|
+
@title || @message
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @return [Diagnostic] a copy with what {Diagnostics::Codes} knows about the message
|
|
88
|
+
# filled in: code, title, span labels, help and notes
|
|
89
|
+
def annotated
|
|
90
|
+
@code ? self : Diagnostics::Codes.annotate(self)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# @return [Diagnostic] a copy with the given attributes replaced
|
|
94
|
+
def with(**changes)
|
|
95
|
+
attrs = {path: @path, spans: @spans, code: @code, title: @title, help: @help, notes: @notes, fix: @fix,
|
|
96
|
+
rule: @rule}.merge(changes)
|
|
97
|
+
Diagnostic.new(@file, @line, @column, @message, @severity, **attrs)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def error?
|
|
101
|
+
@severity == :error
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def warning?
|
|
105
|
+
@severity == :warning
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# @return [String] as protoc prints it, with the virtual file name
|
|
109
|
+
def to_s
|
|
110
|
+
location = @line ? "#{@file}:#{@line}:#{@column}" : @file
|
|
111
|
+
warning? ? "#{location}: warning: #{@message}" : "#{location}: #{@message}"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# @param error_format [Symbol] :gcc or :msvs, protoc's `--error_format`
|
|
115
|
+
# @return [String] as protoc's command line prints it: the path on disk when known
|
|
116
|
+
def format(error_format = :gcc)
|
|
117
|
+
name = @path || @file
|
|
118
|
+
location = if @line.nil?
|
|
119
|
+
name
|
|
120
|
+
elsif error_format == :msvs
|
|
121
|
+
"#{name}(#{@line}) : #{@severity} in column=#{@column}"
|
|
122
|
+
else
|
|
123
|
+
"#{name}:#{@line}:#{@column}"
|
|
124
|
+
end
|
|
125
|
+
warning? ? "#{location}: warning: #{@message}" : "#{location}: #{@message}"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def ==(other)
|
|
129
|
+
other.is_a?(Diagnostic) && other.to_s == to_s
|
|
130
|
+
end
|
|
131
|
+
alias_method :eql?, :==
|
|
132
|
+
|
|
133
|
+
def hash
|
|
134
|
+
to_s.hash
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def inspect
|
|
138
|
+
"#<#{self.class.name} #{self}>"
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Raised when compilation fails
|
|
143
|
+
class Error < Protostar::Error
|
|
144
|
+
# @return [Array<Diagnostic>] every error found, in protoc's order
|
|
145
|
+
attr_reader :diagnostics
|
|
146
|
+
|
|
147
|
+
def initialize(diagnostics)
|
|
148
|
+
@diagnostics = diagnostics.freeze
|
|
149
|
+
super(diagnostics.join("\n"))
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# @return [Schema::Pool] where compiled files go and imports are looked up
|
|
154
|
+
attr_reader :pool
|
|
155
|
+
# @return [Array<String>] directories searched for imports, in order, before the bundled includes
|
|
156
|
+
attr_reader :include_paths
|
|
157
|
+
# @return [Array<Diagnostic>] warnings (and errors) of the last {#compile}
|
|
158
|
+
attr_reader :diagnostics
|
|
159
|
+
|
|
160
|
+
# @param include_paths [Array<String>] directories to resolve `.proto` names against, in order
|
|
161
|
+
# @param pool [Schema::Pool] receives every compiled file; files already in it are reused
|
|
162
|
+
# @param bundled_includes [Boolean] search the bundled `google/protobuf/*.proto` after `include_paths`
|
|
163
|
+
def initialize(include_paths: [], pool: Schema::Pool.new, bundled_includes: true)
|
|
164
|
+
@given_paths = include_paths.map { |p| Compiler.canonical_path(p) }.freeze
|
|
165
|
+
@include_paths = include_paths.map { |p| ::File.expand_path(p) }.freeze
|
|
166
|
+
@include_paths += [INCLUDE_DIR] if bundled_includes
|
|
167
|
+
@pool = pool
|
|
168
|
+
@diagnostics = []
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Compiles `.proto` files and everything they import.
|
|
172
|
+
#
|
|
173
|
+
# The pool keeps every option, as protoc's own pool does, so later files
|
|
174
|
+
# are validated against the full declarations. What is returned is what
|
|
175
|
+
# protoc writes with `--descriptor_set_out`: options declared
|
|
176
|
+
# `retention = RETENTION_SOURCE` removed (pass `retain_options: true`
|
|
177
|
+
# for the pool's files as they are).
|
|
178
|
+
#
|
|
179
|
+
# @param names [Array<String>] file names relative to an include path, e.g. "foo/bar.proto"
|
|
180
|
+
# @param source_info [Boolean] keep `source_code_info` in the built files
|
|
181
|
+
# @param retain_options [Boolean] return the pool's files, source-retention options included
|
|
182
|
+
# @param sources [Hash{String => String}] file contents by name, consulted before the include paths
|
|
183
|
+
# @param protoc_cli [Boolean] @api private: false checks like a bare DescriptorPool rather than
|
|
184
|
+
# protoc's command line (no imports loaded from disk, no unused import, naming style or other
|
|
185
|
+
# command-line checks), as protoc's own parser tests do
|
|
186
|
+
# @return [Array<Schema::File>] the named files and their transitive imports, imports first
|
|
187
|
+
# @raise [Error] with every diagnostic when a file cannot be compiled
|
|
188
|
+
def compile(names, source_info: false, retain_options: false, sources: {}, protoc_cli: true)
|
|
189
|
+
run = Run.new(self, names, source_info, sources: sources, protoc_cli: protoc_cli)
|
|
190
|
+
files = run.call
|
|
191
|
+
@diagnostics = run.diagnostics
|
|
192
|
+
raise Error.new(run.diagnostics) if run.failed?
|
|
193
|
+
retain_options ? files : files.map { |f| output_file(f) }
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Same as {#compile}, each file as `to_proto.to_h`, for reading
|
|
197
|
+
# @deprecated Goes away in 0.2.0. Use {#compile} and read the {Schema::File}s, or
|
|
198
|
+
# `compile(names).map { |f| f.to_proto.to_h }` for the same Hashes.
|
|
199
|
+
# @return [Array<Hash>]
|
|
200
|
+
def compile_to_hashes(names, source_info: false, retain_options: false, sources: {})
|
|
201
|
+
Protostar.deprecated("Compiler#compile_to_hashes", "compile(names).map { |f| f.to_proto.to_h }")
|
|
202
|
+
compile(names, source_info: source_info, retain_options: retain_options, sources: sources).map(&:to_h)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# @param name [String] a virtual file name
|
|
206
|
+
# @return [String, nil] the path it resolves to on disk
|
|
207
|
+
def resolve(name)
|
|
208
|
+
@include_paths.each do |dir|
|
|
209
|
+
path = ::File.join(dir, name)
|
|
210
|
+
return path if ::File.file?(path)
|
|
211
|
+
end
|
|
212
|
+
nil
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# @param name [String] a virtual file name
|
|
216
|
+
# @return [String, nil] where it is on disk, spelled from the include path as it
|
|
217
|
+
# was given, as protoc prints it in diagnostics; nil when not under one
|
|
218
|
+
def disk_path(name)
|
|
219
|
+
@given_paths.each_with_index do |given, i|
|
|
220
|
+
next unless ::File.file?(::File.join(@include_paths[i], name))
|
|
221
|
+
return given.empty? ? name : "#{given}/#{name}"
|
|
222
|
+
end
|
|
223
|
+
nil
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# protoc's CanonicalizePath: "." components, empty components and a
|
|
227
|
+
# trailing slash dropped
|
|
228
|
+
# @api private
|
|
229
|
+
def self.canonical_path(path)
|
|
230
|
+
parts = path.split("/").reject { |p| p.empty? || p == "." }
|
|
231
|
+
path.start_with?("/") ? "/#{parts.join("/")}" : parts.join("/")
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# The options message protoc compiles into itself, from the bundled
|
|
235
|
+
# descriptor.proto, for files that do not import descriptor.proto
|
|
236
|
+
# @api private
|
|
237
|
+
def builtin_options_type(name)
|
|
238
|
+
@builtin ||= begin
|
|
239
|
+
builtin = Compiler.new(include_paths: [], pool: Schema::Pool.new)
|
|
240
|
+
builtin.compile(["google/protobuf/descriptor.proto"]).last
|
|
241
|
+
end
|
|
242
|
+
@builtin.find_message(name)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# The source-retention-stripped copy of a pool file, linked against the
|
|
246
|
+
# stripped copies of its imports
|
|
247
|
+
def output_file(file)
|
|
248
|
+
@output ||= Schema::Pool.new
|
|
249
|
+
existing = @output.file(file.name)
|
|
250
|
+
return existing if existing
|
|
251
|
+
file.dependency_files.each { |dep| output_file(dep) }
|
|
252
|
+
options_type = ->(name) { @pool.find_message(name) || builtin_options_type(name) }
|
|
253
|
+
@output.add(Retention.strip(file, @output, options_type), warn: false)
|
|
254
|
+
end
|
|
255
|
+
private :output_file
|
|
256
|
+
|
|
257
|
+
# protoc's SimpleDtoa: the shortest of %.15g and %.17g that reads back exactly
|
|
258
|
+
# @api private
|
|
259
|
+
def self.simple_dtoa(value)
|
|
260
|
+
Schema::DefaultValue.simple_dtoa(value)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# protoc's SimpleFtoa over the float nearest to `value`
|
|
264
|
+
# @api private
|
|
265
|
+
def self.simple_ftoa(value)
|
|
266
|
+
return "inf" if value == Float::INFINITY
|
|
267
|
+
return "-inf" if value == -Float::INFINITY
|
|
268
|
+
return "nan" if value.nan?
|
|
269
|
+
single = [value].pack("e").unpack1("e")
|
|
270
|
+
text = format("%.6g", single)
|
|
271
|
+
parsed = Float(text)
|
|
272
|
+
unless parsed.finite? && [parsed].pack("e").unpack1("e") == single && strtof_in_range?(parsed)
|
|
273
|
+
text = format("%.9g", single)
|
|
274
|
+
end
|
|
275
|
+
text
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# strtof reports ERANGE for values that overflow or flush to zero
|
|
279
|
+
def self.strtof_in_range?(value)
|
|
280
|
+
return true if value == 0.0
|
|
281
|
+
single = [value].pack("e").unpack1("e")
|
|
282
|
+
single.finite? && single.abs >= 1.1754943508222875e-38
|
|
283
|
+
end
|
|
284
|
+
private_class_method :strtof_in_range?
|
|
285
|
+
|
|
286
|
+
C_ESCAPES = {10 => "\\n", 13 => "\\r", 9 => "\\t", 34 => "\\\"", 39 => "\\'", 92 => "\\\\"}.freeze
|
|
287
|
+
|
|
288
|
+
# absl::CEscape: protoc's spelling of bytes defaults
|
|
289
|
+
# @api private
|
|
290
|
+
def self.c_escape(bytes)
|
|
291
|
+
out = +""
|
|
292
|
+
bytes.each_byte do |b|
|
|
293
|
+
out << if (escaped = C_ESCAPES[b])
|
|
294
|
+
escaped
|
|
295
|
+
elsif b < 32 || b >= 127
|
|
296
|
+
format("\\%03o", b)
|
|
297
|
+
else
|
|
298
|
+
b
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
out
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|