[cfe] Mark enhanced enum toString method as synthetic
This fixes a bug where this method is showing up in coverage reports.
Also needed some plumbing in the VM for this flag, because we were
ignoring it before.
Change-Id: I9200a16dab488f5f880b9797243bd2f39de993b3
Fixes: https://github.com/dart-lang/coverage/issues/386
TEST=Added a source_report_test
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/245041
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Liam Appelbe <liama@google.com>
diff --git a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
index f2812d0..43f0251 100644
--- a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
@@ -388,7 +388,8 @@
AsyncMarker.Sync,
procedureNameScheme,
isExtensionMember: false,
- isInstanceMember: true);
+ isInstanceMember: true,
+ isSynthetic: true);
members["toString"] = toStringBuilder;
}
String className = name;
diff --git a/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart b/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
index 1a7fe1f..2c412dd 100644
--- a/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
@@ -76,7 +76,8 @@
NameScheme nameScheme,
{required bool isExtensionMember,
required bool isInstanceMember,
- String? nativeMethodName})
+ String? nativeMethodName,
+ bool isSynthetic: false})
// ignore: unnecessary_null_comparison
: assert(isExtensionMember != null),
// ignore: unnecessary_null_comparison
@@ -90,7 +91,8 @@
isExtensionInstanceMember ? ProcedureKind.Method : kind,
new FunctionNode(null),
fileUri: libraryBuilder.fileUri,
- reference: procedureReference)
+ reference: procedureReference,
+ isSynthetic: isSynthetic)
..startFileOffset = startCharOffset
..fileOffset = charOffset
..fileEndOffset = charEndOffset
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 4499a08..63f765a 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -437,7 +437,7 @@
Byte stubKind; // Index into the ProcedureStubKind enum above.
UInt flags (isStatic, isAbstract, isExternal, isConst,
isRedirectingFactory, isExtensionMember,
- isNonNullableByDefault);
+ isNonNullableByDefault, isSynthetic);
Name name;
List<Expression> annotations;
MemberReference stubTarget; // May be NullReference.
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 046f874..65690a1 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -608,6 +608,7 @@
bool IsAbstract() const { return (flags_ & kAbstract) != 0; }
bool IsExternal() const { return (flags_ & kExternal) != 0; }
bool IsConst() const { return (flags_ & kConst) != 0; }
+ bool IsSynthetic() const { return (flags_ & kSyntheticProcedure) != 0; }
bool IsForwardingStub() const {
return stub_kind_ == kAbstractForwardingStubKind ||
stub_kind_ == kConcreteForwardingStubKind;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index a9835fa..5cb7d4f 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1977,6 +1977,7 @@
bool is_abstract = procedure_helper.IsAbstract();
bool is_external = procedure_helper.IsExternal();
bool is_extension_member = procedure_helper.IsExtensionMember();
+ bool is_synthetic = procedure_helper.IsSynthetic();
String& native_name = String::Handle(Z);
bool scan_annotations_lazy;
bool has_pragma_annotation;
@@ -2009,7 +2010,8 @@
function.set_has_pragma(has_pragma_annotation);
function.set_end_token_pos(procedure_helper.end_position_);
function.set_is_synthetic(procedure_helper.IsNoSuchMethodForwarder() ||
- procedure_helper.IsMemberSignature());
+ procedure_helper.IsMemberSignature() ||
+ is_synthetic);
function.set_is_visible(!is_invisible_function);
if (register_function) {
functions_.Add(&function);
diff --git a/runtime/vm/source_report_test.cc b/runtime/vm/source_report_test.cc
index f749b28..f445ff1 100644
--- a/runtime/vm/source_report_test.cc
+++ b/runtime/vm/source_report_test.cc
@@ -1073,6 +1073,56 @@
buffer);
}
+ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_IssueCov386_EnhancedEnums) {
+ // https://github.com/dart-lang/coverage/issues/386
+ // WARNING: This MUST be big enough for the serialised JSON string.
+ const int kBufferSize = 1024;
+ char buffer[kBufferSize];
+ const char* kScript =
+ "enum FoodType {\n"
+ " candy();\n"
+ " const FoodType();\n"
+ "}\n"
+ "void main() {\n"
+ " final food = FoodType.candy;\n"
+ "}\n";
+
+ Library& lib = Library::Handle();
+ lib ^= ExecuteScript(kScript);
+ ASSERT(!lib.IsNull());
+ const Script& script =
+ Script::Handle(lib.LookupScript(String::Handle(String::New("test-lib"))));
+
+ SourceReport report(SourceReport::kCoverage, SourceReport::kForceCompile);
+ JSONStream js;
+ report.PrintJSON(&js, script);
+ const char* json_str = js.ToCString();
+ ASSERT(strlen(json_str) < kBufferSize);
+ ElideJSONSubstring("classes", json_str, buffer);
+ ElideJSONSubstring("libraries", buffer, buffer);
+ EXPECT_STREQ(
+ "{\"type\":\"SourceReport\",\"ranges\":["
+
+ // There are two ranges at the FoodType constructor. This one is missed,
+ // but the one below is hit, so it's ok. The point is that the synthetic
+ // toString method doesn't appear in this hitmap.
+ "{\"scriptIndex\":0,\"startPos\":29,\"endPos\":45,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[],\"misses\":[29]}},"
+
+ // Main is hit.
+ "{\"scriptIndex\":0,\"startPos\":49,\"endPos\":94,\"compiled\":true,"
+ "\"coverage\":{\"hits\":[49],\"misses\":[]}},"
+
+ // FoodType constructor is hit.
+ "{\"scriptIndex\":0,\"compiled\":true,\"startPos\":29,\"endPos\":45,"
+ "\"coverage\":{\"hits\":[29],\"misses\":[]}}],"
+
+ // Only one script in the script table.
+ "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+ "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
+ buffer);
+}
+
ISOLATE_UNIT_TEST_CASE(SourceReport_Regress95008_RedirectingFactory) {
// WARNING: This MUST be big enough for the serialised JSON string.
const int kBufferSize = 1024;