| // 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; | |
| } |