| 3259 | } |
| 3260 | |
| 3261 | CheckedError Parser::DoParse(const char *source, const char **include_paths, |
| 3262 | const char *source_filename, |
| 3263 | const char *include_filename) { |
| 3264 | uint64_t source_hash = 0; |
| 3265 | if (source_filename) { |
| 3266 | // If the file is in-memory, don't include its contents in the hash as we |
| 3267 | // won't be able to load them later. |
| 3268 | if (FileExists(source_filename)) |
| 3269 | source_hash = HashFile(source_filename, source); |
| 3270 | else |
| 3271 | source_hash = HashFile(source_filename, nullptr); |
| 3272 | |
| 3273 | if (included_files_.find(source_hash) == included_files_.end()) { |
| 3274 | included_files_[source_hash] = include_filename ? include_filename : ""; |
| 3275 | files_included_per_file_[source_filename] = std::set<std::string>(); |
| 3276 | } else { |
| 3277 | return NoError(); |
| 3278 | } |
| 3279 | } |
| 3280 | if (!include_paths) { |
| 3281 | static const char *current_directory[] = { "", nullptr }; |
| 3282 | include_paths = current_directory; |
| 3283 | } |
| 3284 | field_stack_.clear(); |
| 3285 | builder_.Clear(); |
| 3286 | // Start with a blank namespace just in case this file doesn't have one. |
| 3287 | current_namespace_ = empty_namespace_; |
| 3288 | |
| 3289 | ECHECK(StartParseFile(source, source_filename)); |
| 3290 | |
| 3291 | // Includes must come before type declarations: |
| 3292 | for (;;) { |
| 3293 | // Parse pre-include proto statements if any: |
| 3294 | if (opts.proto_mode && (attribute_ == "option" || attribute_ == "syntax" || |
| 3295 | attribute_ == "package")) { |
| 3296 | ECHECK(ParseProtoDecl()); |
| 3297 | } else if (IsIdent("native_include")) { |
| 3298 | NEXT(); |
| 3299 | vector_emplace_back(&native_included_files_, attribute_); |
| 3300 | EXPECT(kTokenStringConstant); |
| 3301 | EXPECT(';'); |
| 3302 | } else if (IsIdent("include") || (opts.proto_mode && IsIdent("import"))) { |
| 3303 | NEXT(); |
| 3304 | if (opts.proto_mode && attribute_ == "public") NEXT(); |
| 3305 | auto name = flatbuffers::PosixPath(attribute_.c_str()); |
| 3306 | EXPECT(kTokenStringConstant); |
| 3307 | // Look for the file relative to the directory of the current file. |
| 3308 | std::string filepath; |
| 3309 | if (source_filename) { |
| 3310 | auto source_file_directory = |
| 3311 | flatbuffers::StripFileName(source_filename); |
| 3312 | filepath = flatbuffers::ConCatPathFileName(source_file_directory, name); |
| 3313 | } |
| 3314 | if (filepath.empty() || !FileExists(filepath.c_str())) { |
| 3315 | // Look for the file in include_paths. |
| 3316 | for (auto paths = include_paths; paths && *paths; paths++) { |
| 3317 | filepath = flatbuffers::ConCatPathFileName(*paths, name); |
| 3318 | if (FileExists(filepath.c_str())) break; |
nothing calls this directly
no test coverage detected