getDeclarationRef method
DeclarationRef?
getDeclarationRef(})
Looks up a declaration reference for an identifier.
This method resolves an identifier to its declaration, handling imports, exports, and re-exports correctly.
identifier is the name of the identifier to look up.
importingSrc is the asset that is importing the identifier.
importPrefix is an optional import prefix (e.g., 'prefix' in 'prefix.identifier').
Throws IdentifierNotFoundError if the identifier cannot be resolved.
Implementation
DeclarationRef? getDeclarationRef(
String identifier,
Asset importingSrc, {
String? importPrefix,
}) {
DeclarationRef buildRef(
MapEntry<String, int> srcEntry, {
String? providerId,
}) {
return DeclarationRef(
identifier: identifier,
srcId: srcEntry.key,
srcUri: uriForAsset(srcEntry.key),
providerId: providerId ?? srcEntry.key,
type: ReferenceType.fromValue(srcEntry.value),
importingLibrary: importingSrc,
importPrefix: importPrefix,
);
}
final Map<String, int> possibleSrcs = Map<String, int>.fromEntries(
identifiers
.where(
(List<dynamic> e) => e[GraphIndex.identifierName] == identifier,
)
.map(
(List<dynamic> e) => MapEntry<String, int>(
e[GraphIndex.identifierSrc],
e[GraphIndex.identifierType],
),
),
);
final String actualSrc = getParentSrc(importingSrc.id);
// First check if the identifier is declared directly in this file
for (final MapEntry<String, int> entry in possibleSrcs.entries) {
if (entry.key == importingSrc.id || entry.key == actualSrc) {
return buildRef(entry, providerId: actualSrc);
}
}
// Check all imports of the source file
final List<List<Object?>> fileImports = <List<Object?>>[
...importsOf(importingSrc.id),
if (assets.containsKey(_coreImportId)) _coreImport,
];
for (final List<Object?> importEntry in fileImports) {
final String importedFileSrc = importEntry[GraphIndex.directiveSrc] as String;
final String? prefix = importEntry.elementAtOrNull(GraphIndex.directivePrefix) as String?;
if (importPrefix != null && importPrefix != prefix) continue;
// Skip if the identifier is hidden
final List<dynamic> hides = importEntry[GraphIndex.directiveHide] as List<dynamic>? ?? const <dynamic>[];
if (hides.contains(identifier)) continue;
// Skip if the identifier is not shown
final List<dynamic> shows = importEntry[GraphIndex.directiveShow] as List<dynamic>? ?? const <dynamic>[];
if (shows.isNotEmpty && !shows.contains(identifier)) continue;
// Check if the imported file directly declares the identifier
for (final MapEntry<String, int> entry in possibleSrcs.entries) {
if (entry.key == importedFileSrc) {
return buildRef(entry, providerId: importedFileSrc);
}
}
}
for (final List<Object?> importEntry in fileImports) {
final String importedFileSrc = importEntry[GraphIndex.directiveSrc] as String;
final Set<String> visitedSrcs = <String>{};
final String? src = _traceExportsOf(
importedFileSrc,
identifier,
possibleSrcs.keys,
visitedSrcs,
);
if (src != null) {
final MapEntry<String, int> srcEntry = possibleSrcs.entries.firstWhere(
(MapEntry<String, int> k) => k.key == src,
);
return buildRef(srcEntry, providerId: importedFileSrc);
}
}
return null;
}