mirror of
https://github.com/dart-lang/sdk
synced 2024-07-20 04:25:52 +00:00
Put fully resolved analysis results (just errors now) into the byte cache.
R=brianwilkerson@google.com, paulberry@google.com BUG= Review URL: https://codereview.chromium.org/2455573003 .
This commit is contained in:
parent
205e9a58e1
commit
bd594d453f
|
@ -236,7 +236,8 @@ class AnalysisDriver {
|
|||
for (String path in _priorityFiles) {
|
||||
if (_filesToAnalyze.remove(path)) {
|
||||
_File file = _fileForPath(path);
|
||||
AnalysisResult result = _computeAnalysisResult(file);
|
||||
AnalysisResult result =
|
||||
_computeAnalysisResult(file, withUnit: true);
|
||||
yield result;
|
||||
break;
|
||||
}
|
||||
|
@ -252,7 +253,7 @@ class AnalysisDriver {
|
|||
if (_filesToAnalyze.isNotEmpty) {
|
||||
String path = _removeFirst(_filesToAnalyze);
|
||||
_File file = _fileForPath(path);
|
||||
AnalysisResult result = _computeAnalysisResult(file);
|
||||
AnalysisResult result = _computeAnalysisResult(file, withUnit: false);
|
||||
yield result;
|
||||
// Repeat the processing loop.
|
||||
_hasWork.notify();
|
||||
|
@ -366,10 +367,32 @@ class AnalysisDriver {
|
|||
|
||||
/**
|
||||
* Compute the [AnalysisResult] for the [file].
|
||||
*
|
||||
* The result will have the fully resolved unit only if [withUnit] is `true`.
|
||||
*/
|
||||
AnalysisResult _computeAnalysisResult(_File file) {
|
||||
AnalysisResult _computeAnalysisResult(_File file, {bool withUnit: false}) {
|
||||
// If we don't need to the fully resolved unit, check for a cached result.
|
||||
if (!withUnit) {
|
||||
AnalysisResult result = _getCachedAnalysisResult(file);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// We need the fully resolved unit, or the result is not cached.
|
||||
return _logger.run('Compute analysis result for $file', () {
|
||||
_LibraryContext libraryContext = _createLibraryContext(file);
|
||||
|
||||
// We recomputed the dependency hash, and we might have a cached result.
|
||||
if (!withUnit) {
|
||||
AnalysisResult result = _getCachedAnalysisResult(file);
|
||||
if (result != null) {
|
||||
_logger.writeln('Return the cached analysis result.');
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Still no result, compute and store it.
|
||||
AnalysisContext analysisContext = _createAnalysisContext(libraryContext);
|
||||
try {
|
||||
analysisContext.setContents(file.source, file.content);
|
||||
|
@ -377,6 +400,25 @@ class AnalysisDriver {
|
|||
CompilationUnit resolvedUnit =
|
||||
analysisContext.resolveCompilationUnit2(file.source, file.source);
|
||||
List<AnalysisError> errors = analysisContext.computeErrors(file.source);
|
||||
|
||||
// Store the result into the cache.
|
||||
{
|
||||
List<int> bytes = new AnalysisDriverResolvedUnitBuilder(
|
||||
errors: errors
|
||||
.map((error) => new AnalysisDriverUnitErrorBuilder(
|
||||
offset: error.offset,
|
||||
length: error.length,
|
||||
uniqueName: error.errorCode.uniqueName,
|
||||
message: error.message,
|
||||
correction: error.correction))
|
||||
.toList())
|
||||
.toBuffer();
|
||||
String key = _getResolvedUnitKey(file);
|
||||
_byteStore.put(key, bytes);
|
||||
}
|
||||
|
||||
// Return the full result.
|
||||
_logger.writeln('Computed new analysis result.');
|
||||
return new AnalysisResult(file.path, file.uri, file.content,
|
||||
file.contentHash, resolvedUnit, errors);
|
||||
} finally {
|
||||
|
@ -526,6 +568,47 @@ class AnalysisDriver {
|
|||
return new _File.forResolution(this, source);
|
||||
}
|
||||
|
||||
/**
|
||||
* If we know the dependency signature for the [file], try to load the
|
||||
* analysis result from the cache. Return `null` if not found.
|
||||
*/
|
||||
AnalysisResult _getCachedAnalysisResult(_File file) {
|
||||
String key = _getResolvedUnitKey(file);
|
||||
if (key != null) {
|
||||
List<int> bytes = _byteStore.get(key);
|
||||
if (bytes != null) {
|
||||
var unit = new AnalysisDriverResolvedUnit.fromBuffer(bytes);
|
||||
List<AnalysisError> errors = unit.errors
|
||||
.map((error) => new AnalysisError.forValues(
|
||||
file.source,
|
||||
error.offset,
|
||||
error.length,
|
||||
ErrorCode.byUniqueName(error.uniqueName),
|
||||
error.message,
|
||||
error.correction))
|
||||
.toList();
|
||||
return new AnalysisResult(
|
||||
file.path, file.uri, null, file.contentHash, null, errors);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key to store fully resolved results for the [file] into the
|
||||
* cache. Return `null` if the dependency signature is not known yet.
|
||||
*/
|
||||
String _getResolvedUnitKey(_File file) {
|
||||
String dependencyHash = _dependencySignatureMap[file.uri];
|
||||
if (dependencyHash != null) {
|
||||
ApiSignature signature = new ApiSignature();
|
||||
signature.addString(dependencyHash);
|
||||
signature.addString(file.contentHash);
|
||||
return '${signature.toHex()}.resolved';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the API signature for the file with the given [path], and decide
|
||||
* which linked libraries should be invalidated, and files reanalyzed.
|
||||
|
|
|
@ -129,6 +129,296 @@ class _UnlinkedParamKindReader extends fb.Reader<idl.UnlinkedParamKind> {
|
|||
}
|
||||
}
|
||||
|
||||
class AnalysisDriverResolvedUnitBuilder extends Object with _AnalysisDriverResolvedUnitMixin implements idl.AnalysisDriverResolvedUnit {
|
||||
List<AnalysisDriverUnitErrorBuilder> _errors;
|
||||
|
||||
@override
|
||||
List<AnalysisDriverUnitErrorBuilder> get errors => _errors ??= <AnalysisDriverUnitErrorBuilder>[];
|
||||
|
||||
/**
|
||||
* The full list of analysis errors, both syntactic and semantic.
|
||||
*/
|
||||
void set errors(List<AnalysisDriverUnitErrorBuilder> value) {
|
||||
this._errors = value;
|
||||
}
|
||||
|
||||
AnalysisDriverResolvedUnitBuilder({List<AnalysisDriverUnitErrorBuilder> errors})
|
||||
: _errors = errors;
|
||||
|
||||
/**
|
||||
* Flush [informative] data recursively.
|
||||
*/
|
||||
void flushInformative() {
|
||||
_errors?.forEach((b) => b.flushInformative());
|
||||
}
|
||||
|
||||
/**
|
||||
* Accumulate non-[informative] data into [signature].
|
||||
*/
|
||||
void collectApiSignature(api_sig.ApiSignature signature) {
|
||||
if (this._errors == null) {
|
||||
signature.addInt(0);
|
||||
} else {
|
||||
signature.addInt(this._errors.length);
|
||||
for (var x in this._errors) {
|
||||
x?.collectApiSignature(signature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<int> toBuffer() {
|
||||
fb.Builder fbBuilder = new fb.Builder();
|
||||
return fbBuilder.finish(finish(fbBuilder), "ADRU");
|
||||
}
|
||||
|
||||
fb.Offset finish(fb.Builder fbBuilder) {
|
||||
fb.Offset offset_errors;
|
||||
if (!(_errors == null || _errors.isEmpty)) {
|
||||
offset_errors = fbBuilder.writeList(_errors.map((b) => b.finish(fbBuilder)).toList());
|
||||
}
|
||||
fbBuilder.startTable();
|
||||
if (offset_errors != null) {
|
||||
fbBuilder.addOffset(0, offset_errors);
|
||||
}
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
}
|
||||
|
||||
idl.AnalysisDriverResolvedUnit readAnalysisDriverResolvedUnit(List<int> buffer) {
|
||||
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(buffer);
|
||||
return const _AnalysisDriverResolvedUnitReader().read(rootRef, 0);
|
||||
}
|
||||
|
||||
class _AnalysisDriverResolvedUnitReader extends fb.TableReader<_AnalysisDriverResolvedUnitImpl> {
|
||||
const _AnalysisDriverResolvedUnitReader();
|
||||
|
||||
@override
|
||||
_AnalysisDriverResolvedUnitImpl createObject(fb.BufferContext bc, int offset) => new _AnalysisDriverResolvedUnitImpl(bc, offset);
|
||||
}
|
||||
|
||||
class _AnalysisDriverResolvedUnitImpl extends Object with _AnalysisDriverResolvedUnitMixin implements idl.AnalysisDriverResolvedUnit {
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
_AnalysisDriverResolvedUnitImpl(this._bc, this._bcOffset);
|
||||
|
||||
List<idl.AnalysisDriverUnitError> _errors;
|
||||
|
||||
@override
|
||||
List<idl.AnalysisDriverUnitError> get errors {
|
||||
_errors ??= const fb.ListReader<idl.AnalysisDriverUnitError>(const _AnalysisDriverUnitErrorReader()).vTableGet(_bc, _bcOffset, 0, const <idl.AnalysisDriverUnitError>[]);
|
||||
return _errors;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _AnalysisDriverResolvedUnitMixin implements idl.AnalysisDriverResolvedUnit {
|
||||
@override
|
||||
Map<String, Object> toJson() {
|
||||
Map<String, Object> _result = <String, Object>{};
|
||||
if (errors.isNotEmpty) _result["errors"] = errors.map((_value) => _value.toJson()).toList();
|
||||
return _result;
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Object> toMap() => {
|
||||
"errors": errors,
|
||||
};
|
||||
|
||||
@override
|
||||
String toString() => convert.JSON.encode(toJson());
|
||||
}
|
||||
|
||||
class AnalysisDriverUnitErrorBuilder extends Object with _AnalysisDriverUnitErrorMixin implements idl.AnalysisDriverUnitError {
|
||||
String _correction;
|
||||
int _length;
|
||||
String _message;
|
||||
int _offset;
|
||||
String _uniqueName;
|
||||
|
||||
@override
|
||||
String get correction => _correction ??= '';
|
||||
|
||||
/**
|
||||
* The optional correction hint for the error.
|
||||
*/
|
||||
void set correction(String value) {
|
||||
this._correction = value;
|
||||
}
|
||||
|
||||
@override
|
||||
int get length => _length ??= 0;
|
||||
|
||||
/**
|
||||
* The length of the error in the file.
|
||||
*/
|
||||
void set length(int value) {
|
||||
assert(value == null || value >= 0);
|
||||
this._length = value;
|
||||
}
|
||||
|
||||
@override
|
||||
String get message => _message ??= '';
|
||||
|
||||
/**
|
||||
* The message of the error.
|
||||
*/
|
||||
void set message(String value) {
|
||||
this._message = value;
|
||||
}
|
||||
|
||||
@override
|
||||
int get offset => _offset ??= 0;
|
||||
|
||||
/**
|
||||
* The offset from the beginning of the file.
|
||||
*/
|
||||
void set offset(int value) {
|
||||
assert(value == null || value >= 0);
|
||||
this._offset = value;
|
||||
}
|
||||
|
||||
@override
|
||||
String get uniqueName => _uniqueName ??= '';
|
||||
|
||||
/**
|
||||
* The unique name of the error code.
|
||||
*/
|
||||
void set uniqueName(String value) {
|
||||
this._uniqueName = value;
|
||||
}
|
||||
|
||||
AnalysisDriverUnitErrorBuilder({String correction, int length, String message, int offset, String uniqueName})
|
||||
: _correction = correction,
|
||||
_length = length,
|
||||
_message = message,
|
||||
_offset = offset,
|
||||
_uniqueName = uniqueName;
|
||||
|
||||
/**
|
||||
* Flush [informative] data recursively.
|
||||
*/
|
||||
void flushInformative() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Accumulate non-[informative] data into [signature].
|
||||
*/
|
||||
void collectApiSignature(api_sig.ApiSignature signature) {
|
||||
signature.addInt(this._offset ?? 0);
|
||||
signature.addInt(this._length ?? 0);
|
||||
signature.addString(this._uniqueName ?? '');
|
||||
signature.addString(this._message ?? '');
|
||||
signature.addString(this._correction ?? '');
|
||||
}
|
||||
|
||||
fb.Offset finish(fb.Builder fbBuilder) {
|
||||
fb.Offset offset_correction;
|
||||
fb.Offset offset_message;
|
||||
fb.Offset offset_uniqueName;
|
||||
if (_correction != null) {
|
||||
offset_correction = fbBuilder.writeString(_correction);
|
||||
}
|
||||
if (_message != null) {
|
||||
offset_message = fbBuilder.writeString(_message);
|
||||
}
|
||||
if (_uniqueName != null) {
|
||||
offset_uniqueName = fbBuilder.writeString(_uniqueName);
|
||||
}
|
||||
fbBuilder.startTable();
|
||||
if (offset_correction != null) {
|
||||
fbBuilder.addOffset(4, offset_correction);
|
||||
}
|
||||
if (_length != null && _length != 0) {
|
||||
fbBuilder.addUint32(1, _length);
|
||||
}
|
||||
if (offset_message != null) {
|
||||
fbBuilder.addOffset(3, offset_message);
|
||||
}
|
||||
if (_offset != null && _offset != 0) {
|
||||
fbBuilder.addUint32(0, _offset);
|
||||
}
|
||||
if (offset_uniqueName != null) {
|
||||
fbBuilder.addOffset(2, offset_uniqueName);
|
||||
}
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
}
|
||||
|
||||
class _AnalysisDriverUnitErrorReader extends fb.TableReader<_AnalysisDriverUnitErrorImpl> {
|
||||
const _AnalysisDriverUnitErrorReader();
|
||||
|
||||
@override
|
||||
_AnalysisDriverUnitErrorImpl createObject(fb.BufferContext bc, int offset) => new _AnalysisDriverUnitErrorImpl(bc, offset);
|
||||
}
|
||||
|
||||
class _AnalysisDriverUnitErrorImpl extends Object with _AnalysisDriverUnitErrorMixin implements idl.AnalysisDriverUnitError {
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
_AnalysisDriverUnitErrorImpl(this._bc, this._bcOffset);
|
||||
|
||||
String _correction;
|
||||
int _length;
|
||||
String _message;
|
||||
int _offset;
|
||||
String _uniqueName;
|
||||
|
||||
@override
|
||||
String get correction {
|
||||
_correction ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 4, '');
|
||||
return _correction;
|
||||
}
|
||||
|
||||
@override
|
||||
int get length {
|
||||
_length ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
|
||||
return _length;
|
||||
}
|
||||
|
||||
@override
|
||||
String get message {
|
||||
_message ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 3, '');
|
||||
return _message;
|
||||
}
|
||||
|
||||
@override
|
||||
int get offset {
|
||||
_offset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 0, 0);
|
||||
return _offset;
|
||||
}
|
||||
|
||||
@override
|
||||
String get uniqueName {
|
||||
_uniqueName ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 2, '');
|
||||
return _uniqueName;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _AnalysisDriverUnitErrorMixin implements idl.AnalysisDriverUnitError {
|
||||
@override
|
||||
Map<String, Object> toJson() {
|
||||
Map<String, Object> _result = <String, Object>{};
|
||||
if (correction != '') _result["correction"] = correction;
|
||||
if (length != 0) _result["length"] = length;
|
||||
if (message != '') _result["message"] = message;
|
||||
if (offset != 0) _result["offset"] = offset;
|
||||
if (uniqueName != '') _result["uniqueName"] = uniqueName;
|
||||
return _result;
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Object> toMap() => {
|
||||
"correction": correction,
|
||||
"length": length,
|
||||
"message": message,
|
||||
"offset": offset,
|
||||
"uniqueName": uniqueName,
|
||||
};
|
||||
|
||||
@override
|
||||
String toString() => convert.JSON.encode(toJson());
|
||||
}
|
||||
|
||||
class CodeRangeBuilder extends Object with _CodeRangeMixin implements idl.CodeRange {
|
||||
int _length;
|
||||
int _offset;
|
||||
|
|
|
@ -781,6 +781,46 @@ enum UnlinkedParamKind : byte {
|
|||
named
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a resolved unit.
|
||||
*/
|
||||
table AnalysisDriverResolvedUnit {
|
||||
/**
|
||||
* The full list of analysis errors, both syntactic and semantic.
|
||||
*/
|
||||
errors:[AnalysisDriverUnitError] (id: 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about an error in a resolved unit.
|
||||
*/
|
||||
table AnalysisDriverUnitError {
|
||||
/**
|
||||
* The optional correction hint for the error.
|
||||
*/
|
||||
correction:string (id: 4);
|
||||
|
||||
/**
|
||||
* The length of the error in the file.
|
||||
*/
|
||||
length:uint (id: 1);
|
||||
|
||||
/**
|
||||
* The message of the error.
|
||||
*/
|
||||
message:string (id: 3);
|
||||
|
||||
/**
|
||||
* The offset from the beginning of the file.
|
||||
*/
|
||||
offset:uint (id: 0);
|
||||
|
||||
/**
|
||||
* The unique name of the error code.
|
||||
*/
|
||||
uniqueName:string (id: 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about an element code range.
|
||||
*/
|
||||
|
|
|
@ -57,6 +57,56 @@ import 'format.dart' as generated;
|
|||
*/
|
||||
const informative = null;
|
||||
|
||||
/**
|
||||
* Information about a resolved unit.
|
||||
*/
|
||||
@TopLevel('ADRU')
|
||||
abstract class AnalysisDriverResolvedUnit extends base.SummaryClass {
|
||||
factory AnalysisDriverResolvedUnit.fromBuffer(List<int> buffer) =>
|
||||
generated.readAnalysisDriverResolvedUnit(buffer);
|
||||
|
||||
/**
|
||||
* The full list of analysis errors, both syntactic and semantic.
|
||||
*/
|
||||
@Id(0)
|
||||
List<AnalysisDriverUnitError> get errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about an error in a resolved unit.
|
||||
*/
|
||||
abstract class AnalysisDriverUnitError extends base.SummaryClass {
|
||||
/**
|
||||
* The optional correction hint for the error.
|
||||
*/
|
||||
@Id(4)
|
||||
String get correction;
|
||||
|
||||
/**
|
||||
* The length of the error in the file.
|
||||
*/
|
||||
@Id(1)
|
||||
int get length;
|
||||
|
||||
/**
|
||||
* The message of the error.
|
||||
*/
|
||||
@Id(3)
|
||||
String get message;
|
||||
|
||||
/**
|
||||
* The offset from the beginning of the file.
|
||||
*/
|
||||
@Id(0)
|
||||
int get offset;
|
||||
|
||||
/**
|
||||
* The unique name of the error code.
|
||||
*/
|
||||
@Id(2)
|
||||
String get uniqueName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about an element code range.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue