d4t_formulas/.pub-cache/hosted/pub.dev/analyzer-7.7.1/example/ddd16.dart
Álvaro González 1d339653d5 feat: add formula data classes with strict JSON parsing
- Add VariableSpec class with magnitude field validation
- Add Formula class supporting multiple input/output variables
- Support d4rt_code as string or object with code field
- Add comprehensive tests for parsing and serialization
- Fix broken test import in pruebas_d4rt_test.dart

Follows README.md format requirements exactly
2025-08-21 17:15:00 +02:00

321 lines
9.2 KiB
Dart

import 'dart:developer' as developer;
import 'dart:io' as io;
import 'dart:typed_data';
import 'package:analyzer/file_system/overlay_file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver_event.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:heap_snapshot/analysis.dart';
import 'package:heap_snapshot/format.dart';
import 'package:linter/src/rules.dart';
import 'package:vm_service/vm_service.dart';
void main() async {
var resourceProvider = OverlayResourceProvider(
PhysicalResourceProvider.INSTANCE,
);
registerLintRules();
var byteStore = NullByteStore();
var packageRootPath = '/Users/scheglov/dart/admin-portal';
var libPath = '$packageRootPath/lib';
// var builder = PackageConfigFileBuilder()
// ..add(
// name: 'test',
// rootPath: packageRootPath,
// );
//
// resourceProvider.setOverlay(
// '$packageRootPath/.dart_tool/package_config.json',
// content: builder.toContent(
// toUriStr: (path) {
// var pathContext = resourceProvider.pathContext;
// return pathContext.toUri(path).toString();
// },
// ),
// modificationStamp: 0,
// );
var modelPath = '$libPath/data/models/group_model.dart';
var modelCode = resourceProvider.getFile(modelPath).readAsStringSync();
var collection = AnalysisContextCollectionImpl(
resourceProvider: resourceProvider,
// includedPaths: [libPath],
includedPaths: [
'/Users/scheglov/dart/admin-portal/lib/data/models/group_model.dart',
'/Users/scheglov/dart/admin-portal/lib/utils/formatting.dart',
'/Users/scheglov/dart/admin-portal/lib/redux/company/company_selectors.dart',
],
byteStore: byteStore,
performanceLog: PerformanceLog(io.stdout),
drainStreams: false,
);
var analysisContext = collection.contextFor(modelPath);
for (var path in analysisContext.contextRoot.analyzedFiles()) {
if (path.endsWith('.dart')) {
analysisContext.driver.addFile(path);
}
}
analysisContext.driver.scheduler.events.listen((event) {
switch (event) {
case AnalyzeFile analyzeFile:
print('[events][analyzeFile][file: ${analyzeFile.file}]');
case ResolvedUnitResultImpl unitResult:
print('[events][resolvedUnit][file: ${unitResult.file}]');
print(' [events][errors: ${unitResult.errors}]');
default:
print('[events][event: $event]');
}
});
await collection.scheduler.waitForIdle();
await pumpEventQueue();
print('\n' * 2);
print('[S] Now idle');
print('-' * 64);
{
var heapBytes = _getHeapSnapshot();
_analyzeSnapshot(heapBytes);
}
print('\n' * 2);
print('[S] Printed heap analysis');
print('-' * 64);
resourceProvider.setOverlay(
modelPath,
content: modelCode.replaceAll(
'bool get hasCurrency =>',
'bool get hasCurrency2 =>',
),
modificationStamp: 1,
);
analysisContext.changeFile(modelPath);
print('[S] hasCurrency -> hasCurrency2');
print('\n' * 2);
await collection.scheduler.waitForIdle();
await pumpEventQueue();
print('\n' * 2);
print('[S] Now idle');
print('-' * 64);
resourceProvider.setOverlay(
modelPath,
content: modelCode.replaceAll(
'bool get hasCurrency2 =>',
'bool get hasCurrency =>',
),
modificationStamp: 2,
);
analysisContext.changeFile(modelPath);
print('[S] hasCurrency2 -> hasCurrency');
print('\n' * 2);
await collection.scheduler.waitForIdle();
await pumpEventQueue();
print('\n' * 2);
print('[S] Now idle');
print('-' * 64);
resourceProvider.setOverlay(
modelPath,
content: modelCode.replaceAll(
'bool get hasCurrency =>',
'bool get hasCurrency2 =>',
),
modificationStamp: 3,
);
analysisContext.changeFile(modelPath);
print('[S] hasCurrency -> hasCurrency2');
print('\n' * 2);
await collection.scheduler.waitForIdle();
await pumpEventQueue();
print('\n' * 2);
print('[S] Now idle');
print('-' * 64);
print('[S] Disposing...');
await collection.dispose();
}
final Stopwatch timer = Stopwatch();
Future pumpEventQueue([int times = 5000]) {
if (times == 0) return Future.value();
return Future.delayed(Duration.zero, () => pumpEventQueue(times - 1));
}
void _analyzeSnapshot(Uint8List bytes) {
timer.reset();
var graph = HeapSnapshotGraph.fromChunks([
bytes.buffer.asByteData(bytes.offsetInBytes, bytes.length),
]);
print('[+${timer.elapsedMilliseconds} ms] Create HeapSnapshotGraph');
var analysis = Analysis(graph);
// Computing reachable objects takes some time.
timer.reset();
analysis.reachableObjects;
print('[+${timer.elapsedMilliseconds} ms] Compute reachable objects');
print('');
// {
// var measure = analysis.measureObjects(analysis.reachableObjects);
// allResults.add(
// BenchmarkResultCompound(name: 'reachableObjects', children: [
// BenchmarkResultCount(
// name: 'count',
// value: measure.count,
// ),
// BenchmarkResultBytes(
// name: 'size',
// value: measure.size,
// ),
// ]),
// );
// }
// It is interesting to see all reachable objects.
{
print('Reachable objects');
var objects = analysis.reachableObjects;
analysis.printObjectStats(objects, maxLines: 100);
}
// {
// print('\n\n');
// print('Tokens');
// print('Instances of: _GrowableList');
// final objectList = analysis.filter(analysis.reachableObjects, (object) {
// return object.klass.libraryUri == Uri.parse('dart:core') &&
// object.klass.name == '_GrowableList';
// // return analysis.variableLengthOf(object) == 0;
// });
//
// // final objectList = analysis.filterByClassPatterns(
// // analysis.reachableObjects,
// // ['_GrowableList'],
// // );
// final stats = analysis.generateObjectStats(objectList);
// print(formatHeapStats(stats, maxLines: 20));
// print('');
//
// const maxEntries = 10;
// final paths = analysis.retainingPathsOf(objectList, 10);
// for (int i = 0; i < paths.length; ++i) {
// if (maxEntries != -1 && i >= maxEntries) break;
// final path = paths[i];
// print('There are ${path.count} retaining paths of');
// print(formatRetainingPath(analysis.graph, paths[i]));
// print('');
// }
// }
// timer.reset();
//
// allResults.add(
// _doUniqueUriStr(analysis),
// );
//
// allResults.add(
// _doInterfaceType(analysis),
// );
//
// allResults.add(
// _doLinkedData(analysis),
// );
//
// print('[+${timer.elapsedMilliseconds} ms] Compute benchmark results');
// print('');
//
// return allResults;
}
Uint8List _getHeapSnapshot() {
timer.reset();
var tmpDir = io.Directory.systemTemp.createTempSync('analyzer_heap');
try {
var snapshotFile = io.File('${tmpDir.path}/0.heap_snapshot');
developer.NativeRuntime.writeHeapSnapshotToFile(snapshotFile.path);
print('[+${timer.elapsedMilliseconds} ms] Write heap snapshot');
timer.reset();
var bytes = snapshotFile.readAsBytesSync();
print(
'[+${timer.elapsedMilliseconds} ms] '
'Read heap snapshot, ${bytes.length ~/ (1024 * 1024)} MB',
);
return bytes;
} finally {
tmpDir.deleteSync(recursive: true);
}
}
extension on Analysis {
// IntSet classByPredicate(bool Function(HeapSnapshotClass) predicate) {
// var allClasses = graph.classes;
// var classSet = SpecializedIntSet(allClasses.length);
// for (var class_ in allClasses) {
// if (predicate(class_)) {
// classSet.add(class_.classId);
// }
// }
// return classSet;
// }
// IntSet filterByClass(
// IntSet objectIds, {
// required Uri libraryUri,
// required String name,
// }) {
// var cid = graph.classes.singleWhere((class_) {
// return class_.libraryUri == libraryUri && class_.name == name;
// }).classId;
// return filter(objectIds, (object) => object.classId == cid);
// }
// _ObjectSetMeasure measureObjects(IntSet objectIds) {
// var stats = generateObjectStats(objectIds);
// var totalSize = 0;
// var totalCount = 0;
// for (var class_ in stats.classes) {
// totalCount += stats.counts[class_.classId];
// totalSize += stats.sizes[class_.classId];
// }
// return _ObjectSetMeasure(count: totalCount, size: totalSize);
// }
void printObjectStats(IntSet objectIds, {int maxLines = 20}) {
var stats = generateObjectStats(objectIds);
print(formatHeapStats(stats, maxLines: maxLines));
print('');
}
// ignore: unused_element
void printRetainers(IntSet objectIds, {int maxEntries = 3}) {
var paths = retainingPathsOf(objectIds, 20);
for (int i = 0; i < paths.length; ++i) {
if (i >= maxEntries) break;
var path = paths[i];
print('There are ${path.count} retaining paths of');
print(formatRetainingPath(graph, paths[i]));
print('');
}
}
}
// class _ObjectSetMeasure {
// final int count;
// final int size;
//
// _ObjectSetMeasure({required this.count, required this.size});
// }