mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 04:06:59 +00:00
Add the ability to associate a URL with a diagnostic
Change-Id: I06f694311130a36b1db4b4baf2e7d46d999f07b7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97554 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
87c553bf3c
commit
11a148c85e
|
@ -2891,6 +2891,11 @@ a:focus, a:hover {
|
|||
<p>
|
||||
The name, as a string, of the error code associated with this error.
|
||||
</p>
|
||||
</dd><dt class="field"><b>url: String<span style="color:#999999"> (optional)</span></b></dt><dd>
|
||||
|
||||
<p>
|
||||
The URL of a page containing documentation associated with this error.
|
||||
</p>
|
||||
</dd><dt class="field"><b>hasFix: bool<span style="color:#999999"> (optional)</span></b></dt><dd>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -39,34 +39,6 @@ List<AnalysisError> doAnalysisError_listFromEngine(
|
|||
analysisOptions, lineInfo, errors, newAnalysisError_fromEngine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates engine errors through the ErrorProcessor.
|
||||
*/
|
||||
List<T> mapEngineErrors<T>(
|
||||
engine.AnalysisOptions analysisOptions,
|
||||
engine.LineInfo lineInfo,
|
||||
List<engine.AnalysisError> errors,
|
||||
T Function(engine.LineInfo lineInfo, engine.AnalysisError error,
|
||||
[engine.ErrorSeverity errorSeverity])
|
||||
constructor) {
|
||||
List<T> serverErrors = <T>[];
|
||||
for (engine.AnalysisError error in errors) {
|
||||
ErrorProcessor processor =
|
||||
ErrorProcessor.getProcessor(analysisOptions, error);
|
||||
if (processor != null) {
|
||||
engine.ErrorSeverity severity = processor.severity;
|
||||
// Errors with null severity are filtered out.
|
||||
if (severity != null) {
|
||||
// Specified severities override.
|
||||
serverErrors.add(constructor(lineInfo, error, severity));
|
||||
}
|
||||
} else {
|
||||
serverErrors.add(constructor(lineInfo, error));
|
||||
}
|
||||
}
|
||||
return serverErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds [edit] to the file containing the given [element].
|
||||
*/
|
||||
|
@ -103,6 +75,34 @@ String getReturnTypeString(engine.Element element) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates engine errors through the ErrorProcessor.
|
||||
*/
|
||||
List<T> mapEngineErrors<T>(
|
||||
engine.AnalysisOptions analysisOptions,
|
||||
engine.LineInfo lineInfo,
|
||||
List<engine.AnalysisError> errors,
|
||||
T Function(engine.LineInfo lineInfo, engine.AnalysisError error,
|
||||
[engine.ErrorSeverity errorSeverity])
|
||||
constructor) {
|
||||
List<T> serverErrors = <T>[];
|
||||
for (engine.AnalysisError error in errors) {
|
||||
ErrorProcessor processor =
|
||||
ErrorProcessor.getProcessor(analysisOptions, error);
|
||||
if (processor != null) {
|
||||
engine.ErrorSeverity severity = processor.severity;
|
||||
// Errors with null severity are filtered out.
|
||||
if (severity != null) {
|
||||
// Specified severities override.
|
||||
serverErrors.add(constructor(lineInfo, error, severity));
|
||||
}
|
||||
} else {
|
||||
serverErrors.add(constructor(lineInfo, error));
|
||||
}
|
||||
}
|
||||
return serverErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct based on error information from the analyzer engine.
|
||||
*
|
||||
|
@ -140,8 +140,9 @@ AnalysisError newAnalysisError_fromEngine(
|
|||
String code = errorCode.name.toLowerCase();
|
||||
String correction = error.correction;
|
||||
bool fix = hasFix(error.errorCode);
|
||||
String url = errorCode.url;
|
||||
return new AnalysisError(severity, type, location, message, code,
|
||||
correction: correction, hasFix: fix);
|
||||
correction: correction, hasFix: fix, url: url);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,4 +20,5 @@ const String START_COLUMN = 'startColumn';
|
|||
const String START_LINE = 'startLine';
|
||||
const String SUBSCRIPTIONS = 'subscriptions';
|
||||
const String TYPE = 'type';
|
||||
const String URL = 'url';
|
||||
const String VERSION = 'version';
|
||||
|
|
|
@ -34,6 +34,7 @@ final Matcher isAddContentOverlay = new LazyMatcher(() => new MatchesJsonObject(
|
|||
* "message": String
|
||||
* "correction": optional String
|
||||
* "code": String
|
||||
* "url": optional String
|
||||
* "hasFix": optional bool
|
||||
* }
|
||||
*/
|
||||
|
@ -46,6 +47,7 @@ final Matcher isAnalysisError =
|
|||
"code": isString
|
||||
}, optionalFields: {
|
||||
"correction": isString,
|
||||
"url": isString,
|
||||
"hasFix": isBool
|
||||
}));
|
||||
|
||||
|
|
|
@ -67,6 +67,31 @@ class AnalysisErrorTest {
|
|||
});
|
||||
}
|
||||
|
||||
void test_fromEngine_hasUrl() {
|
||||
engineError = new MockAnalysisError(
|
||||
source,
|
||||
new MockErrorCode(url: 'http://codes.dartlang.org/TEST_ERROR'),
|
||||
10,
|
||||
20,
|
||||
'my message');
|
||||
AnalysisError error = newAnalysisError_fromEngine(lineInfo, engineError);
|
||||
expect(error.toJson(), {
|
||||
SEVERITY: 'ERROR',
|
||||
TYPE: 'COMPILE_TIME_ERROR',
|
||||
LOCATION: {
|
||||
FILE: 'foo.dart',
|
||||
OFFSET: 10,
|
||||
LENGTH: 20,
|
||||
START_LINE: 3,
|
||||
START_COLUMN: 2
|
||||
},
|
||||
MESSAGE: 'my message',
|
||||
CODE: 'test_error',
|
||||
URL: 'http://codes.dartlang.org/TEST_ERROR',
|
||||
HAS_FIX: false
|
||||
});
|
||||
}
|
||||
|
||||
void test_fromEngine_noCorrection() {
|
||||
engineError.correction = null;
|
||||
AnalysisError error = newAnalysisError_fromEngine(lineInfo, engineError);
|
||||
|
@ -213,3 +238,41 @@ class MockAnalysisError implements engine.AnalysisError {
|
|||
MockAnalysisError(
|
||||
this.source, this.errorCode, this.offset, this.length, this.message);
|
||||
}
|
||||
|
||||
class MockErrorCode implements engine.ErrorCode {
|
||||
@override
|
||||
engine.ErrorType type;
|
||||
|
||||
@override
|
||||
engine.ErrorSeverity errorSeverity;
|
||||
|
||||
@override
|
||||
String name;
|
||||
|
||||
@override
|
||||
String url;
|
||||
|
||||
MockErrorCode(
|
||||
{this.type: engine.ErrorType.COMPILE_TIME_ERROR,
|
||||
this.errorSeverity: engine.ErrorSeverity.ERROR,
|
||||
this.name: 'TEST_ERROR',
|
||||
this.url});
|
||||
|
||||
@override
|
||||
String get correction {
|
||||
throw new StateError('Unexpected invocation of correction');
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isUnresolvedIdentifier => false;
|
||||
|
||||
@override
|
||||
String get message {
|
||||
throw new StateError('Unexpected invocation of message');
|
||||
}
|
||||
|
||||
@override
|
||||
String get uniqueName {
|
||||
throw new StateError('Unexpected invocation of uniqueName');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,11 @@ public class AnalysisError {
|
|||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* The URL of a page containing documentation associated with this error.
|
||||
*/
|
||||
private final String url;
|
||||
|
||||
/**
|
||||
* A hint to indicate to interested clients that this error has an associated fix (or fixes). The
|
||||
* absence of this field implies there are not known to be fixes. Note that since the operation to
|
||||
|
@ -82,13 +87,14 @@ public class AnalysisError {
|
|||
/**
|
||||
* Constructor for {@link AnalysisError}.
|
||||
*/
|
||||
public AnalysisError(String severity, String type, Location location, String message, String correction, String code, Boolean hasFix) {
|
||||
public AnalysisError(String severity, String type, Location location, String message, String correction, String code, String url, Boolean hasFix) {
|
||||
this.severity = severity;
|
||||
this.type = type;
|
||||
this.location = location;
|
||||
this.message = message;
|
||||
this.correction = correction;
|
||||
this.code = code;
|
||||
this.url = url;
|
||||
this.hasFix = hasFix;
|
||||
}
|
||||
|
||||
|
@ -103,6 +109,7 @@ public class AnalysisError {
|
|||
ObjectUtilities.equals(other.message, message) &&
|
||||
ObjectUtilities.equals(other.correction, correction) &&
|
||||
ObjectUtilities.equals(other.code, code) &&
|
||||
ObjectUtilities.equals(other.url, url) &&
|
||||
ObjectUtilities.equals(other.hasFix, hasFix);
|
||||
}
|
||||
return false;
|
||||
|
@ -115,8 +122,9 @@ public class AnalysisError {
|
|||
String message = jsonObject.get("message").getAsString();
|
||||
String correction = jsonObject.get("correction") == null ? null : jsonObject.get("correction").getAsString();
|
||||
String code = jsonObject.get("code").getAsString();
|
||||
String url = jsonObject.get("url") == null ? null : jsonObject.get("url").getAsString();
|
||||
Boolean hasFix = jsonObject.get("hasFix") == null ? null : jsonObject.get("hasFix").getAsBoolean();
|
||||
return new AnalysisError(severity, type, location, message, correction, code, hasFix);
|
||||
return new AnalysisError(severity, type, location, message, correction, code, url, hasFix);
|
||||
}
|
||||
|
||||
public static List<AnalysisError> fromJsonArray(JsonArray jsonArray) {
|
||||
|
@ -189,6 +197,13 @@ public class AnalysisError {
|
|||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of a page containing documentation associated with this error.
|
||||
*/
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
HashCodeBuilder builder = new HashCodeBuilder();
|
||||
|
@ -198,6 +213,7 @@ public class AnalysisError {
|
|||
builder.append(message);
|
||||
builder.append(correction);
|
||||
builder.append(code);
|
||||
builder.append(url);
|
||||
builder.append(hasFix);
|
||||
return builder.toHashCode();
|
||||
}
|
||||
|
@ -212,6 +228,9 @@ public class AnalysisError {
|
|||
jsonObject.addProperty("correction", correction);
|
||||
}
|
||||
jsonObject.addProperty("code", code);
|
||||
if (url != null) {
|
||||
jsonObject.addProperty("url", url);
|
||||
}
|
||||
if (hasFix != null) {
|
||||
jsonObject.addProperty("hasFix", hasFix);
|
||||
}
|
||||
|
@ -234,6 +253,8 @@ public class AnalysisError {
|
|||
builder.append(correction + ", ");
|
||||
builder.append("code=");
|
||||
builder.append(code + ", ");
|
||||
builder.append("url=");
|
||||
builder.append(url + ", ");
|
||||
builder.append("hasFix=");
|
||||
builder.append(hasFix);
|
||||
builder.append("]");
|
||||
|
|
|
@ -63,6 +63,9 @@ class MockErrorCode implements ErrorCode {
|
|||
@override
|
||||
String name;
|
||||
|
||||
@override
|
||||
String url;
|
||||
|
||||
MockErrorCode(this.type, this.errorSeverity, this.name);
|
||||
|
||||
@override
|
||||
|
|
|
@ -900,6 +900,11 @@ a:focus, a:hover {
|
|||
<p>
|
||||
The name, as a string, of the error code associated with this error.
|
||||
</p>
|
||||
</dd><dt class="field"><b>url: String<span style="color:#999999"> (optional)</span></b></dt><dd>
|
||||
|
||||
<p>
|
||||
The URL of a page containing documentation associated with this error.
|
||||
</p>
|
||||
</dd><dt class="field"><b>hasFix: bool<span style="color:#999999"> (optional)</span></b></dt><dd>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -102,6 +102,7 @@ class AddContentOverlay implements HasToJson {
|
|||
* "message": String
|
||||
* "correction": optional String
|
||||
* "code": String
|
||||
* "url": optional String
|
||||
* "hasFix": optional bool
|
||||
* }
|
||||
*
|
||||
|
@ -120,6 +121,8 @@ class AnalysisError implements HasToJson {
|
|||
|
||||
String _code;
|
||||
|
||||
String _url;
|
||||
|
||||
bool _hasFix;
|
||||
|
||||
/**
|
||||
|
@ -205,6 +208,18 @@ class AnalysisError implements HasToJson {
|
|||
this._code = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of a page containing documentation associated with this error.
|
||||
*/
|
||||
String get url => _url;
|
||||
|
||||
/**
|
||||
* The URL of a page containing documentation associated with this error.
|
||||
*/
|
||||
void set url(String value) {
|
||||
this._url = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* A hint to indicate to interested clients that this error has an associated
|
||||
* fix (or fixes). The absence of this field implies there are not known to
|
||||
|
@ -233,13 +248,14 @@ class AnalysisError implements HasToJson {
|
|||
|
||||
AnalysisError(AnalysisErrorSeverity severity, AnalysisErrorType type,
|
||||
Location location, String message, String code,
|
||||
{String correction, bool hasFix}) {
|
||||
{String correction, String url, bool hasFix}) {
|
||||
this.severity = severity;
|
||||
this.type = type;
|
||||
this.location = location;
|
||||
this.message = message;
|
||||
this.correction = correction;
|
||||
this.code = code;
|
||||
this.url = url;
|
||||
this.hasFix = hasFix;
|
||||
}
|
||||
|
||||
|
@ -288,12 +304,16 @@ class AnalysisError implements HasToJson {
|
|||
} else {
|
||||
throw jsonDecoder.mismatch(jsonPath, "code");
|
||||
}
|
||||
String url;
|
||||
if (json.containsKey("url")) {
|
||||
url = jsonDecoder.decodeString(jsonPath + ".url", json["url"]);
|
||||
}
|
||||
bool hasFix;
|
||||
if (json.containsKey("hasFix")) {
|
||||
hasFix = jsonDecoder.decodeBool(jsonPath + ".hasFix", json["hasFix"]);
|
||||
}
|
||||
return new AnalysisError(severity, type, location, message, code,
|
||||
correction: correction, hasFix: hasFix);
|
||||
correction: correction, url: url, hasFix: hasFix);
|
||||
} else {
|
||||
throw jsonDecoder.mismatch(jsonPath, "AnalysisError", json);
|
||||
}
|
||||
|
@ -310,6 +330,9 @@ class AnalysisError implements HasToJson {
|
|||
result["correction"] = correction;
|
||||
}
|
||||
result["code"] = code;
|
||||
if (url != null) {
|
||||
result["url"] = url;
|
||||
}
|
||||
if (hasFix != null) {
|
||||
result["hasFix"] = hasFix;
|
||||
}
|
||||
|
@ -328,6 +351,7 @@ class AnalysisError implements HasToJson {
|
|||
message == other.message &&
|
||||
correction == other.correction &&
|
||||
code == other.code &&
|
||||
url == other.url &&
|
||||
hasFix == other.hasFix;
|
||||
}
|
||||
return false;
|
||||
|
@ -342,6 +366,7 @@ class AnalysisError implements HasToJson {
|
|||
hash = JenkinsSmiHash.combine(hash, message.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, correction.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, code.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, url.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, hasFix.hashCode);
|
||||
return JenkinsSmiHash.finish(hash);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ final Matcher isAddContentOverlay = new LazyMatcher(() => new MatchesJsonObject(
|
|||
* "message": String
|
||||
* "correction": optional String
|
||||
* "code": String
|
||||
* "url": optional String
|
||||
* "hasFix": optional bool
|
||||
* }
|
||||
*/
|
||||
|
@ -46,6 +47,7 @@ final Matcher isAnalysisError =
|
|||
"code": isString
|
||||
}, optionalFields: {
|
||||
"correction": isString,
|
||||
"url": isString,
|
||||
"hasFix": isBool
|
||||
}));
|
||||
|
||||
|
|
|
@ -95,6 +95,12 @@
|
|||
The name, as a string, of the error code associated with this error.
|
||||
</p>
|
||||
</field>
|
||||
<field name="url" optional="true">
|
||||
<ref>String</ref>
|
||||
<p>
|
||||
The URL of a page containing documentation associated with this error.
|
||||
</p>
|
||||
</field>
|
||||
<field name="hasFix" optional="true">
|
||||
<ref>bool</ref>
|
||||
<p>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// Copyright (c) 2016, 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.
|
||||
|
||||
|
@ -25,6 +25,12 @@ abstract class ErrorCode {
|
|||
*/
|
||||
final String correction;
|
||||
|
||||
/**
|
||||
* The URL of a page containing documentation for errors with this code, or
|
||||
* `null` if there is no known documentation.
|
||||
*/
|
||||
final String url;
|
||||
|
||||
/**
|
||||
* Whether this error is caused by an unresolved identifier.
|
||||
*/
|
||||
|
@ -36,7 +42,7 @@ abstract class ErrorCode {
|
|||
* template. The correction associated with the error will be created from the
|
||||
* given [correction] template.
|
||||
*/
|
||||
const ErrorCode(this.name, this.message, [this.correction])
|
||||
const ErrorCode(this.name, this.message, [this.correction, this.url])
|
||||
: isUnresolvedIdentifier = false;
|
||||
|
||||
/**
|
||||
|
@ -46,7 +52,7 @@ abstract class ErrorCode {
|
|||
* given [correction] template.
|
||||
*/
|
||||
const ErrorCode.temporary(this.name, this.message,
|
||||
{this.correction, this.isUnresolvedIdentifier: false});
|
||||
{this.correction, this.isUnresolvedIdentifier: false, this.url});
|
||||
|
||||
/**
|
||||
* The severity of the error.
|
||||
|
|
Loading…
Reference in a new issue