blob: 8fe66bb55c9c435ffba8de46c6e783c34eb9ade3 [file] [log] [blame]
// Copyright (c) 2021, 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 'dart:convert';
import 'dart:io';
import '../protoc.dart';
const protobufImportPrefix = r'$pb';
const asyncImportPrefix = r'$async';
const coreImportPrefix = r'$core';
const grpcImportPrefix = r'$grpc';
const mixinImportPrefix = r'$mixin';
extension FileDescriptorProtoExt on FileGenerator {
/// Convert leading comments of a definition at [path] to Dart doc comment
/// syntax.
///
/// This never returns an empty string: if the comment is empty it returns
/// `null`.
///
/// The output can contain multiple lines. None of the lines will have
/// trailing whitespace.
String? commentBlock(List<int> path) {
final bits = descriptor.sourceCodeInfo.location
.where((element) => element.path.toString() == path.toString())
.toList();
if (bits.length == 1) {
final match = bits.single;
return toDartComment(match.leadingComments);
}
if (bits.length > 1) {
// TODO: evaluate if we should just concatenate all of the entries.
stderr.writeln('Too many source code locations. Skipping.');
}
return null;
}
}
/// Convert a comment to Dart doc comment syntax.
///
/// This is the internal method for [FileDescriptorProtoExt.commentBlock],
/// public to be able to test.
String? toDartComment(String value) {
if (value.isEmpty) return null;
var lines = LineSplitter.split(value).toList();
// Find any leading spaces in the first line. If all of the lines have the
// same leading spaces, remove them all.
final leadingSpaces = _leadingSpaces.firstMatch(lines.first);
if (leadingSpaces != null) {
final prefix = leadingSpaces.group(0)!;
if (lines.every((element) => element.startsWith(prefix))) {
lines = lines.map((e) => e.substring(prefix.length)).toList();
}
}
// Remove empty, trailing lines.
while (lines.isNotEmpty && lines.last.trim().isEmpty) {
lines.removeLast();
}
// Don't generate a documentation comment if all lines are empty.
if (lines.isEmpty) {
return null;
}
return lines.map((e) => '/// $e'.trimRight()).join('\n');
}
final _leadingSpaces = RegExp('^ +');