Prepare to compute the documentation URL for diagnostics

Change-Id: Ib1b7e4887e18b90c1552f3f8501948ee8d8d2c1f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105260
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index e24d2db..07fcdd8 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -141,10 +141,6 @@
   String correction = error.correction;
   bool fix = hasFix(error.errorCode);
   String url = errorCode.url;
-  if (url == null && errorCode is engine.LintCode) {
-    String lintName = errorCode.name.toLowerCase();
-    url = 'https://dart-lang.github.io/linter/lints/$lintName.html';
-  }
   return new AnalysisError(severity, type, location, message, code,
       correction: correction, hasFix: fix, url: url);
 }
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 7bc7663..07e7073 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -304,6 +304,9 @@
   }
 
   @override
+  bool get hasPublishedDocs => false;
+
+  @override
   bool get isUnresolvedIdentifier => false;
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 0b16500..76e63a9 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -824,8 +824,10 @@
    * template. The correction associated with the error will be created from the
    * given [correction] template.
    */
-  const HintCode(String name, String message, {String correction})
-      : super.temporary(name, message, correction: correction);
+  const HintCode(String name, String message,
+      {String correction, bool hasPublishedDocs})
+      : super.temporary(name, message,
+            correction: correction, hasPublishedDocs: hasPublishedDocs);
 
   @override
   ErrorSeverity get errorSeverity => ErrorType.HINT.severity;
diff --git a/pkg/analyzer/lib/src/dart/error/lint_codes.dart b/pkg/analyzer/lib/src/dart/error/lint_codes.dart
index d83e4a9..8d61ae3 100644
--- a/pkg/analyzer/lib/src/dart/error/lint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/lint_codes.dart
@@ -27,4 +27,8 @@
    * subclass the lint's code is defined in.
    */
   String get uniqueName => "LintCode.$name";
+
+  @override
+  String get url =>
+      'https://dart-lang.github.io/linter/lints/${name.toLowerCase()}.html';
 }
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 5b05f7a..9363922 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -83,8 +83,9 @@
    * given [correction] template.
    */
   const CheckedModeCompileTimeErrorCode(String name, String message,
-      {String correction})
-      : super.temporary(name, message, correction: correction);
+      {String correction, bool hasPublishedDocs})
+      : super.temporary(name, message,
+            correction: correction, hasPublishedDocs: hasPublishedDocs);
 
   @override
   ErrorSeverity get errorSeverity =>
@@ -2924,9 +2925,12 @@
    * given [correction] template.
    */
   const CompileTimeErrorCode(String name, String message,
-      {String correction, bool isUnresolvedIdentifier: false})
+      {String correction,
+      bool hasPublishedDocs,
+      bool isUnresolvedIdentifier: false})
       : super.temporary(name, message,
             correction: correction,
+            hasPublishedDocs: hasPublishedDocs,
             isUnresolvedIdentifier: isUnresolvedIdentifier);
 
   @override
@@ -3556,9 +3560,12 @@
    * given [correction] template.
    */
   const StaticTypeWarningCode(String name, String message,
-      {String correction, bool isUnresolvedIdentifier: false})
+      {String correction,
+      bool hasPublishedDocs,
+      bool isUnresolvedIdentifier: false})
       : super.temporary(name, message,
             correction: correction,
+            hasPublishedDocs: hasPublishedDocs,
             isUnresolvedIdentifier: isUnresolvedIdentifier);
 
   @override
@@ -4632,10 +4639,12 @@
    */
   const StaticWarningCode(String name, String message,
       {String correction,
-      this.errorSeverity: ErrorSeverity.ERROR,
+      this.errorSeverity = ErrorSeverity.ERROR,
+      bool hasPublishedDocs,
       bool isUnresolvedIdentifier: false})
       : super.temporary(name, message,
             correction: correction,
+            hasPublishedDocs: hasPublishedDocs,
             isUnresolvedIdentifier: isUnresolvedIdentifier);
 
   @override
@@ -4904,9 +4913,10 @@
    * created from the optional [correction] template.
    */
   const StrongModeCode(ErrorType type, String name, String message,
-      {String correction})
+      {String correction, bool hasPublishedDocs})
       : type = type,
-        super.temporary('STRONG_MODE_$name', message, correction: correction);
+        super.temporary('STRONG_MODE_$name', message,
+            correction: correction, hasPublishedDocs: hasPublishedDocs);
 
   @override
   ErrorSeverity get errorSeverity => type.severity;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 3e549d1..bc7190f 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -3659,8 +3659,10 @@
   /// message associated with the error will be created from the given [message]
   /// template. The correction associated with the error will be created from
   /// the given [correction] template.
-  const ResolverErrorCode(String name, String message, {String correction})
-      : super.temporary(name, message, correction: correction);
+  const ResolverErrorCode(String name, String message,
+      {String correction, bool hasPublishedDocs})
+      : super.temporary(name, message,
+            correction: correction, hasPublishedDocs: hasPublishedDocs);
 
   @override
   ErrorSeverity get errorSeverity => type.severity;
diff --git a/pkg/analyzer_cli/test/mocks.dart b/pkg/analyzer_cli/test/mocks.dart
index ab4e74f..b5e5627 100644
--- a/pkg/analyzer_cli/test/mocks.dart
+++ b/pkg/analyzer_cli/test/mocks.dart
@@ -87,6 +87,9 @@
   }
 
   @override
+  bool get hasPublishedDocs => false;
+
+  @override
   bool get isUnresolvedIdentifier => false;
 
   @override
diff --git a/pkg/front_end/lib/src/base/errors.dart b/pkg/front_end/lib/src/base/errors.dart
index 2fbd323..735fa5d 100644
--- a/pkg/front_end/lib/src/base/errors.dart
+++ b/pkg/front_end/lib/src/base/errors.dart
@@ -26,10 +26,10 @@
   final String correction;
 
   /**
-   * The URL of a page containing documentation for errors with this code, or
-   * `null` if there is no known documentation.
+   * Return `true` if diagnostics with this code have documentation for them
+   * that has been published.
    */
-  final String url;
+  final bool hasPublishedDocs;
 
   /**
    * Whether this error is caused by an unresolved identifier.
@@ -42,7 +42,8 @@
    * template. The correction associated with the error will be created from the
    * given [correction] template.
    */
-  const ErrorCode(this.name, this.message, [this.correction, this.url])
+  const ErrorCode(this.name, this.message,
+      [this.correction, this.hasPublishedDocs = false])
       : isUnresolvedIdentifier = false;
 
   /**
@@ -52,7 +53,9 @@
    * given [correction] template.
    */
   const ErrorCode.temporary(this.name, this.message,
-      {this.correction, this.isUnresolvedIdentifier: false, this.url});
+      {this.correction,
+      this.isUnresolvedIdentifier: false,
+      this.hasPublishedDocs = false});
 
   /**
    * The severity of the error.
@@ -69,6 +72,12 @@
    */
   String get uniqueName => "$runtimeType.$name";
 
+  /**
+   * Return a URL that can be used to access documentation for diagnostics with
+   * this code, or `null` if there is no published documentation.
+   */
+  String get url => null;
+
   @override
   String toString() => uniqueName;
 }