Open DanTup opened 2 years ago
Yes, I saw this before, these two happen periodically internally. I was not able to track them down so far. More data could probably be gathered in places where we load (LibraryContext.load2
) and un-load (AnalysisDriver._removePotentiallyAffectedLibraries
) libraries and see how we load/un-load and maybe why we failed to re-load.
I'm not sure I know enough about this to be able to add more useful detail, although if it helps I did find the log from when I hit this myself.
For me, the thing left in the list was package:dds/src/dap/protocol_generated.dart
and it seems to have happened after VS code sent notifications to both open and then immediately close file:///Users/danny/Dev/Google/flutter/bin/cache/dart-sdk/lib/core/object.dart
. This happens when you hold Ctrl and hover over something in VS Code - it opens the file to get a preview of the contents but immediately closes (IMO this is strange behaviour, a side effect of VS Code opening and closing the file internally but triggering events to extensions), though I'm not sure if that's related.
[2:20:22 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///Users/danny/Dev/Google/flutter/bin/cache/dart-sdk/lib/core/object.dart","languageId":"dart","version":1,"text":"// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file\n// for details. All rights reserved. Use of this source code is governed by a\n// BSD-style license that can be found in the LICENSE file.\n\npart of dart.core;\n\n/// The base class for all Dart objects except `null`.\n///\n/// Because `Object` is a root of the non-nullable Dart class hierarchy,\n/// every other non-`Null` Dart class is a subclass of `Object`.\n///\n/// When you define a class, you should consider overriding [toString]\n/// to return a string describing an instance of that class.\n/// You might also need to define [hashCode] and [operator ==], as described in the\n/// [Implementing map keys](https://dart.dev/guides/libraries/library-tour#implementing-map-keys)\n/// section of the [library tour](https://dart.dev/guides/libraries/library-tour).\n@pragma(\"vm:entry-point\")\nclass Object {\n /// Creates a new [Object] instance.\n ///\n /// [Object] instances have no meaningful state, and are only useful\n /// through their identity. An [Object] instance is equal to itself\n /// only.\n @pragma(\"vm:recognized\", \"other\")\n const Object();\n\n /// The equality operator.\n ///\n /// The default behavior for all [Object]s is to return true if and\n /// only if this object and [other] are the same object.\n ///\n /// Override this method to specify a different equality relation on\n /// a class. The overriding method must still be an equivalence relation.\n /// That is, it must be:\n ///\n /// * Total: It must return a boolean for all arguments. It should never throw.\n ///\n /// * Reflexive: For all objects `o`, `o == o` must be true.\n ///\n /// * Symmetric: For all objects `o1` and `o2`, `o1 == o2` and `o2 == o1` must\n /// either both be true, or both be false.\n ///\n /// * Transitive: For all objects `o1`, `o2`, and `o3`, if `o1 == o2` and\n /// `o2 == o3` are true, then `o1 == o3` must be true.\n ///\n /// The method should also be consistent over time,\n /// so whether two objects are equal should only change\n /// if at least one of the objects was modified.\n ///\n /// If a subclass overrides the equality operator, it should override\n /// the [hashCode] method as well to maintain consistency.\n external bool operator ==(Object other);\n\n /// The hash code for this object.\n ///\n /// A hash code is a single integer which represents the state of the object\n /// that affects [operator ==] comparisons.\n ///\n /// All objects have hash codes.\n /// The default hash code implemented by [Object]\n /// represents only the identity of the object,\n /// the same way as the default [operator ==] implementation only considers objects\n /// equal if they are identical (see [identityHashCode]).\n ///\n /// If [operator ==] is overridden to use the object state instead,\n /// the hash code must also be changed to represent that state,\n /// otherwise the object cannot be used in hash based data structures\n /// like the default [Set] and [Map] implementations.\n ///\n /// Hash codes must be the same for objects that are equal to each other\n /// according to [operator ==].\n /// The hash code of an object should only change if the object changes\n /// in a way that affects equality.\n /// There are no further requirements for the hash codes.\n /// They need not be consistent between executions of the same program\n /// and there are no distribution guarantees.\n ///\n /// Objects that are not equal are allowed to have the same hash code.\n /// It is even technically allowed that all instances have the same hash code,\n /// but if clashes happen too often,\n /// it may reduce the efficiency of hash-based data structures\n /// like [HashSet] or [HashMap].\n ///\n /// If a subclass overrides [hashCode], it should override the\n /// [operator ==] operator as well to maintain consistency.\n external int get hashCode;\n\n /// A string representation of this object.\n ///\n /// Some classes have a default textual representation,\n /// often paired with a static `parse` function (like [int.parse]).\n /// These classes will provide the textual representation as\n /// their string representation.\n ///\n /// Other classes have no meaningful textual representation\n /// that a program will care about.\n /// Such classes will typically override `toString` to provide\n /// useful information when inspecting the object,\n /// mainly for debugging or logging.\n external String toString();\n\n /// Invoked when a non-existent method or property is accessed.\n ///\n /// A dynamic member invocation can attempt to call a member which\n /// doesn't exist on the receiving object. Example:\n /// ```dart\n /// dynamic object = 1;\n /// object.add(42); // Statically allowed, run-time error\n /// ```\n /// This invalid code will invoke the `noSuchMethod` method\n /// of the integer `1` with an [Invocation] representing the\n /// `.add(42)` call and arguments (which then throws).\n ///\n /// Classes can override [noSuchMethod] to provide custom behavior\n /// for such invalid dynamic invocations.\n ///\n /// A class with a non-default [noSuchMethod] invocation can also\n /// omit implementations for members of its interface.\n /// Example:\n /// ```dart\n /// class MockList<T> implements List<T> {\n /// noSuchMethod(Invocation invocation) {\n /// log(invocation);\n /// super.noSuchMethod(invocation); // Will throw.\n /// }\n /// }\n /// void main() {\n /// MockList().add(42);\n /// }\n /// ```\n /// This code has no compile-time warnings or errors even though\n /// the `MockList` class has no concrete implementation of\n /// any of the `List` interface methods.\n /// Calls to `List` methods are forwarded to `noSuchMethod`,\n /// so this code will `log` an invocation similar to\n /// `Invocation.method(#add, [42])` and then throw.\n ///\n /// If a value is returned from `noSuchMethod`,\n /// it becomes the result of the original invocation.\n /// If the value is not of a type that can be returned by the original\n /// invocation, a type error occurs at the invocation.\n ///\n /// The default behavior is to throw a [NoSuchMethodError].\n @pragma(\"vm:entry-point\")\n external dynamic noSuchMethod(Invocation invocation);\n\n /// A representation of the runtime type of the object.\n external Type get runtimeType;\n\n /// Creates a combined hash code for a number of objects.\n ///\n /// The hash code is computed for all arguments that are actually\n /// supplied, even if they are `null`, by numerically combining the\n /// [Object.hashCode] of each argument.\n ///\n /// Example:\n /// ```dart\n /// class SomeObject {\n /// final Object a, b, c;\n /// SomeObject(this.a, this.b, this.c);\n /// bool operator ==(Object other) =>\n /// other is SomeObject && a == other.a && b == other.b && c == other.c;\n /// int get hashCode => Object.hash(a, b, c);\n /// }\n /// ```\n ///\n /// The computed value will be consistent when the function is called\n /// with the same arguments multiple times\n /// during the execution of a single program.\n ///\n /// The hash value generated by this function is *not* guaranteed to be stable\n /// over different runs of the same program,\n /// or between code run in different isolates of the same program.\n /// The exact algorithm used may differ between different platforms,\n /// or between different versions of the platform libraries,\n /// and it may depend on values that change on each program execution.\n ///\n /// The [hashAll] function gives the same result as this function when\n /// called with a collection containing the actual arguments\n /// to this function in the same order.\n @Since(\"2.14\")\n static int hash(Object? object1, Object? object2,\n [Object? object3 = sentinelValue,\n Object? object4 = sentinelValue,\n Object? object5 = sentinelValue,\n Object? object6 = sentinelValue,\n Object? object7 = sentinelValue,\n Object? object8 = sentinelValue,\n Object? object9 = sentinelValue,\n Object? object10 = sentinelValue,\n Object? object11 = sentinelValue,\n Object? object12 = sentinelValue,\n Object? object13 = sentinelValue,\n Object? object14 = sentinelValue,\n Object? object15 = sentinelValue,\n Object? object16 = sentinelValue,\n Object? object17 = sentinelValue,\n Object? object18 = sentinelValue,\n Object? object19 = sentinelValue,\n Object? object20 = sentinelValue]) {\n if (sentinelValue == object3) {\n return SystemHash.hash2(object1.hashCode, object2.hashCode, _hashSeed);\n }\n if (sentinelValue == object4) {\n return SystemHash.hash3(\n object1.hashCode, object2.hashCode, object3.hashCode, _hashSeed);\n }\n if (sentinelValue == object5) {\n return SystemHash.hash4(object1.hashCode, object2.hashCode,\n object3.hashCode, object4.hashCode, _hashSeed);\n }\n if (sentinelValue == object6) {\n return SystemHash.hash5(object1.hashCode, object2.hashCode,\n object3.hashCode, object4.hashCode, object5.hashCode, _hashSeed);\n }\n if (sentinelValue == object7) {\n return SystemHash.hash6(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object8) {\n return SystemHash.hash7(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object9) {\n return SystemHash.hash8(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object10) {\n return SystemHash.hash9(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object11) {\n return SystemHash.hash10(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n object10.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object12) {\n return SystemHash.hash11(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n object10.hashCode,\n object11.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object13) {\n return SystemHash.hash12(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n object10.hashCode,\n object11.hashCode,\n object12.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object14) {\n return SystemHash.hash13(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n object10.hashCode,\n object11.hashCode,\n object12.hashCode,\n object13.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object15) {\n return SystemHash.hash14(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n object10.hashCode,\n object11.hashCode,\n object12.hashCode,\n object13.hashCode,\n object14.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object16) {\n return SystemHash.hash15(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n object10.hashCode,\n object11.hashCode,\n object12.hashCode,\n object13.hashCode,\n object14.hashCode,\n object15.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object17) {\n return SystemHash.hash16(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n object10.hashCode,\n object11.hashCode,\n object12.hashCode,\n object13.hashCode,\n object14.hashCode,\n object15.hashCode,\n object16.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object18) {\n return SystemHash.hash17(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n object10.hashCode,\n object11.hashCode,\n object12.hashCode,\n object13.hashCode,\n object14.hashCode,\n object15.hashCode,\n object16.hashCode,\n object17.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object19) {\n return SystemHash.hash18(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n object10.hashCode,\n object11.hashCode,\n object12.hashCode,\n object13.hashCode,\n object14.hashCode,\n object15.hashCode,\n object16.hashCode,\n object17.hashCode,\n object18.hashCode,\n _hashSeed);\n }\n if (sentinelValue == object20) {\n return SystemHash.hash19(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n object10.hashCode,\n object11.hashCode,\n object12.hashCode,\n object13.hashCode,\n object14.hashCode,\n object15.hashCode,\n object16.hashCode,\n object17.hashCode,\n object18.hashCode,\n object19.hashCode,\n _hashSeed);\n }\n return SystemHash.hash20(\n object1.hashCode,\n object2.hashCode,\n object3.hashCode,\n object4.hashCode,\n object5.hashCode,\n object6.hashCode,\n object7.hashCode,\n object8.hashCode,\n object9.hashCode,\n object10.hashCode,\n object11.hashCode,\n object12.hashCode,\n object13.hashCode,\n object14.hashCode,\n object15.hashCode,\n object16.hashCode,\n object17.hashCode,\n object18.hashCode,\n object19.hashCode,\n object20.hashCode,\n _hashSeed);\n }\n\n /// Creates a combined hash code for a sequence of objects.\n ///\n /// The hash code is computed for elements in [objects],\n /// even if they are `null`,\n /// by numerically combining the [Object.hashCode] of each element\n /// in iteration order.\n ///\n /// The result of `hashAll([o])` is not `o.hashCode`.\n ///\n /// Example:\n /// ```dart\n /// class SomeObject {\n /// final List<String> path;\n /// SomeObject(this.path);\n /// bool operator ==(Object other) {\n /// if (other is SomeObject) {\n /// if (path.length != other.path.length) return false;\n /// for (int i = 0; i < path.length; i++) {\n /// if (path[i] != other.path[i]) return false;\n /// }\n /// return true;\n /// }\n /// return false;\n /// }\n ///\n /// int get hashCode => Object.hashAll(path);\n /// }\n /// ```\n ///\n /// The computed value will be consistent when the function is called\n /// again with objects that have the same hash codes in the same order\n /// during an execution of a single program.\n ///\n /// The hash value generated by this function is *not* guaranteed to be stable\n /// over different runs of the same program,\n /// or between code run in different isolates of the same program.\n /// The exact algorithm used may differ between different platforms,\n /// or between different versions of the platform libraries,\n /// and it may depend on values that change on each program execution.\n @Since(\"2.14\")\n static int hashAll(Iterable<Object?> objects) {\n int hash = _hashSeed;\n for (var object in objects) {\n hash = SystemHash.combine(hash, object.hashCode);\n }\n return SystemHash.finish(hash);\n }\n\n /// Creates a combined hash code for a collection of objects.\n ///\n /// The hash code is computed for elements in [objects],\n /// even if they are `null`,\n /// by numerically combining the [Object.hashCode] of each element\n /// in an order independent way.\n ///\n /// The result of `unorderedHashAll({o})` is not `o.hashCode`.\n ///\n /// Example:\n /// ```dart\n /// bool setEquals<T>(Set<T> set1, Set<T> set2) {\n /// var hashCode1 = Object.unorderedHashAll(set1);\n /// var hashCode2 = Object.unorderedHashAll(set2);\n /// if (hashCode1 != hashCode2) return false;\n /// // Compare elements ...\n /// }\n /// ```\n ///\n /// The computed value will be consistent when the function is called\n /// again with objects that have the same hash codes\n /// during an execution of a single program,\n /// even if the objects are not necessarily in the same order,\n ///\n /// The hash value generated by this function is *not* guaranteed to be stable\n /// over different runs of the same program.\n /// The exact algorithm used may differ between different platforms,\n /// or between different versions of the platform libraries,\n /// and it may depend on values that change per program run\n @Since(\"2.14\")\n static int hashAllUnordered(Iterable<Object?> objects) {\n int sum = 0;\n int count = 0;\n const int mask = 0x3FFFFFFF;\n for (var object in objects) {\n int objectHash = SystemHash.smear(object.hashCode);\n sum = (sum + objectHash) & mask;\n count += 1;\n }\n return SystemHash.hash2(sum, count);\n }\n}\n\n// A per-isolate seed for hash code computations.\nfinal int _hashSeed = identityHashCode(Object);\n"}}}
[2:20:22 PM] [Analyzer] [Info] ==> Content-Length: 165
[2:20:22 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","method":"textDocument/didClose","params":{"textDocument":{"uri":"file:///Users/danny/Dev/Google/flutter/bin/cache/dart-sdk/lib/core/object.dart"}}}
[2:20:22 PM] [Analyzer] [Info] <== Content-Length: 146
Content-Type: application/vscode-jsonrpc; charset=utf-8
[2:20:22 PM] [Analyzer] [Info] <== {"method":"window/showMessage","params":{"type":1,"message":"An error occurred while handling textDocument/didOpen notification"},"jsonrpc":"2.0"}
[2:20:22 PM] [Analyzer] [Info] <== Content-Length: 3958
Content-Type: application/vscode-jsonrpc; charset=utf-8
{"method":"window/logMessage","params":{"type":1,"message":"An error occurred while handling textDocument/didOpen notification: Bad state: Expected to link dart:core and dart:async first: [package:dds/src/dap/protocol_generated.dart]\n#0 LinkedElementFactory.removeLibraries (package:analyzer/src/summary2/linked_element_factory.dart:224:9)\n#1 AnalysisDriver._removePotentiallyAffectedLibraries (package:analyzer/src/dart/analysis/driver.dart:1786:37)\n#2 AnalysisDriver.changeFile (package:analyzer/src/dart/analysis/driver.dart:510:7)\n#3 LspAnalysisServer._afterOverlayChanged.<anonymous closure> (package:analysis_server/src/lsp/lsp_analysis_server.dart:674:49)\n#4 _HashMapValueIterable.forEach.<anonymous closure> (dart:collection-patch/collection_patch.dart:471:13)\n#5 _HashMap.forEach (dart:collection-patch/collection_patch.dart:164:15)\n#6 _HashMapValueIterable.forEach (dart:collection-patch/collection_patch.dart:470:10)\n#7 LspAnalysisServer._afterOverlayChanged (package:analysis_server/src/lsp/lsp_analysis_server.dart:674:22)\n#8 LspAnalysisServer.onOverlayCreated (package:analysis_server/src/lsp/lsp_analysis_server.dart:416:5)\n#9 TextDocumentOpenHandler.handle.<anonymous closure> (package:analysis_server/src/lsp/handlers/handler_text_document_changes.dart:106:14)\n#10 ErrorOr.mapResult (package:analysis_server/lsp_protocol/protocol_special.dart:249:12)\n#11 TextDocumentOpenHandler.handle (package:analysis_server/src/lsp/handlers/handler_text_document_changes.dart:99:17)\n#12 MessageHandler.handleMessage (package:analysis_server/src/lsp/handlers/handlers.dart:150:12)\n#13 ServerStateMessageHandler.handleMessage (package:analysis_server/src/lsp/handlers/handlers.dart:181:22)\n#14 LspAnalysisServer.handleMessage.<anonymous closure> (package:analysis_server/src/lsp/lsp_analysis_server.dart:340:47)\n#15 LspAnalysisServer.handleMessage.<anonymous closure> (package:analysis_server/src/lsp/lsp_analysis_server.dart:325:21)\n#16 _rootRun (dart:async/zone.dart:1426:13)\n#17 _CustomZone.run (dart:async/zone.dart:1328:19)\n#18 _runZoned (dart:async/zone.dart:1861:10)\n#19 runZonedGuarded (dart:async/zone.dart:1849:12)\n#20 LspAnalysisServer.handleMessage (package:analysis_server/src/lsp/lsp_analysis_server.dart:325:5)\n#21 LspByteStreamServerChannel._readMessage (package:analysis_server/src/lsp/channel/lsp_byte_stream_channel.dart:87:16)\n#22 LspByteStreamServerChannel.listen.<anonymous closure> (package:analysis_server/src/lsp/channel/lsp_byte_stream_channel.dart:54:24)\n#23 _rootRunUnary (dart:async/zone.dart:1434:47)\n#24 _CustomZone.runUnary (dart:async/zone.dart:1335:19)\n#25 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)\n#26 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)\n#27 _DelayedData.perform (dart:async/stream_impl.dart:591:14)\n#28 _StreamImplEvents.handleNext (dart:async/stream_impl.dart:706:11)\n#29 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:663:7)\n#30 _rootRun (dart:async/zone.dart:1418:47)\n#31 _CustomZone.run (dart:async/zone.dart:1328:19)\n#32 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)\n#33 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)\n#34 _rootRun (dart:async/zone.dart:1426:13)\n#35 _CustomZone.run (dart:async/zone.dart:1328:19)\n#36 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)\n#37 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)\n#38 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)\n#39 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)\n#40 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:122:13)\n#41 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:193:5)\n"},"jsonrpc":"2.0"}Content-Length: 99
Content-Type: application/vscode-jsonrpc; charset=utf-8
hmm, the log in https://github.com/Dart-Code/Dart-Code/issues/3625 also has an open and close right before this happens. I wonder if some async work in opening a file could result in it not being complete before the close is being handled?
Yes, somehow this URI package:dds/src/dap/protocol_generated.dart
is left after dart:core
was removed. Theoretically any library one way or another imports dart:core
, so when a file from dart:core
is reported as changed, we should remove all libraries at all. But apparently this did not happen. Maybe this remaining library somehow referenced another version of dart:core
? Or was not able to resolve dart:core
? I don't know.
I don't have any ideas either. I don't know how it would reference a different dart:core
, although from my log above seems like I was using the Dart SDK from inside the Flutter SDK (I'm not sure if that's relevant).
so when a file from
dart:core
is reported as changed
Hmm, this initially sounded odd - I wasn't modifying anything in dart:core
.. but I think I understand what happened:
dart:core
Cmd
... this caused VS Code to decide to try and show a preview of the file containing the source definition in the tooltip, which...It seems unfortunate that hovering over a symbol inside a users own file in the editor can result in triggering this work. I wonder if it could be avoided? (it doesn't fix the underlying bug here, although it would probably significantly reduce the chance of it happening because it's unlikely dart:core
is actually modified by most users).
We can't prevent the didOpen
/didClose
events getting to the LSP server currently, but maybe we could skip the call to driver.changeFile()
if the contents have not been modified?
This came up at https://github.com/dart-lang/sdk/issues/48458. Some info that may or may not be relevant from that thread:
Maybe relevant info
- Only seeing this in a low memory environment (4GB). I have yet to see it on my 32GB PC.
- We have yet to convert our codebase to sound null safety.
- Fairly big codebase: 140.000+ lines.
This came up at #48458. Some info that may or may not be relevant from that thread:
Maybe relevant info
- Only seeing this in a low memory environment (4GB). I have yet to see it on my 32GB PC.
- We have yet to convert our codebase to sound null safety.
- Fairly big codebase: 140.000+ lines.
I am having this crash multiple times a day, doesn't matter the type of project (both in projects with and without null safety), nor the project size. I have 32 GB of RAM on my machine. It doesn't happen on my macbook though, but I also don't use it as much.
Flutter doctor: [✓] Flutter (Channel stable, 2.10.3, on Ubuntu 20.04.4 LTS 5.13.0-35-generic, locale ro_RO.UTF-8) • Flutter version 2.10.3 at /home/adrian/Programe/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 7e9793dee1 (2 weeks ago), 2022-03-02 11:23:12 -0600 • Engine revision bd539267b4 • Dart version 2.16.1 • DevTools version 2.9.2
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc1) • Android SDK at /home/adrian/Android/Sdk • Platform android-31, build-tools 33.0.0-rc1 • ANDROID_SDK_ROOT = /home/adrian/Android/Sdk • Java binary at: /home/adrian/Programe/android-studio/jre/bin/java • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822) • All Android licenses accepted.
[✓] Chrome - develop for the web • Chrome at google-chrome
[✓] Linux toolchain - develop for Linux desktop • clang version 10.0.0-4ubuntu1 • cmake version 3.16.3 • ninja version 1.10.0 • pkg-config version 0.29.1
[✓] Android Studio (version 2021.1) • Android Studio at /home/adrian/Programe/android-studio • Flutter plugin version 65.2.2 • Dart plugin version 211.7808 • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
[✓] VS Code • VS Code at /snap/code/current • Flutter extension version 3.36.0
[✓] Connected device (2 available) • Linux (desktop) • linux • linux-x64 • Ubuntu 20.04.4 LTS 5.13.0-35-generic • Chrome (web) • chrome • web-javascript • Google Chrome 99.0.4844.74
[✓] HTTP Host Availability • All required HTTP hosts are available
• No issues found!
It usually happens when I have left Ctrl button pressed.
@scheglov @DanTup Do we have a way to move forward with this issue?
I do still see this (though very infrequently) but haven't been able to reproduce it either manually or in a test. All the reports that have logs seem to contain the same thing, a textDocument/didOpen
call followed immediately by a textDocument/didClose
call for an SDK file. VS Code sends these when you hover over something holding Ctrl down as it opens the file to get a preview of the definition for the hover tooltip (something also specifically called out above).
So my feeling is that there could be some race when a file is opened (overlay created) and closed (overlay destroyed) in a short space of time.
One thing that might reduce the chance of it happening would be to short-cut and not trigger this code when an overlay is created if it doesn't actually change the contents:
#3 AnalysisDriver._removePotentiallyAffectedLibraries (package:analyzer/src/dart/analysis/driver.dart:1708:13)
#4 AnalysisDriver.changeFile (package:analyzer/src/dart/analysis/driver.dart:507:7)
#5 LspAnalysisServer._afterOverlayChanged.<anonymous closure> (package:analysis_server/src/lsp/lsp_analysis_server.dart:674:49)
#6 _HashMapValueIterable.forEach.<anonymous closure> (dart:collection-patch/collection_patch.dart:471:13)
#7 _HashMap.forEach (dart:collection-patch/collection_patch.dart:164:15)
#8 _HashMapValueIterable.forEach (dart:collection-patch/collection_patch.dart:470:10)
#9 LspAnalysisServer._afterOverlayChanged (package:analysis_server/src/lsp/lsp_analysis_server.dart:674:22)
#10 LspAnalysisServer.onOverlayCreated (package:analysis_server/src/lsp/lsp_analysis_server.dart:416:5)
In the cases that are triggering this, an SDK file is being opened, but it's content is almost certainly the same as on disk, but we still end up calling AnalysisDriver.changeFile
. If we could quickly check the content and skip this, it's possible a lot of the cases will go away (although, the underlying issue will still remain).
If that seems like a sensible thing to do, isAnalysisDriver.changeFile
the right place for it, or should it be done further up in the server(s) before they call this?
(Edit: I pasted the integration test I'd been using to try and repro here in case it's useful to come back to so I don't lose it)
... for an SDK file.
Out of curiosity, is this for a file in either dart:core
or dart:async
, or is this a different SDK library? (I have no idea whether it matters.)
In the cases that are triggering this, an SDK file is being opened, but it's content is almost certainly the same as on disk ...
I hadn't realized that didOpen
passed over the content of the file.
If we could quickly check the content and skip this ...
That sounds good, but I'm not sure how that plays with the watcher. We'll need to think about possible timing scenarios.
... is
AnalysisDriver.changeFile
the right place for it ...
I'd be more comfortable putting the check in the code that's going to call AnalysisDriver.changeFile
(presumably the didOpen
handler). I don't think we want to introduce a file read everywhere that we're reporting that a file has changed because most of the time the file has really changed.
Out of curiosity, is this for a file in either dart:core or dart:async, or is this a different SDK library? (I have no idea whether it matters.)
In one of my repros above, the file was flutter/bin/cache/dart-sdk/lib/core/object.dart
and in https://github.com/Dart-Code/Dart-Code/issues/3625 it was dart-sdk/sdk/out/ReleaseX64/dart-sdk/lib/core/int.dart
. It's a small sample, but both are from dart:core
.
That sounds good, but I'm not sure how that plays with the watcher. We'll need to think about possible timing scenarios.
I'm not sure if I understand the scenario you have in mind. The didOpen
request for LSP is sent when the IDE is claiming control over the file contents now. I don't expect there to be any relevant watcher events when this happens. It is possible the content we're given doesn't match the disk (for example if VS Code was restoring an unsaved file during startup), but that should be an easy check.
I'd be more comfortable putting the check in the code that's going to call
AnalysisDriver.changeFile
(presumably thedidOpen
handler). I don't think we want to introduce a file read everywhere that we're reporting that a file has changed because most of the time the file has really changed.
Yeah, that makes more sense. onOverlayCreated
may be the right place (it's what creates the overlay, and I we still want that to happen in this case, but then note bother calling _onOverlayChanged
if the content was identical). I'll do some testing, thanks!
It seems sad to try to hide an issue by adding workarounds. Ideally we need to reproduce and fix it.
It sounds like it might not be too hard to reproduce now that we know some files that trigger it. Though it looks like a timing issue, probably when we ask to resolve a file in the core library before we've built the core library (and hence the type provider, etc.), and those can sometimes be tricky.
It seems sad to try to hide an issue by adding workarounds. Ideally we need to reproduce and fix it.
I agree we need to track this down and fix it - although my suggestion wasn't to hide or workaround it. It seems like the issue is being triggered where we're work under the assumption that an SDK library has been modified when it has not. I think the change above may make sense regardless of this issue (for performance reasons) - especially given VS Code triggers opening+closing on a bunch of files the user doesn't even open when it just wants to show previews in tooltips etc.?
How do you run the test? To which class do you add this method?
Yes, it might be some timing issue.
It looks to me that it is not so easy to check if a change should have any effect. We want to know if the content is different than what is in FileState
for this file in every AnalysisDriver
. Although this also means that we might be lucky - we don't have to read the file.
I was running the test in the LSP diagnostic test class here:
I tried a bunch of different things (with/without await
s, pumpEventQueue
etc. to try and affect timing) and ran it lots of times, without any luck :(
We want to know if the content is different than what is in
FileState
for this file in everyAnalysisDriver
.
In what situations might each driver not have the same content? I thought we could read the file once (through resourceProvider
?) and then skip the changeFile
call for all drivers if the content was identical to the overlay. I hadn't got as far as trying to actually do it yet though.
Race conditions are hard :-)
Well, you are right, in the server the content of a file must be the same for all drivers. So, this might work, at least I cannot think out why not.
If that helps - I've got
Bad state: Expected to link dart:core and dart:async together: [dart:core/annotations.dart, dart:core]
#0 LinkedElementFactory.removeLibraries (package:analyzer/src/summary2/linked_element_factory.dart:260:9)
#1 LibraryContext.remove (package:analyzer/src/dart/analysis/library_context.dart:265:20)
#2 AnalysisDriver._removePotentiallyAffectedLibraries (package:analyzer/src/dart/analysis/driver.dart:1711:22)
#3 AnalysisDriver._applyPendingFileChanges (packa…
when navigating in vs code into @override
, Iterable's .last
, etc
I am also getting a similar error as @emakar, several times a day.
[3:30:08 PM] [Analyzer] [Error] Unhandled exception:
Bad state: Expected to link dart:core and dart:async together: [dart:core/string.dart, dart:core]
#0 LinkedElementFactory.removeLibraries (package:analyzer/src/summary2/linked_element_factory.dart:260:9)
#1 LibraryContext.remove (package:analyzer/src/dart/analysis/library_context.dart:265:20)
#2 AnalysisDriver._removePotentiallyAffectedLibraries (package:analyzer/src/dart/analysis/driver.dart:1711:22)
#3 AnalysisDriver._applyPendingFileChanges (packa…
and they also usually occur when navigating to an area of the code, or saving a file.
full log:
I made a change in https://github.com/dart-lang/sdk/commit/0add39a68e145329a38fc215b99e1c468440d765 which I hoped would reduce the chance of this (it always seemed to be related to overlays for SDK files which are rarely modified, so may not need overlays).
It's not clear that worked, but it looks like when a file is closed in VS Code we still unconditionally call driver.changeFile()
without first checking whether that file even had an overlay (we're only skipping it when the overlay is created). I'll look at applying the same change to onOverlayDestroyed
which I think will have the original intended improvement (which doesn't fix the underlying issue, but should prevent it from being triggered as much).
I also seem to encounter this when navigating to definitions while working on Flutter. Here are some more logs, in case it's of any use:
I am getting this crash ~50 times a day Dart v3.86.0
{"id":1932,"jsonrpc":"2.0","result":{"contents":{"kind":"markdown","value":"```dart\n(new) DateTime DateTime.now()\n```\n*dart:core*\n\n---\nConstructs a [DateTime] instance with current date and time in the\nlocal time zone.\n\n```dart\nfinal now = DateTime.now();\n```"},"range":{"end":{"character":31,"line":793},"start":{"character":19,"line":793}}}}
[3:46:03 PM] [Analyzer] [Info] ==> Content-Length: 34765
[3:46:03 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///home/user/Documents/misc/flutter/bin/cache/pkg/sky_engine/lib/core/date_time.dart","languageId":"dart","version":1,"text":"// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file\n// for details. All rights reserved. Use of this source code is governed by a\n// BSD-style license that can be found in the LICENSE file.\n\npart of dart.core;\n\n/// An instant in time, such as July 2…
[3:46:03 PM] [Analyzer] [Info] ==> Content-Length: 212
[3:46:03 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","method":"textDocument/didClose","params":{"textDocument":{"uri":"file:///home/user/Documents/misc/flutter/bin/cache/pkg/sky_engine/lib/core/date_time.dart"}},"clientRequestTime":1713440763711}
[3:46:03 PM] [Analyzer] [Error] Unhandled exception:
Bad state: Expected to link dart:core and dart:async together: [dart:core/date_time.dart, dart:core]
#0 LinkedElementFactory.removeLibraries (package:analyzer/src/summary2/linked_element_factory.dart:283:9)
#1 LibraryContext.remove (package:analyzer/src/dart/analysis/library_context.dart:274:20)
#2 AnalysisDriver._removePotentiallyAffectedLibraries (package:analyzer/src/dart/analysis/driver.dart:1816:22)
#3 AnalysisDriver._applyPendingFileChanges (package…
[3:46:03 PM] [Analyzer] [Info] ==> Content-Length: 357
[3:46:03 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///home/user/Documents/PROJECTS/my_project/lib/chat/chat_room.dart","version":124},"contentChanges":[{"range":{"start":{"line":790,"character":15},"end":{"line":790,"character":25}},"rangeLength":10,"text":"processTask"}]},"clientRequestTime":1713440763742}
[3:46:03 PM] [Analyzer] [Info] Spawning /home/user/Documents/misc/flutter/bin/cache/dart-sdk/bin/dart with args ["language-server","--protocol=lsp","--client-id=VS-Code","--client-version=3.86.0"]
[3:46:03 PM] [Analyzer] [Info] PID: 82843
@scheglov
This error has been reported a few times via the VS Code extension. I'm not able to reproduce it, but I did see it once after working for a few hours and could not reproduce.
@scheglov I see the error comes from https://github.com/dart-lang/sdk/blob/a2fd0da4f9bbdefcea1f5ea395438e7f9949fa2e/pkg/analyzer/lib/src/summary2/linked_element_factory.dart#L224, but I don't understand the context to figure out what might cause it. Have you seen this before? Any ideas on how to get more info?
Perhaps a coincidence, but when I saw this I was working on the analysis server codebase, and the user from the last comment above also seems to have some analyzer packages in the list. There are some other errors also reported in the last issue above, but I'm not sure if they're the same cause - for example: