[analyzer] handle youtube and animation dartdoc directives

Change-Id: I5bcad74803da2466c8a50160823c586f57e00ec1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99711
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Devon Carew <devoncarew@google.com>
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index 4229e9c..1dd0b83 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -107,7 +107,8 @@
 
   static String computeDocumentation(
       DartdocDirectiveInfo dartdocInfo, Element element) {
-    // TODO(dantup) We're reusing this in parameter information - move it somewhere shared?
+    // TODO(dantup) We're reusing this in parameter information - move it
+    // somewhere shared?
     if (element is FieldFormalParameterElement) {
       element = (element as FieldFormalParameterElement).field;
     }
diff --git a/pkg/analyzer/lib/src/dartdoc/dartdoc_directive_info.dart b/pkg/analyzer/lib/src/dartdoc/dartdoc_directive_info.dart
index ca9c241..1449906 100644
--- a/pkg/analyzer/lib/src/dartdoc/dartdoc_directive_info.dart
+++ b/pkg/analyzer/lib/src/dartdoc/dartdoc_directive_info.dart
@@ -18,6 +18,13 @@
       r'[ ]*{@template\s+(.+?)}([\s\S]+?){@endtemplate}[ ]*\n?',
       multiLine: true);
 
+  /// A regular expression used to match a youtube or animation directive.
+  ///
+  /// These are in the form:
+  /// `{@youtube 560 315 https://www.youtube.com/watch?v=2uaoEDOgk_I}`.
+  static final videoRegExp =
+      new RegExp(r'{@(youtube|animation)\s+[^}]+\s+[^}]+\s+([^}]+)}');
+
   /// A table mapping the names of templates to the unprocessed bodies of the
   /// templates.
   final Map<String, String> templateMap = {};
@@ -45,8 +52,12 @@
     }
   }
 
-  /// Process the given Dartdoc [comment], replacing any macro directives with
-  /// the body of the corresponding template.
+  /// Process the given Dartdoc [comment], replacing any known dartdoc
+  /// directives with the associated content.
+  ///
+  /// Macro directives are replaced with the body of the corresponding template.
+  ///
+  /// Youtube and animation directives are replaced with markdown hyperlinks.
   String processDartdoc(String comment) {
     List<String> lines = _stripDelimiters(comment);
     for (int i = lines.length - 1; i >= 0; i--) {
@@ -58,6 +69,20 @@
         if (value != null) {
           lines[i] = value;
         }
+        continue;
+      }
+
+      match = videoRegExp.firstMatch(line);
+      if (match != null) {
+        String uri = match.group(2);
+        if (uri != null && uri.isNotEmpty) {
+          String label = uri;
+          if (label.startsWith('https://')) {
+            label = label.substring('https://'.length);
+          }
+          lines[i] = '[$label]($uri)';
+        }
+        continue;
       }
     }
     return lines.join('\n');
diff --git a/pkg/analyzer/test/src/dartdoc/dartdoc_directive_info_test.dart b/pkg/analyzer/test/src/dartdoc/dartdoc_directive_info_test.dart
index 43c386a..389fff5 100644
--- a/pkg/analyzer/test/src/dartdoc/dartdoc_directive_info_test.dart
+++ b/pkg/analyzer/test/src/dartdoc/dartdoc_directive_info_test.dart
@@ -81,4 +81,30 @@
     expect(result, '''
 Comment without a macro.''');
   }
+
+  test_processDartdoc_youtube_directive() {
+    String result = info.processDartdoc('''
+/// {@youtube 560 315 https://www.youtube.com/watch?v=2uaoEDOgk_I}
+''');
+    expect(result, '''
+[www.youtube.com/watch?v=2uaoEDOgk_I](https://www.youtube.com/watch?v=2uaoEDOgk_I)''');
+  }
+
+  test_processDartdoc_youtube_malformed() {
+    String result = info.processDartdoc('''
+/// {@youtube 560x315 https://www.youtube.com/watch?v=2uaoEDOgk_I}
+''');
+    expect(result,
+        '{@youtube 560x315 https://www.youtube.com/watch?v=2uaoEDOgk_I}');
+  }
+
+  test_processDartdoc_animation_directive() {
+    String result = info.processDartdoc('''
+/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_bounce_in.mp4}
+''');
+    expect(
+        result,
+        '[flutter.github.io/assets-for-api-docs/assets/animation/curve_bounce_in.mp4]'
+        '(https://flutter.github.io/assets-for-api-docs/assets/animation/curve_bounce_in.mp4)');
+  }
 }