blob: 93ad1af0c642fb17ff4b57ce8ca0e5bfdd054b63 [file] [edit]
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart.developer;
/// Holds the source code location where an object was created, when its class
/// was annotated with `@pragma('track-creation-locations')`.
///
/// When a class definition is annotated with `@pragma('track-creation-locations')`,
/// the Dart compiler injects the call-site location into any invocation of that
/// class's or any subclass's constructors and stores it in the created object.
///
/// The location of such an object can be read by calling [CreationLocation.of]
/// with the object as the argument.
///
/// ## Example
///
/// ```dart
/// import 'dart:developer';
///
/// // Marks this and any subclass to have their constructor call-sites tracked.
/// @pragma('track-creation-locations')
/// class TargetClass {
/// TargetClass();
/// }
///
/// void main() {
/// // The source-code location of this constructor call is injected into the object.
/// final instance = TargetClass();
///
/// final location = CreationLocation.of(instance);
/// print(location); // Will print the current file path, line 11, column 20
/// }
/// ```
///
/// ## Limitations
///
/// The compiler transformation relies on injecting a named parameter into the
/// target class's constructors. Since Dart semantics do not permit a function
/// to have both optional positional parameters and named parameters simultaneously,
/// this transformation **will silently skip** any constructor that declares optional
/// positional parameters. Calling [CreationLocation.of] on an object whose
/// constructor was skipped, will return `null`.
final class CreationLocation {
/// Returns the creation location of [object].
///
/// The provided object must be an instance of a class annotated with
/// `@pragma('track-creation-locations')`.
static CreationLocation? of(Object? object) {
if (object is _HasCreationLocation) {
return object._location;
}
return null;
}
const CreationLocation._({
required this.file,
required this.line,
required this.column,
this.name,
});
/// File path of the location.
final String file;
/// 1-based line number.
final int line;
/// 1-based column number.
final int column;
/// Optional name of the parameter or function at this location.
final String? name;
/// JSON representation of this location.
Map<String, Object?> toJsonMap() {
return <String, Object?>{
'file': file,
'line': line,
'column': column,
'name': name,
};
}
@override
String toString() => <String>[?name, file, '$line', '$column'].join(':');
}
/// Interface for classes that track the source code location their
/// constructor was called from.
abstract interface class _HasCreationLocation {
/// The location where the constructor was called.
CreationLocation? _location;
}