Fix for exporting setters.

R=brianwilkerson@google.com

Change-Id: Ie67834547a94a480e8ed86df430c40bcb36e37e1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103024
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
index cb279c6..c411c79 100644
--- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
@@ -74,7 +74,12 @@
         } else {
           var references = linker.elementFactory.exportsOfLibrary('$uri');
           for (var reference in references) {
-            export.addToExportScope(reference.name, reference);
+            var name = reference.name;
+            if (reference.isSetter) {
+              export.addToExportScope('$name=', reference);
+            } else {
+              export.addToExportScope(name, reference);
+            }
           }
         }
       }
diff --git a/pkg/analyzer/lib/src/summary2/combinator.dart b/pkg/analyzer/lib/src/summary2/combinator.dart
index 5d7b20e..96f1152 100644
--- a/pkg/analyzer/lib/src/summary2/combinator.dart
+++ b/pkg/analyzer/lib/src/summary2/combinator.dart
@@ -8,9 +8,16 @@
 
   Combinator(this.isShow, this.names);
 
-  Combinator.show(Iterable<String> names) : this(true, names.toSet());
-
   Combinator.hide(Iterable<String> names) : this(false, names.toSet());
 
+  Combinator.show(Iterable<String> names) : this(true, names.toSet());
+
   bool get isHide => !isShow;
+
+  bool matches(String name) {
+    if (name.endsWith('=')) {
+      name = name.substring(0, name.length - 1);
+    }
+    return names.contains(name);
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/export.dart b/pkg/analyzer/lib/src/summary2/export.dart
index 63a1365..18247c3 100644
--- a/pkg/analyzer/lib/src/summary2/export.dart
+++ b/pkg/analyzer/lib/src/summary2/export.dart
@@ -16,8 +16,8 @@
   bool addToExportScope(String name, Reference reference) {
     if (combinators != null) {
       for (Combinator combinator in combinators) {
-        if (combinator.isShow && !combinator.names.contains(name)) return false;
-        if (combinator.isHide && combinator.names.contains(name)) return false;
+        if (combinator.isShow && !combinator.matches(name)) return false;
+        if (combinator.isHide && combinator.matches(name)) return false;
       }
     }
     return exporter.addToExportScope(name, reference);
diff --git a/pkg/analyzer/lib/src/summary2/reference.dart b/pkg/analyzer/lib/src/summary2/reference.dart
index bdc98fc..626fdc8 100644
--- a/pkg/analyzer/lib/src/summary2/reference.dart
+++ b/pkg/analyzer/lib/src/summary2/reference.dart
@@ -69,6 +69,8 @@
 
   bool get isPrefix => parent != null && parent.name == '@prefix';
 
+  bool get isSetter => parent != null && parent.name == '@setter';
+
   bool get isTypeAlias => parent != null && parent.name == '@typeAlias';
 
   /// Return the child with the given name, or `null` if does not exist.
@@ -97,9 +99,9 @@
     }
   }
 
-  String toString() => parent == null ? 'root' : '$parent::$name';
-
   void removeChild(String name) {
     _children.remove(name);
   }
+
+  String toString() => parent == null ? 'root' : '$parent::$name';
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/export_test.dart b/pkg/analyzer/test/src/dart/resolution/export_test.dart
new file mode 100644
index 0000000..565f72d
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/export_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, 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:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExportResolutionTest);
+  });
+}
+
+@reflectiveTest
+class ExportResolutionTest extends DriverResolutionTest {
+  /// Test that both getter and setter are in the export namespace.
+  test_namespace_getter_setter() async {
+    newFile('/test/lib/a.dart', content: r'''
+get f => null;
+set f(_) {}
+''');
+    addTestFile(r'''
+export 'a.dart';
+''');
+    await resolveTestFile();
+    var exportNamespace = result.libraryElement.exportNamespace;
+    expect(exportNamespace.get('f'), isNotNull);
+    expect(exportNamespace.get('f='), isNotNull);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 5af83c45..10b3832 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -12,6 +12,7 @@
 import 'constructor_test.dart' as constructor;
 import 'definite_assignment_test.dart' as definite_assignment;
 import 'enum_test.dart' as enum_resolution;
+import 'export_test.dart' as export_;
 import 'flow_analysis_test.dart' as flow_analysis;
 import 'for_element_test.dart' as for_element;
 import 'for_in_test.dart' as for_in;
@@ -44,6 +45,7 @@
     constructor.main();
     definite_assignment.main();
     enum_resolution.main();
+    export_.main();
     flow_analysis.main();
     for_element.main();
     for_in.main();
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index c201a7c..b602cc7 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -5610,6 +5610,25 @@
         withExportScope: true);
   }
 
+  test_export_show_getter_setter() async {
+    addLibrarySource('/a.dart', '''
+get f => null;
+void set f(value) {}
+''');
+    var library = await checkLibrary('export "a.dart" show f;');
+    checkElementText(
+        library,
+        r'''
+export 'a.dart' show f;
+
+--------------------
+Exports:
+  f: a.dart;f?
+  f=: a.dart;f=
+''',
+        withExportScope: true);
+  }
+
   test_export_typedef() async {
     addLibrarySource('/a.dart', 'typedef F();');
     var library = await checkLibrary('export "a.dart";');