2a98f98098
Change-Id: Ief30fb79b2afcbb3f50d9127eb622fac362b07b1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/340141 Commit-Queue: Devon Carew <devoncarew@google.com> Auto-Submit: Parker Lougheed <parlough@gmail.com> Reviewed-by: Devon Carew <devoncarew@google.com> Reviewed-by: Bob Nystrom <rnystrom@google.com>
98 lines
2.7 KiB
Dart
98 lines
2.7 KiB
Dart
// Copyright (c) 2020, 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/dart/ast/ast.dart';
|
|
import 'package:scrape/scrape.dart';
|
|
|
|
final quoteRegExp = RegExp('\\\\?[\'"]');
|
|
|
|
void main(List<String> arguments) {
|
|
Scrape()
|
|
..addHistogram('Directive')
|
|
..addHistogram('Expression')
|
|
..addHistogram('Escapes')
|
|
..addVisitor(StringVisitor.new)
|
|
..runCommandLine(arguments);
|
|
}
|
|
|
|
class StringVisitor extends ScrapeVisitor {
|
|
@override
|
|
void visitSimpleStringLiteral(SimpleStringLiteral node) {
|
|
_record('Expression', node);
|
|
_recordEscapes(node);
|
|
super.visitSimpleStringLiteral(node);
|
|
}
|
|
|
|
@override
|
|
void visitStringInterpolation(StringInterpolation node) {
|
|
// Entire expression containing interpolation elements.
|
|
_record('Expression', node);
|
|
|
|
// TODO: Analyze escaped quotes inside strings.
|
|
|
|
// TODO: Analyze string literals nested inside interpolation.
|
|
super.visitStringInterpolation(node);
|
|
}
|
|
|
|
@override
|
|
void visitExportDirective(ExportDirective node) {
|
|
_record('Directive', node.uri);
|
|
// Don't recurse so that we don't treat the URI as a string expression.
|
|
}
|
|
|
|
@override
|
|
void visitImportDirective(ImportDirective node) {
|
|
_record('Directive', node.uri);
|
|
// Don't recurse so that we don't treat the URI as a string expression.
|
|
}
|
|
|
|
@override
|
|
void visitPartDirective(PartDirective node) {
|
|
_record('Directive', node.uri);
|
|
// Don't recurse so that we don't treat the URI as a string expression.
|
|
}
|
|
|
|
@override
|
|
void visitPartOfDirective(PartOfDirective node) {
|
|
if (node.uri != null) _record('Directive', node.uri!);
|
|
// Don't recurse so that we don't treat the URI as a string expression.
|
|
}
|
|
|
|
void _record(String histogram, StringLiteral string) {
|
|
record(histogram, _quoteType(string.beginToken.lexeme));
|
|
}
|
|
|
|
void _recordEscapes(StringLiteral string) {
|
|
var quote = _quoteType(string.beginToken.lexeme);
|
|
|
|
// Ignore the rarer quote styles.
|
|
if (quote != "'" && quote != '"') return;
|
|
|
|
var contents = string.toSource();
|
|
contents = contents.substring(1, contents.length - 1);
|
|
|
|
var quotes = quoteRegExp
|
|
.allMatches(contents)
|
|
.map((match) => match[0])
|
|
.toSet()
|
|
.toList();
|
|
quotes.sort();
|
|
|
|
if (quotes.isNotEmpty) {
|
|
record('Escapes', '$quote containing ${quotes.join(" ")}');
|
|
}
|
|
}
|
|
|
|
String _quoteType(String lexeme) {
|
|
const types = ['"""', "'''", 'r"""', "r'''", '"', "'", 'r"', "r'"];
|
|
|
|
for (var type in types) {
|
|
if (lexeme.startsWith(type)) return type;
|
|
}
|
|
|
|
log('Unknown string quote in $lexeme');
|
|
return '';
|
|
}
|
|
}
|