| 
 | 1 | +// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file  | 
 | 2 | +// for details. All rights reserved. Use of this source code is governed by a  | 
 | 3 | +// BSD-style license that can be found in the LICENSE file.  | 
 | 4 | + | 
 | 5 | +/// This is a temporary utility script that moves entries from  | 
 | 6 | +/// `pkg/front_end/messages.yaml` to a new  | 
 | 7 | +/// `pkg/_fe_analyzer_shared/messages.yaml` file.  | 
 | 8 | +///  | 
 | 9 | +/// Only messages that are actually shared (those with an `index` parameter) are  | 
 | 10 | +/// moved.  | 
 | 11 | +library;  | 
 | 12 | + | 
 | 13 | +import 'dart:io';  | 
 | 14 | + | 
 | 15 | +import 'package:analyzer_plugin/protocol/protocol_common.dart';  | 
 | 16 | +import 'package:analyzer_testing/package_root.dart' as pkg_root;  | 
 | 17 | +import 'package:analyzer_utilities/messages.dart';  | 
 | 18 | +import 'package:collection/collection.dart';  | 
 | 19 | +import 'package:path/path.dart';  | 
 | 20 | +import 'package:source_span/src/location.dart';  | 
 | 21 | +import 'package:yaml/yaml.dart';  | 
 | 22 | + | 
 | 23 | +void main() {  | 
 | 24 | +  Map<Uri, _EditAccumulator> editAccumulators = {};  | 
 | 25 | +  var sharedYamlContents = StringBuffer('''  | 
 | 26 | +# Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file  | 
 | 27 | +# for details. All rights reserved. Use of this source code is governed by a  | 
 | 28 | +# BSD-style license that can be found in the LICENSE file.  | 
 | 29 | +
  | 
 | 30 | +# This file contains error messages that are shared between the analyzer and the  | 
 | 31 | +# front end.  | 
 | 32 | +
  | 
 | 33 | +# See pkg/front_end/messages.yaml for documentation about this file.  | 
 | 34 | +
  | 
 | 35 | +# Currently, the code generation logic uses the presence of an `index` entry to  | 
 | 36 | +# determine whether a given error message should be generated into both the  | 
 | 37 | +# analyzer and the front end, so all error messages in this file should have a  | 
 | 38 | +# non-null `index`.  | 
 | 39 | +# TODO(paulberry): remove the need for the `index` field.  | 
 | 40 | +
  | 
 | 41 | +''');  | 
 | 42 | + | 
 | 43 | +  for (var MapEntry(key: name, value: message) in frontEndMessages.entries) {  | 
 | 44 | +    if (message.index != null) {  | 
 | 45 | +      var node = message.yamlNode!;  | 
 | 46 | +      sharedYamlContents.write('$name:\n  ${node.span.text}');  | 
 | 47 | +      var uri = node.span.sourceUrl!;  | 
 | 48 | +      (editAccumulators[uri] ??= _EditAccumulator(uri)).deleteMessage(node);  | 
 | 49 | +    }  | 
 | 50 | +  }  | 
 | 51 | +  for (var editAccumulator in editAccumulators.values) {  | 
 | 52 | +    editAccumulator.apply();  | 
 | 53 | +  }  | 
 | 54 | +  File(  | 
 | 55 | +    join(pkg_root.packageRoot, '_fe_analyzer_shared', 'messages.yaml'),  | 
 | 56 | +  ).writeAsStringSync(sharedYamlContents.toString());  | 
 | 57 | +}  | 
 | 58 | + | 
 | 59 | +class _EditAccumulator {  | 
 | 60 | +  final File _file;  | 
 | 61 | +  final Set<int> _nodeOffsetsToDelete = {};  | 
 | 62 | +  late final content = _file.readAsStringSync();  | 
 | 63 | + | 
 | 64 | +  _EditAccumulator(Uri uri) : _file = File(uri.toFilePath());  | 
 | 65 | + | 
 | 66 | +  void apply() {  | 
 | 67 | +    if (_nodeOffsetsToDelete.isEmpty) return;  | 
 | 68 | +    var document = loadYamlDocument(content);  | 
 | 69 | +    var edits = <SourceEdit>[];  | 
 | 70 | +    for (var entry in (document.contents as YamlMap).nodes.entries) {  | 
 | 71 | +      if (_nodeOffsetsToDelete.contains(entry.value.span.start.offset)) {  | 
 | 72 | +        var deletionStart = _startOfLine((entry.key as YamlScalar).span.start);  | 
 | 73 | +        var deletionEnd = entry.value.span.end.offset;  | 
 | 74 | +        edits.add(SourceEdit(deletionStart, deletionEnd - deletionStart, ''));  | 
 | 75 | +      }  | 
 | 76 | +    }  | 
 | 77 | +    edits.sortBy((e) => -e.offset);  | 
 | 78 | +    var newContent = SourceEdit.applySequence(content, edits);  | 
 | 79 | +    _file.writeAsStringSync(newContent);  | 
 | 80 | +    _nodeOffsetsToDelete.clear();  | 
 | 81 | +  }  | 
 | 82 | + | 
 | 83 | +  void deleteMessage(YamlNode node) {  | 
 | 84 | +    _nodeOffsetsToDelete.add(node.span.start.offset);  | 
 | 85 | +  }  | 
 | 86 | + | 
 | 87 | +  int _startOfLine(SourceLocation start) =>  | 
 | 88 | +      content.lastIndexOf('\n', start.offset) + 1;  | 
 | 89 | +}  | 
0 commit comments