[kernel] Add ability to (de)serialize StaticGet

Change-Id: I8593c38c38f7aa4a9b8d573516681158db7f670c
Reviewed-on: https://dart-review.googlesource.com/c/89546
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
Reviewed-by: Daniel Hillerström <hillerstrom@google.com>
diff --git a/pkg/kernel/lib/text/serializer_combinators.dart b/pkg/kernel/lib/text/serializer_combinators.dart
index 77e59c4..c06937d 100644
--- a/pkg/kernel/lib/text/serializer_combinators.dart
+++ b/pkg/kernel/lib/text/serializer_combinators.dart
@@ -7,6 +7,7 @@
 import 'dart:convert' show json;
 
 import '../ast.dart' show Node;
+import '../canonical_name.dart' show CanonicalName;
 import 'text_serializer.dart' show Tagger;
 
 class DeserializationEnvironment<T extends Node> {
@@ -70,8 +71,9 @@
 
 class DeserializationState {
   final DeserializationEnvironment environment;
+  final CanonicalName nameRoot;
 
-  DeserializationState(this.environment);
+  DeserializationState(this.environment, this.nameRoot);
 }
 
 class SerializationState {
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index 7e4e566..1b8665c 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -98,6 +98,7 @@
 
   String visitVariableGet(VariableGet _) => "get-var";
   String visitVariableSet(VariableSet _) => "set-var";
+  String visitStaticGet(StaticGet _) => "get-static";
 }
 
 TextSerializer<InvalidExpression> invalidExpressionSerializer = new Wrapped(
@@ -381,7 +382,8 @@
         stream,
         new DeserializationState(
             new DeserializationEnvironment(state.environment)
-              ..add(variable.name, variable)));
+              ..add(variable.name, variable),
+            state.nameRoot));
     return new Let(variable, body);
   }
 
@@ -511,6 +513,49 @@
   return new VariableSet(tuple.first, tuple.second);
 }
 
+class CanonicalNameSerializer extends TextSerializer<CanonicalName> {
+  static const String delimiter = "::";
+
+  const CanonicalNameSerializer();
+
+  static void writeName(CanonicalName name, StringBuffer buffer) {
+    if (!name.isRoot) {
+      if (!name.parent.isRoot) {
+        writeName(name.parent, buffer);
+        buffer.write(delimiter);
+      }
+      buffer.write(name.name);
+    }
+  }
+
+  CanonicalName readFrom(Iterator<Object> stream, DeserializationState state) {
+    String string = const DartString().readFrom(stream, state);
+    CanonicalName name = state.nameRoot;
+    for (String s in string.split(delimiter)) {
+      name = name.getChild(s);
+    }
+    return name;
+  }
+
+  void writeTo(
+      StringBuffer buffer, CanonicalName name, SerializationState state) {
+    StringBuffer sb = new StringBuffer();
+    writeName(name, sb);
+    const DartString().writeTo(buffer, sb.toString(), state);
+  }
+}
+
+TextSerializer<StaticGet> staticGetSerializer =
+    new Wrapped(unwrapStaticGet, wrapStaticGet, new CanonicalNameSerializer());
+
+CanonicalName unwrapStaticGet(StaticGet expression) {
+  return expression.targetReference.canonicalName;
+}
+
+StaticGet wrapStaticGet(CanonicalName name) {
+  return new StaticGet.byReference(name.getReference());
+}
+
 Case<Expression> expressionSerializer =
     new Case.uninitialized(const ExpressionTagger());
 
@@ -717,6 +762,7 @@
     "invoke-super",
     "get-var",
     "set-var",
+    "get-static",
   ]);
   expressionSerializer.serializers.addAll([
     stringLiteralSerializer,
@@ -753,6 +799,7 @@
     superMethodInvocationSerializer,
     variableGetSerializer,
     variableSetSerializer,
+    staticGetSerializer,
   ]);
   dartTypeSerializer.tags.addAll([
     "invalid",
diff --git a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
index de25b93..1f26364 100644
--- a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
+++ b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
@@ -45,8 +45,8 @@
       DeserializationState deserializationState})
       : this.serializationState =
             serializationState ?? new SerializationState(null),
-        this.deserializationState =
-            deserializationState ?? new DeserializationState(null);
+        this.deserializationState = deserializationState ??
+            new DeserializationState(null, new CanonicalName.root());
 }
 
 void test() {
@@ -94,14 +94,28 @@
           new VariableDeclaration("x", type: const DynamicType());
       return new TestCase(
           name: "/* suppose: dynamic x; */ x = 42",
-          node: () {
-            return new VariableSet(x, new IntLiteral(42));
-          }(),
+          node: new VariableSet(x, new IntLiteral(42)),
           expectation: "(set-var \"x^0\" (int 42))",
           serializationState: new SerializationState(
-              new SerializationEnvironment(null)..add(x, "x^0")),
+            new SerializationEnvironment(null)..add(x, "x^0"),
+          ),
           deserializationState: new DeserializationState(
-              new DeserializationEnvironment(null)..add("x^0", x)));
+              new DeserializationEnvironment(null)..add("x^0", x),
+              new CanonicalName.root()));
+    }(),
+    () {
+      Field field = new Field(new Name("field"), type: const DynamicType());
+      Library library = new Library(
+          new Uri(scheme: "package", path: "foo/bar.dart"),
+          fields: <Field>[field]);
+      Component component = new Component(libraries: <Library>[library]);
+      component.computeCanonicalNames();
+      return new TestCase(
+          name: "/* suppose top-level: dynamic field; */ field",
+          node: new StaticGet(field),
+          expectation: "(get-static \"package:foo/bar.dart::@fields::field\")",
+          serializationState: new SerializationState(null),
+          deserializationState: new DeserializationState(null, component.root));
     }(),
   ];
   for (TestCase testCase in tests) {
diff --git a/pkg/kernel/test/text_serializer_test.dart b/pkg/kernel/test/text_serializer_test.dart
index d50f173..c64ff64 100644
--- a/pkg/kernel/test/text_serializer_test.dart
+++ b/pkg/kernel/test/text_serializer_test.dart
@@ -17,8 +17,8 @@
 Expression readExpression(String input) {
   TextIterator stream = new TextIterator(input, 0);
   stream.moveNext();
-  Expression result =
-      expressionSerializer.readFrom(stream, new DeserializationState(null));
+  Expression result = expressionSerializer.readFrom(
+      stream, new DeserializationState(null, new CanonicalName.root()));
   if (stream.moveNext()) {
     throw StateError("extra cruft in basic literal");
   }