@@ -100,10 +100,53 @@ void SymbolInformationBuilder::finish(bool deterministic,
100
100
}));
101
101
}
102
102
103
+ void ForwardDeclResolver::insert (SymbolSuffix suffix,
104
+ SymbolInformationBuilder *builder) {
105
+ this ->docInternalMap .emplace (suffix, SymbolInfoOrBuilderPtr{builder});
106
+ }
107
+
108
+ void ForwardDeclResolver::insert (SymbolSuffix suffix,
109
+ SymbolInformation *symbolInfo) {
110
+ this ->docInternalMap .emplace (suffix, SymbolInfoOrBuilderPtr{symbolInfo});
111
+ }
112
+
113
+ void ForwardDeclResolver::insertExternal (SymbolNameRef symbol) {
114
+ if (auto optSuffix = symbol.getPackageAgnosticSuffix ()) {
115
+ this ->externalsMap [*optSuffix].insert (symbol);
116
+ }
117
+ }
118
+
119
+ std::optional<ForwardDeclResolver::SymbolInfoOrBuilderPtr>
120
+ ForwardDeclResolver::lookupInDocuments (SymbolSuffix suffix) const {
121
+ auto it = this ->docInternalMap .find (suffix);
122
+ if (it == this ->docInternalMap .end ()) {
123
+ return {};
124
+ }
125
+ return it->second ;
126
+ }
127
+
128
+ const absl::flat_hash_set<SymbolNameRef> *
129
+ ForwardDeclResolver::lookupExternals (SymbolSuffix suffix) const {
130
+ auto it = this ->externalsMap .find (suffix);
131
+ if (it == this ->externalsMap .end ()) {
132
+ return {};
133
+ }
134
+ return &it->second ;
135
+ }
136
+
137
+ void ForwardDeclResolver::deleteExternals (SymbolSuffix suffix) {
138
+ this ->externalsMap .erase (suffix);
139
+ }
140
+
103
141
SymbolNameRef SymbolNameInterner::intern (std::string &&s) {
104
142
return SymbolNameRef{std::string_view (this ->impl .save (s))};
105
143
}
106
144
145
+ SymbolNameRef SymbolNameInterner::intern (SymbolNameRef s) {
146
+ return SymbolNameRef{
147
+ std::string_view (this ->impl .save (llvm::StringRef (s.value )))};
148
+ }
149
+
107
150
DocumentBuilder::DocumentBuilder (scip::Document &&first,
108
151
SymbolNameInterner interner)
109
152
: soFar(), interner(interner),
@@ -144,11 +187,12 @@ void DocumentBuilder::merge(scip::Document &&doc) {
144
187
}
145
188
}
146
189
147
- void DocumentBuilder::populateSymbolToInfoMap (
148
- SymbolToInfoMap &symbolToInfoMap ) {
190
+ void DocumentBuilder::populateForwardDeclResolver (
191
+ ForwardDeclResolver &forwardDeclResolver ) {
149
192
for (auto &[symbolName, symbolInfoBuilder] : this ->symbolInfos ) {
150
- symbolToInfoMap.emplace (symbolName,
151
- SymbolToInfoMap::mapped_type (&symbolInfoBuilder));
193
+ if (auto optSuffix = symbolName.getPackageAgnosticSuffix ()) {
194
+ forwardDeclResolver.insert (*optSuffix, &symbolInfoBuilder);
195
+ }
152
196
}
153
197
}
154
198
@@ -251,60 +295,92 @@ void IndexBuilder::addExternalSymbol(scip::SymbolInformation &&extSym) {
251
295
builder->mergeRelationships (std::move (*extSym.mutable_relationships ()));
252
296
}
253
297
254
- std::unique_ptr<SymbolToInfoMap> IndexBuilder::populateSymbolToInfoMap () {
298
+ std::unique_ptr<ForwardDeclResolver>
299
+ IndexBuilder::populateForwardDeclResolver () {
255
300
TRACE_EVENT (scip_clang::tracing::indexMerging,
256
- " IndexBuilder::populateSymbolToInfoMap " , " documents.size" ,
301
+ " IndexBuilder::populateForwardDeclResolver " , " documents.size" ,
257
302
this ->documents .size (), " multiplyIndexed.size" ,
258
303
this ->multiplyIndexed .size ());
259
- SymbolToInfoMap symbolToInfoMap ;
304
+ ForwardDeclResolver forwardDeclResolver ;
260
305
for (auto &document : this ->documents ) {
261
306
for (auto &symbolInfo : *document.mutable_symbols ()) {
262
- symbolToInfoMap.emplace (SymbolNameRef{symbolInfo.symbol ()},
263
- SymbolToInfoMap::mapped_type (&symbolInfo));
307
+ if (auto optSuffix =
308
+ SymbolNameRef{symbolInfo.symbol ()}.getPackageAgnosticSuffix ()) {
309
+ forwardDeclResolver.insert (*optSuffix, &symbolInfo);
310
+ }
264
311
}
265
312
}
266
313
for (auto &[_, docBuilder] : this ->multiplyIndexed ) {
267
- docBuilder->populateSymbolToInfoMap (symbolToInfoMap );
314
+ docBuilder->populateForwardDeclResolver (forwardDeclResolver );
268
315
}
269
- return std::make_unique<SymbolToInfoMap >(std::move (symbolToInfoMap ));
316
+ return std::make_unique<ForwardDeclResolver >(std::move (forwardDeclResolver ));
270
317
}
271
318
272
- void IndexBuilder::addForwardDeclaration (const SymbolToInfoMap &symbolToInfoMap,
273
- scip::ForwardDecl &&forwardDeclSym) {
274
- auto name =
275
- this ->interner .intern (std::move (*forwardDeclSym.mutable_symbol ()));
276
- auto it = symbolToInfoMap.find (name);
277
- if (it == symbolToInfoMap.end ()) {
278
- if (!this ->externalSymbols .contains (name)) {
279
- scip::SymbolInformation extSym{};
280
- *extSym.add_documentation () = std::move (forwardDeclSym.documentation ());
281
- this ->addExternalSymbolUnchecked (name, std::move (extSym));
282
- } else {
319
+ void IndexBuilder::addForwardDeclaration (
320
+ ForwardDeclResolver &forwardDeclResolver,
321
+ scip::ForwardDecl &&forwardDeclSym) {
322
+ auto suffix = SymbolSuffix{
323
+ this ->interner .intern (std::move (*forwardDeclSym.mutable_suffix ())).value };
324
+ auto optSymbolInfoOrBuilderPtr =
325
+ forwardDeclResolver.lookupInDocuments (suffix);
326
+ if (!optSymbolInfoOrBuilderPtr.has_value ()) {
327
+ if (auto *externals = forwardDeclResolver.lookupExternals (suffix)) {
283
328
// The main index confirms that this was an external symbol, which means
284
329
// that we must have seen the definition in an out-of-project file.
285
330
// In this case, just throw away the information we have,
286
331
// and rely on what we found externally as the source of truth.
332
+ ENFORCE (!externals->empty (),
333
+ " externals list for a suffix should be non-empty" );
334
+ // TODO: Log a debug warning if externals->size() > 1
335
+ for (auto symbolName : *externals) {
336
+ this ->addForwardDeclOccurrences (symbolName,
337
+ scip::ForwardDecl{forwardDeclSym});
338
+ }
339
+ } else {
340
+ scip::SymbolInformation extSym{};
341
+ // Make up a fake prefix, as we have no package information 🤷🏽
342
+ auto name = this ->interner .intern (
343
+ std::move (suffix.addFakePrefix ().asStringRefMut ()));
344
+ *extSym.add_documentation () = std::move (forwardDeclSym.documentation ());
345
+ this ->addExternalSymbolUnchecked (name, std::move (extSym));
346
+ this ->addForwardDeclOccurrences (name, std::move (forwardDeclSym));
287
347
}
288
- this ->addForwardDeclOccurrences (name, std::move (forwardDeclSym));
289
348
return ;
290
349
}
291
- auto extIt = this -> externalSymbols . find (name );
292
- if (extIt != this -> externalSymbols . end ( )) {
350
+ auto symbolInfoOrBuilderPtr = optSymbolInfoOrBuilderPtr. value ( );
351
+ if (auto *externals = forwardDeclResolver. lookupExternals (suffix )) {
293
352
// We found the symbol in a document, so the external symbols list is
294
353
// too pessimistic. This can happen when a TU processes a decl only via
295
354
// a forward decl (and hence conservatively assumes it must be external),
296
355
// but another in-project TU contains the definition.
297
356
//
298
357
// So remove the entry from the external symbols list.
299
- extIt->second ->discard ();
300
- this ->externalSymbols .erase (extIt);
358
+ for (auto name : *externals) {
359
+ auto it = this ->externalSymbols .find (name);
360
+ if (it != this ->externalSymbols .end ()) {
361
+ it->second ->discard ();
362
+ this ->externalSymbols .erase (it);
363
+ }
364
+ }
365
+ forwardDeclResolver.deleteExternals (suffix);
366
+ }
367
+ SymbolNameRef name;
368
+ if (auto *symbolInfo =
369
+ symbolInfoOrBuilderPtr.dyn_cast <scip::SymbolInformation *>()) {
370
+ name = SymbolNameRef{std::string_view (symbolInfo->symbol ())};
371
+ } else {
372
+ auto *symbolInfoBuilder =
373
+ symbolInfoOrBuilderPtr.get <SymbolInformationBuilder *>();
374
+ name = symbolInfoBuilder->name ;
301
375
}
376
+ name = this ->interner .intern (name);
302
377
if (!forwardDeclSym.documentation ().empty ()) {
303
378
// FIXME(def: better-doc-merging): The missing documentation placeholder
304
379
// value is due to a bug in the backend which seemingly came up randomly
305
380
// and also got fixed somehow. We should remove the workaround if this
306
381
// is no longer an issue.
307
- if (auto *symbolInfo = it->second .dyn_cast <scip::SymbolInformation *>()) {
382
+ if (auto *symbolInfo =
383
+ symbolInfoOrBuilderPtr.dyn_cast <scip::SymbolInformation *>()) {
308
384
bool isMissingDocumentation =
309
385
symbolInfo->documentation_size () == 0
310
386
|| (symbolInfo->documentation_size () == 1
@@ -316,7 +392,8 @@ void IndexBuilder::addForwardDeclaration(const SymbolToInfoMap &symbolToInfoMap,
316
392
std::move (*forwardDeclSym.mutable_documentation ());
317
393
}
318
394
} else {
319
- auto &symbolInfoBuilder = *it->second .get <SymbolInformationBuilder *>();
395
+ auto &symbolInfoBuilder =
396
+ *symbolInfoOrBuilderPtr.get <SymbolInformationBuilder *>();
320
397
// FIXME(def: better-doc-merging): We shouldn't drop
321
398
// documentation attached to a forward declaration.
322
399
if (!symbolInfoBuilder.hasDocumentation ()) {
0 commit comments