Files
sdk/pkg/analysis_server/tool/spec/codegen_dart_notification_handler.dart
Paul Berry afcfbbeba8 Migrate developer experience packages to new constructor decl syntax.
(Part of https://github.com/dart-lang/sdk/issues/63288)

This change migrates the packages owned by the developer experience
team to use the new constructor declaration syntax, described in
https://github.com/dart-lang/language/blob/main/accepted/future-releases/primary-constructors/feature-specification.md#abbreviations-of-in-body-constructor-declarations.

This change was performed in an automated fashion, by (a) bumping the
packages' SDK constraints to `3.13.0-0`, (b) enabling the lints
`unnecessary_type_name_in_constructor` and
`unnecessary_const_in_enum_constructor`, (c) fixing the resulting lint
failures using `dart fix`, and then (d) reformatting the affected
files.

To ease code review, I've reverted unrelated formatting changes.

Since this change requires bumping SDK constaints to `3.13.0-0`, it
was only performed on packages that are *not* published on
pub. (Packages that *are* published on pub should remain on lower
language versions until at least after the stable version of 3.13 is
released, so that we don't block users on the stable channel from
receiving updates to those packages.)

Change-Id: Ibb4daebafd239da58251e838ea6a3f336a6a6964
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/505046
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
SLSA-Policy-Verified: SLSA Policy Verification Service <devtools-gerritcodereview-exitgate@google.com>
2026-05-27 14:52:58 -07:00

153 lines
4.8 KiB
Dart

// Copyright (c) 2018, 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.
import 'package:analyzer_utilities/html_dom.dart';
import 'package:analyzer_utilities/html_generator.dart';
import 'package:analyzer_utilities/tools.dart';
import 'api.dart';
import 'codegen_dart.dart';
import 'codegen_protocol_constants.dart' show generateConstName;
import 'from_html.dart';
GeneratedFile clientTarget() {
return GeneratedFile(
'analysis_server_client/lib/handler/notification_handler.dart',
(pkgRoot) async {
var visitor = CodegenNotificationHandlerVisitor(readApi(pkgRoot));
return visitor.collectCode(visitor.visitApi);
},
);
}
String _capitalize(String name) =>
'${name.substring(0, 1).toUpperCase()}${name.substring(1)}';
List<String> _generateDartDoc(Element html) => html.children
.where((Element elem) => elem.name == 'p')
.map<String>((Element elem) => innerText(elem).trim())
.toList();
String _generateNotificationMethodName(String domainName, String event) =>
'on${_capitalize(domainName)}${_capitalize(event)}';
String _generateParamTypeName(String domainName, String event) =>
'${_capitalize(domainName)}${_capitalize(event)}Params';
/// Visitor which produces Dart code representing the API.
class CodegenNotificationHandlerVisitor extends DartCodegenVisitor
with CodeGenerator {
new(super.api) {
codeGeneratorSettings.commentLineLength = 79;
codeGeneratorSettings.docCommentStartMarker = null;
codeGeneratorSettings.docCommentLineLeader = '/// ';
codeGeneratorSettings.docCommentEndMarker = null;
codeGeneratorSettings.languageName = 'dart';
}
void emitDartdoc(List<String> dartdoc) {
var first = true;
for (var paragraph in dartdoc) {
if (first) {
first = false;
} else {
writeln(' ///');
}
for (var line in paragraph.split(RegExp('\r?\n'))) {
writeln(' /// ${line.trim()}');
}
}
}
void emitImports() {
writeln("import 'package:analysis_server_client/protocol.dart';");
}
void emitNotificationHandler() {
var visitor = _NotificationVisitor(api)..visitApi();
var notifications = visitor.notificationConstants;
notifications.sort((n1, n2) => n1.constName.compareTo(n2.constName));
writeln('''
/// [NotificationHandler] processes analysis server notifications
/// and dispatches those notifications to different methods based upon
/// the type of notification. Clients may override
/// any of the "on<EventName>" methods that are of interest.
///
/// Clients may mix-in this class, but may not implement it.
mixin NotificationHandler {
void handleEvent(Notification notification) {
var params = notification.params;
var decoder = ResponseDecoder(null);
switch (notification.event) {
''');
for (var notification in notifications) {
writeln(' case ${notification.constName}:');
writeln(' ${notification.methodName}(');
writeln(' ${notification.paramsTypeName}');
writeln(" .fromJson(decoder, 'params', params));");
writeln(' break;');
}
writeln(' default:');
writeln(' onUnknownNotification(notification.event, params);');
writeln(' break;');
writeln(' }');
writeln(' }');
for (var notification in notifications) {
writeln();
emitDartdoc(notification.dartdoc);
writeln(' void ${notification.methodName}(');
writeln(' ${notification.paramsTypeName} params) {');
writeln(' }');
}
writeln();
writeln(' /// Reports a notification that is not processed');
writeln(' /// by any other notification handlers.');
writeln(' void onUnknownNotification(String event, params) {}');
writeln('}');
}
@override
void visitApi() {
outputHeader(year: '2018');
writeln();
emitImports();
emitNotificationHandler();
}
}
class _Notification {
final String constName;
final String methodName;
final String paramsTypeName;
final List<String> dartdoc;
new(this.constName, this.methodName, this.paramsTypeName, this.dartdoc);
}
class _NotificationVisitor extends HierarchicalApiVisitor {
final notificationConstants = <_Notification>[];
new(super.api);
@override
void visitNotification(Notification notification) {
notificationConstants.add(
_Notification(
generateConstName(
notification.domainName,
'notification',
notification.event,
),
_generateNotificationMethodName(
notification.domainName,
notification.event,
),
_generateParamTypeName(notification.domainName, notification.event),
_generateDartDoc(notification.html!),
),
);
}
}