Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DartAnalyzer exception in WebStorm #25372

Closed
zoechi opened this issue Jan 7, 2016 · 3 comments
Closed

DartAnalyzer exception in WebStorm #25372

zoechi opened this issue Jan 7, 2016 · 3 comments
Assignees
Labels
analyzer-completion Issues with the analysis server's code completion feature analyzer-stability area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P1 A high priority bug; for example, a single project is unusable or has many test failures type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@zoechi
Copy link
Contributor

zoechi commented Jan 7, 2016

[3522266] ERROR - yzer.DartAnalysisServerService - Dart analysis server, SDK version 1.14.0-edge.c6f0d75d81a4a45817be1516449e1d3fe04be223, server version 1.14.0, error: Exception from assist contributor: DefaultAssistContributor
Cannot compute RESOLVED_UNIT for /home/myuser/dart/bwu_ng_iron_list/lib/bwu_ng_iron_list.dart in /home/myuser/dart/bwu_ng_iron_list/lib/bwu_ng_iron_list.dart

0 AnalysisContextImpl.computeResult (package:analyzer/src/context/context.dart:651)

1 AnalysisContextImpl.resolveCompilationUnit2 (package:analyzer/src/context/context.dart:1166)

2 DartAssistContributor.computeAssists.<computeAssists_async_body> (package:analysis_server/plugin/edit/assist/assist_dart.dart:64)

3 Future.Future.microtask. (dart:async/future.dart:144)

4 _rootRun (dart:async/zone.dart:903)

5 _CustomZone.run (dart:async/zone.dart:802)

6 _CustomZone.runGuarded (dart:async/zone.dart:708)

7 _CustomZone.bindCallback. (dart:async/zone.dart:733)

8 _rootRun (dart:async/zone.dart:907)

9 _CustomZone.run (dart:async/zone.dart:802)

10 _CustomZone.runGuarded (dart:async/zone.dart:708)

11 _CustomZone.bindCallback. (dart:async/zone.dart:733)

12 _microtaskLoop (dart:async/schedule_microtask.dart:41)

13 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50)

14 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:96)

15 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:149)

Caused by Unexpected exception while performing ResolveUnitTask for source /home/myuser/dart/bwu_ng_iron_list/lib/bwu_ng_iron_list.dart

0 AnalysisTask._safelyPerform (package:analyzer/task/model.dart:320)

1 AnalysisTask.perform (package:analyzer/task/model.dart:210)

2 AnalysisDriver.performWorkItem (package:analyzer/src/task/driver.dart:271)

3 AnalysisDriver.computeResult (package:analyzer/src/task/driver.dart:109)

4 AnalysisContextImpl.computeResult (package:analyzer/src/context/context.dart:647)

5 AnalysisContextImpl.resolveCompilationUnit2 (package:analyzer/src/context/context.dart:1166)

6 DartAssistContributor.computeAssists.<computeAssists_async_body> (package:analysis_server/plugin/edit/assist/assist_dart.dart:64)

7 Future.Future.microtask. (dart:async/future.dart:144)

8 _rootRun (dart:async/zone.dart:903)

9 _CustomZone.run (dart:async/zone.dart:802)

10 _CustomZone.runGuarded (dart:async/zone.dart:708)

11 _CustomZone.bindCallback. (dart:async/zone.dart:733)

12 _rootRun (dart:async/zone.dart:907)

13 _CustomZone.run (dart:async/zone.dart:802)

14 _CustomZone.runGuarded (dart:async/zone.dart:708)

15 _CustomZone.bindCallback. (dart:async/zone.dart:733)

16 _microtaskLoop (dart:async/schedule_microtask.dart:41)

17 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50)

18 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:96)

19 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:149)

Caused by IllegalArgumentException: Expected 3 parameters, not 2 null

0 ArgumentList.correspondingStaticParameters= (package:analyzer/src/generated/ast.dart:453)

1 StaticTypeAnalyzer._inferMethodInvocationGeneric (package:analyzer/src/generated/static_type_analyzer.dart:1874)

2 StaticTypeAnalyzer._inferMethodInvocation (package:analyzer/src/generated/static_type_analyzer.dart:1816)

3 StaticTypeAnalyzer.visitMethodInvocation (package:analyzer/src/generated/static_type_analyzer.dart:745)

4 MethodInvocation.accept (package:analyzer/src/generated/ast.dart:8214)

5 ResolverVisitor.visitMethodInvocation (package:analyzer/src/generated/resolver.dart:9165)

6 MethodInvocation.accept (package:analyzer/src/generated/ast.dart:8214)

7 AstNode._safelyVisitChild (package:analyzer/src/generated/ast.dart:1110)

8 VariableDeclaration.visitChildren (package:analyzer/src/generated/ast.dart:11913)

9 ResolverVisitor.visitNode (package:analyzer/src/generated/resolver.dart:9177)

10 UnifyingAstVisitor.visitVariableDeclaration (package:analyzer/dart/ast/visitor.dart:1844)

11 ScopedVisitor.visitVariableDeclaration (package:analyzer/src/generated/resolver.dart:10628)

12 ResolverVisitor.visitVariableDeclaration (package:analyzer/src/generated/resolver.dart:9293)

13 VariableDeclaration.accept (package:analyzer/src/generated/ast.dart:11907)

14 NodeList.accept (package:analyzer/src/generated/ast.dart:8612)

15 VariableDeclarationList.visitChildren (package:analyzer/src/generated/ast.dart:12022)

16 ResolverVisitor.visitNode (package:analyzer/src/generated/resolver.dart:9177)

17 UnifyingAstVisitor.visitVariableDeclarationList (package:analyzer/dart/ast/visitor.dart:1848)

18 ResolverVisitor.visitVariableDeclarationList (package:analyzer/src/generated/resolver.dart:9318)

19 VariableDeclarationList.accept (package:analyzer/src/generated/ast.dart:12016)

20 AstNode._safelyVisitChild (package:analyzer/src/generated/ast.dart:1110)

21 VariableDeclarationStatement.visitChildren (package:analyzer/src/generated/ast.dart:12079)

22 ResolverVisitor.visitNode (package:analyzer/src/generated/resolver.dart:9177)

23 UnifyingAstVisitor.visitVariableDeclarationStatement (package:analyzer/dart/ast/visitor.dart:1852)

24 VariableDeclarationStatement.accept (package:analyzer/src/generated/ast.dart:12075)

25 NodeList.accept (package:analyzer/src/generated/ast.dart:8612)

26 Block.visitChildren (package:analyzer/src/generated/ast.dart:1595)

27 ResolverVisitor.visitNode (package:analyzer/src/generated/resolver.dart:9177)

28 UnifyingAstVisitor.visitBlock (package:analyzer/dart/ast/visitor.dart:1545)

29 ScopedVisitor.visitBlock (package:analyzer/src/generated/resolver.dart:10148)

30 Block.accept (package:analyzer/src/generated/ast.dart:1591)

31 AstNode._safelyVisitChild (package:analyzer/src/generated/ast.dart:1110)

32 BlockFunctionBody.visitChildren (package:analyzer/src/generated/ast.dart:1674)

33 ResolverVisitor.visitNode (package:analyzer/src/generated/resolver.dart:9177)

34 UnifyingAstVisitor.visitBlockFunctionBody (package:analyzer/dart/ast/visitor.dart:1548)

35 ScopedVisitor.visitBlockFunctionBody (package:analyzer/src/generated/resolver.dart:10160)

36 ResolverVisitor.visitBlockFunctionBody (package:analyzer/src/generated/resolver.dart:8445)

37 BlockFunctionBody.accept (package:analyzer/src/generated/ast.dart:1670)

38 AstNode._safelyVisitChild (package:analyzer/src/generated/ast.dart:1110)

39 MethodDeclaration.visitChildren (package:analyzer/src/generated/ast.dart:8046)

40 ResolverVisitor.visitNode (package:analyzer/src/generated/resolver.dart:9177)

41 UnifyingAstVisitor.visitMethodDeclaration (package:analyzer/dart/ast/visitor.dart:1726)

42 ScopedVisitor.visitMethodDeclarationInScope (package:analyzer/src/generated/resolver.dart:10554)

43 ResolverVisitor.visitMethodDeclarationInScope (package:analyzer/src/generated/resolver.dart:9138)

44 ScopedVisitor.visitMethodDeclaration (package:analyzer/src/generated/resolver.dart:10546)

45 ResolverVisitor.visitMethodDeclaration (package:analyzer/src/generated/resolver.dart:9129)

46 MethodDeclaration.accept (package:analyzer/src/generated/ast.dart:8037)

47 NodeList.accept (package:analyzer/src/generated/ast.dart:8612)

48 ScopedVisitor.visitClassMembersInScope (package:analyzer/src/generated/resolver.dart:10229)

49 ScopedVisitor.visitClassDeclaration (package:analyzer/src/generated/resolver.dart:10206)

50 ResolverVisitor.visitClassDeclaration (package:analyzer/src/generated/resolver.dart:8487)

51 ClassDeclaration.accept (package:analyzer/src/generated/ast.dart:2277)

52 ResolverVisitor.visitCompilationUnit (package:analyzer/src/generated/resolver.dart:8573)

53 CompilationUnit.accept (package:analyzer/src/generated/ast.dart:2896)

54 ResolveUnitTask.internalPerform (package:analyzer/src/task/dart.dart:4837)

55 AnalysisTask._safelyPerform (package:analyzer/task/model.dart:310)

56 AnalysisTask.perform (package:analyzer/task/model.dart:210)

57 AnalysisDriver.performWorkItem (package:analyzer/src/task/driver.dart:271)

58 AnalysisDriver.computeResult (package:analyzer/src/task/driver.dart:109)

59 AnalysisContextImpl.computeResult (package:analyzer/src/context/context.dart:647)

60 AnalysisContextImpl.resolveCompilationUnit2 (package:analyzer/src/context/context.dart:1166)

61 DartAssistContributor.computeAssists.<computeAssists_async_body> (package:analysis_server/plugin/edit/assist/assist_dart.dart:64)

62 Future.Future.microtask. (dart:async/future.dart:144)

63 _rootRun (dart:async/zone.dart:903)

64 _CustomZone.run (dart:async/zone.dart:802)

65 _CustomZone.runGuarded (dart:async/zone.dart:708)

66 _CustomZone.bindCallback. (dart:async/zone.dart:733)

67 _rootRun (dart:async/zone.dart:907)

68 _CustomZone.run (dart:async/zone.dart:802)

69 _CustomZone.runGuarded (dart:async/zone.dart:708)

70 _CustomZone.bindCallback. (dart:async/zone.dart:733)

71 _microtaskLoop (dart:async/schedule_microtask.dart:41)

72 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50)

73 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:96)

74 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:149)

java.lang.Throwable
at com.intellij.openapi.diagnostic.Logger.error(Logger.java:115)
at com.jetbrains.lang.dart.analyzer.DartAnalysisServerService$1.serverError(DartAnalysisServerService.java:204)
at com.google.dart.server.internal.BroadcastAnalysisServerListener.serverError(BroadcastAnalysisServerListener.java:180)
at com.google.dart.server.internal.remote.processor.NotificationServerErrorProcessor.process(NotificationServerErrorProcessor.java:37)
at com.google.dart.server.internal.remote.RemoteAnalysisServerImpl.processNotification(RemoteAnalysisServerImpl.java:502)
at com.google.dart.server.internal.remote.RemoteAnalysisServerImpl.processResponse(RemoteAnalysisServerImpl.java:517)
at com.google.dart.server.internal.remote.RemoteAnalysisServerImpl.access$600(RemoteAnalysisServerImpl.java:49)
at com.google.dart.server.internal.remote.RemoteAnalysisServerImpl$ServerResponseReaderThread.run(RemoteAnalysisServerImpl.java:868)
[3522267] ERROR - yzer.DartAnalysisServerService - WebStorm 11.0.3 Build #WS-143.1559.5
[3522267] ERROR - yzer.DartAnalysisServerService - JDK: 1.8.0_11
[3522267] ERROR - yzer.DartAnalysisServerService - VM: Java HotSpot(TM) 64-Bit Server VM
[3522267] ERROR - yzer.DartAnalysisServerService - Vendor: Oracle Corporation
[3522267] ERROR - yzer.DartAnalysisServerService - OS: Linux
[3522267] ERROR - yzer.DartAnalysisServerService - Last Action: SaveAll

Dart VM version: 1.14.0-edge.a7ebeb00fbb09b774836239b31d2c7defcc12c9c (Wed Jan 6 17:25:11 2016) on "linux_x64"

  • .analysis_options.
analyzer:
  strong-mode: true
  exclude:
    - '**/*array*'
    - '**/array*'
  language:
    enableSuperMixins: true
linter:
  rules:
    - always_declare_return_types
    - always_specify_types
#    - avoid_as
    - camel_case_types
    - constant_identifier_names
    - empty_constructor_bodies
    - implementation_imports
    - library_names
    - library_prefixes
    - non_constant_identifier_names
    - one_member_abstracts
    - package_api_docs
    - package_prefixed_library_names
    - prefer_is_not_empty
    - slash_for_doc_comments
    - super_goes_last
    - type_annotate_public_apis
    - type_init_formals
#    - unnecessary_brace_in_string_interp
    - unnecessary_getters_setters
    - package_names
  • lib/bwu_ng_iron_list.dart
/// @license
/// Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
/// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
/// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
/// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
/// Code distributed by Google as part of the polymer project is also
/// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt

library bwu_ng_iron_list;

import 'dart:math' show max, min;
import 'dart:html' show CssStyleDeclaration, Element, window;
import 'dart:async' show Future;
import 'package:angular2/angular2.dart';

//<link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html">

/// `iron-list` displays a virtual, 'infinite' list. The template inside
/// the iron-list element represents the DOM to create for each list item.
/// The `items` property specifies an array of list item data.
///
/// For performance reasons, not every item in the list is rendered at once;
/// instead a small subset of actual template elements *(enough to fill the viewport)*
/// are rendered and reused as the user scrolls. As such, it is important that all
/// state of the list template be bound to the model driving it, since the view may
/// be reused with a new model at any time. Particularly, any state that may change
/// as the result of a user interaction with the list item must be bound to the model
/// to avoid view state inconsistency.
///
/// __Important:__ `iron-list` must either be explicitly sized, or delegate scrolling to an
/// explicitly sized parent. By "explicitly sized", we mean it either has an explicit
/// CSS `height` property set via a class or inline style, or else is sized by other
/// layout means (e.g. the `flex` or `fit` classes).
///
/// ### Template model
///
/// List item templates should bind to template models of the following structure:
///
///     {
///       index: 0,     // data index for this item
///       item: {       // user data corresponding to items[index]
///         /* user item data
///       }
///     }
///
/// Alternatively, you can change the property name used as data index by changing the
/// `indexAs` property. The `as` property defines the name of the variable to add to the binding
/// scope for the array.
///
/// For example, given the following `data` array:
///
/// ##### data.json
///
/// ```js
/// [
///   {"name": "Bob"},
///   {"name": "Tim"},
///   {"name": "Mike"}
/// ]
/// ```
///
/// The following code would render the list (note the name and checked properties are
/// bound from the model object provided to the template scope):
///
/// ```html
/// <template is="dom-bind">
///   <iron-ajax url="data.json" last-response="{{data}}" auto></iron-ajax>
///   <iron-list items="[[data]]" as="item">
///     <template>
///       <div>
///         Name: <span>[[item.name]]</span>
///       </div>
///     </template>
///   </iron-list>
/// </template>
/// ```
///
/// ### Styling
///
/// Use the `--iron-list-items-container` mixin to style the container of items, e.g.
///
/// ```css
/// iron-list {
///  --iron-list-items-container: {
///     margin: auto;
///   };
/// }
/// ```
///
/// ### Resizing
///
/// `iron-list` lays out the items when it receives a notification via the `iron-resize` event.
/// This event is fired by any element that implements `IronResizableBehavior`.
///
/// By default, elements such as `iron-pages`, `paper-tabs` or `paper-dialog` will trigger
/// this event automatically. If you hide the list manually (e.g. you use `display: none`)
/// you might want to implement `IronResizableBehavior` or fire this event manually right
/// after the list became visible again. e.g.
///
/// ```js
/// document.querySelector('iron-list').fire('iron-resize');
/// ```
///
/// ### When should `<iron-list>` be used?
///
/// `iron-list` should be used when a page has significantly more DOM nodes than the ones
/// visible on the screen. e.g. the page has 500 nodes, but only 20 are visible at the time.
/// This is why we refer to it as a `virtual` list. In this case, a `dom-repeat` will still
/// create 500 nodes which could slow down the web app, but `iron-list` will only create 20.
///
/// However, having an `iron-list` does not mean that you can load all the data at once.
/// Say, you have a million records in the database, you want to split the data into pages
/// so you can bring a page at the time. The page could contain 500 items, and iron-list
/// will only render 20.
///
/// @group Iron Element
/// @element iron-list
/// @demo demo/index.html Simple list
/// @demo demo/selection.html Selection of items
/// @demo demo/collapse.html Collapsable items

@Component(selector: 'bwu-iron-list')
@View(templateUrl: 'bwu_ng_iron_list.html'
//    directives: const [FORM_DIRECTIVES]
    )
class BwuIronList implements AfterViewInit {
  static final List<Match> IOS =
      new RegExp(r'iP(?:hone|ad;(?: U;)? CPU) OS (\d+)')
          .allMatches(window.navigator.userAgent);
  static final bool IOS_TOUCH_SCROLLING = IOS.isNotEmpty &&
      IOS[1].start >=
          8; // TODO(zoechi) check if this works properly (especiall '.start'
  static final int DEFAULT_PHYSICAL_COUNT = 3;
  static final int MAX_PHYSICAL_COUNT = 500;

  /// An array containing items determining how many instances of the template
  /// to stamp and that that each template instance should bind to.
  @Input() List items;

  /// The name of the variable to add to the binding scope for the array
  /// element associated with a given template instance.
  @Input() String as = 'item';

  /// The name of the variable to add to the binding scope with the index
  /// for the row.
  @Input() String indexAs = 'index';

  /// The name of the variable to add to the binding scope to indicate
  /// if the row is selected.
  @Input() String selectedAs = 'selected';

  /// When true, tapping a row will select the item, placing its data model
  /// in the set of selected items retrievable via the selection property.
  ///
  /// Note that tapping focusable elements within the list item will not
  /// result in selection, since they are presumed to have their * own action.
  @Input() bool selectionEnabled = false;

  /// When `multiSelection` is false, this is the currently selected item, or `null`
  /// if no item is selected.
  @Input() dynamic selectedItem;
  @Output() EventEmitter selectedItemChange = new EventEmitter();

  /// When `multiSelection` is true, this is an array that contains the selected items.
  @Input() dynamic selectedItems;
  @Output() EventEmitter selectedItemsChange = new EventEmitter();

  /// When `true`, multiple items may be selected at once (in this case,
  /// `selected` is an array of currently selected items).  When `false`,
  /// only one item may be selected at a time.
  @Input() bool multiSelection = false;

// TODO(zoechi)
//    observers: [
//      '_itemsChanged(items.*)',
//      '_selectionEnabledChanged(selectionEnabled)',
//      '_multiSelectionChanged(multiSelection)'
//    ],
//
//    behaviors: [
//      Polymer.Templatizer,
//      Polymer.IronResizableBehavior
//    ],

  @HostBinding('iron-resize') void _resizeHandler2(e) => _resizeHandler();

  /// The ratio of hidden tiles that should remain in the scroll direction.
  /// Recommended value ~0.5, so it will distribute tiles evely in both directions.
  double _ratio = 0.5;

  /// The element that controls the scroll
  /// @type {?Element}
  Element _scroller = null;

  /// The padding-top value of the `scroller` element
  int _scrollerPaddingTop = 0;

  /// This value is the same as `scrollTop`.
  int _scrollPosition = 0;

  /// The number of tiles in the DOM.
  int _physicalCount = 0;

  /// The k-th tile that is at the top of the scrolling list.
  int _physicalStart = 0;

  /// The k-th tile that is at the bottom of the scrolling list.
  int _physicalEnd = 0;

  /// The sum of the heights of all the tiles in the DOM.
  int _physicalSize = 0;

  /// The average `offsetHeight` of the tiles observed till now.

  int _physicalAverage = 0;

  /// The number of tiles which `offsetHeight` > 0 observed until now.

  int _physicalAverageCount = 0;

  /// The Y position of the item rendered in the `_physicalStart`
  /// tile relative to the scrolling list.

  int _physicalTop = 0;

  /// The number of items in the list.

  int _virtualCount = 0;

  /// The n-th item rendered in the `_physicalStart` tile.

  int _virtualStartVal = 0;

  /// A map between an item key and its physical item index

  Map<dynamic, int> _physicalIndexForKey = null;

  /// The estimated scroll height based on `_physicalAverage`

  int _estScrollHeight = 0;

  /// The scroll height of the dom node

  int _scrollHeight = 0;

  /// The height of the list. This is referred as the viewport in the context of list.

  int _viewportSize = 0;

  /// An array of DOM nodes that are currently in the tree
  /// @type {?Array<!TemplatizerNode>}

  List _physicalItems = null;

  /// An array of heights for each item in `_physicalItems`
  /// @type {?Array<number>}

  List _physicalSizes = null;

  /// A cached value for the first visible index.
  /// See `firstVisibleIndex`
  /// @type {?number}

  List _firstVisibleIndexVal = null;

  /// A cached value for the last visible index.
  /// See `lastVisibleIndex`
  /// @type {?number}

  List _lastVisibleIndexVal = null;

  /// A Polymer collection for the items.
  /// @type {?Polymer.Collection}

  List _collection = null;

  /// True if the current item list was rendered for the first time
  /// after attached.

  bool _itemsRendered = false;

  /// The page that is currently rendered.

  int _lastPage = null;

  /// The max number of pages to render. One page is equivalent to the height of the list.

  int _maxPages = 3;

  /// The bottom of the physical content.

  int get _physicalBottom => _physicalTop + _physicalSize;

  /// The bottom of the scroll.

  int get _scrollBottom => _scrollPosition + _viewportSize;

  /// The n-th item rendered in the last physical item.

  int get _virtualEnd => _virtualStartVal + _physicalCount - 1;

  /// The lowest n-th value for an item such that it can be rendered in `_physicalStart`.

  int _minVirtualStart = 0;

  /// The largest n-th value for an item such that it can be rendered in `_physicalStart`.

  int get _maxVirtualStart => max(0, _virtualCount - _physicalCount);

  /// The height of the physical content that isn't on the screen.

  int get _hiddenContentSize => _physicalSize - _viewportSize;

  /// The maximum scroll top value.

  int get _maxScrollTop => _estScrollHeight - _viewportSize;

  /// Sets the n-th item rendered in `_physicalStart`

  void set _virtualStart(int val) {
    // clamp the value so that _minVirtualStart <= val <= _maxVirtualStart
    _virtualStartVal = min(_maxVirtualStart, max(_minVirtualStart, val));
    _physicalStart = _virtualStartVal % _physicalCount;
    _physicalEnd = (_physicalStart + _physicalCount - 1) % _physicalCount;
  }

  /// Gets the n-th item rendered in `_physicalStart`

  int get _virtualStart => _virtualStartVal;

  /// An optimal physical size such that we will have enough physical items
  /// to fill up the viewport and recycle when the user scrolls.

  /// This default value assumes that we will at least have the equivalent
  /// to a viewport of physical items above and below the user's viewport.

  int get _optPhysicalSize => _viewportSize * _maxPages;

  /// True if the current list is visible.

  bool get _isVisible =>
      _scroller != null &&
      (_scroller.offsetWidth > 0 || _scroller.offsetHeight > 0);

  /// Gets the index of the first visible item in the viewport.
  ///
  /// @type {number}

  int get firstVisibleIndex {
    int physicalOffset;

    if (_firstVisibleIndexVal == null) {
      physicalOffset = _physicalTop;

      _firstVisibleIndexVal = _iterateItems((int pidx, int vidx) {
            physicalOffset += _physicalSizes[pidx];

            if (physicalOffset > _scrollPosition) {
              return vidx;
            }
          }) ??
          0;
    }

    return _firstVisibleIndexVal;
  }

  /// Gets the index of the last visible item in the viewport.
  ///
  /// @type {number}

  int get lastVisibleIndex {
    int physicalOffset;

    if (_lastVisibleIndexVal == null) {
      physicalOffset = _physicalTop;

      _iterateItems((pidx, vidx) {
        physicalOffset += _physicalSizes[pidx];

        if (physicalOffset <= _scrollBottom) {
          _lastVisibleIndexVal = vidx;
        }
      });
    }

    return _lastVisibleIndexVal;
  }

  void ngAfterViewInit() {
    if (IOS_TOUCH_SCROLLING) {
      _scrollListener = () {
        window.requestAnimationFrame(_scrollHandler);
      };
    } else {
      _scrollListener = _scrollHandler;
    }
  }

  /// When the element has been attached to the DOM tree.

  /// TODO(zoechi) replace attached with proper Angular lifecycle method
  attached() {
    // delegate to the parent's scroller
    // e.g. paper-scroll-header-panel
    var el = Polymer.dom(this);

    var parentNode = /*@type {?{scroller: ?Element}} */ (el.parentNode);
    if (parentNode && parentNode.scroller) {
      _scroller = parentNode.scroller;
    } else {
      _scroller = this;
      classes.add('has-scroller');
    }

    if (IOS_TOUCH_SCROLLING) {
      _scroller.style.setProperty('webkitOverflowScrolling', 'touch');
    }

    _scroller.addEventListener('scroll', _scrollListener);

    updateViewportBoundaries();
    _render();
  }

  /// When the element has been removed from the DOM tree.
  /// TODO(zoechi) replace attached with proper Angular lifecycle method

  detached() {
    _itemsRendered = false;
    if (_scroller) {
      _scroller.removeEventListener('scroll', _scrollListener);
    }
  }

  /// Invoke this method if you dynamically update the viewport's
  /// size or CSS padding.
  ///
  /// @method updateViewportBoundaries

  void updateViewportBoundaries() {
    CssStyleDeclaration scrollerStyle = _scroller.getComputedStyle();
    _scrollerPaddingTop = parseInt(scrollerStyle['padding-top'], 10);
    _viewportSize = _scroller.offsetHeight;
  }

  /// Update the models, the position of the
  /// items in the viewport and recycle tiles as needed.

  _refresh() {
    // clamp the `scrollTop` value
    // IE 10|11 scrollTop may go above `_maxScrollTop`
    // iOS `scrollTop` may go below 0 and above `_maxScrollTop`
    int scrollTop = max(0, min(_maxScrollTop, _scroller.scrollTop));
    int tileHeight, tileTop, kth, scrollBottom, physicalBottom;
    List<int> recycledTileSet;
    double ratio = _ratio;
    int delta = scrollTop - _scrollPosition;
    int recycledTiles = 0;
    int hiddenContentSize = _hiddenContentSize;
    double currentRatio = ratio;
    List<int> movingUp = [];

    // track the last `scrollTop`
    _scrollPosition = scrollTop;

    // clear cached visible index
    _firstVisibleIndexVal = null;
    _lastVisibleIndexVal = null;

    scrollBottom = _scrollBottom;
    physicalBottom = _physicalBottom;

    // random access
    if (delta.abs() > _physicalSize) {
      _physicalTop += delta;
      recycledTiles = (delta / _physicalAverage).round();
    }
    // scroll up
    else if (delta < 0) {
      int topSpace = scrollTop - _physicalTop;
      int virtualStart = _virtualStart;

      recycledTileSet = [];

      kth = _physicalEnd;
      currentRatio = topSpace / hiddenContentSize;

      // move tiles from bottom to top
      while (
          // approximate `currentRatio` to `ratio`
          currentRatio < ratio &&
              // recycle less physical items than the total
              recycledTiles < _physicalCount &&
              // ensure that these recycled tiles are needed
              virtualStart - recycledTiles > 0 &&
              // ensure that the tile is not visible
              physicalBottom - _physicalSizes[kth] > scrollBottom) {
        tileHeight = _physicalSizes[kth];
        currentRatio += tileHeight / hiddenContentSize;
        physicalBottom -= tileHeight;
        recycledTileSet.add(kth);
        recycledTiles++;
        kth = (kth == 0) ? _physicalCount - 1 : kth - 1;
      }

      movingUp = recycledTileSet;
      recycledTiles = -recycledTiles;
    }
    // scroll down
    else if (delta > 0) {
      int bottomSpace = physicalBottom - scrollBottom;
      int virtualEnd = _virtualEnd;
      int lastVirtualItemIndex = _virtualCount - 1;

      recycledTileSet = [];

      kth = _physicalStart;
      currentRatio = bottomSpace / hiddenContentSize;

      // move tiles from top to bottom
      while (
          // approximate `currentRatio` to `ratio`
          currentRatio < ratio &&
              // recycle less physical items than the total
              recycledTiles < _physicalCount &&
              // ensure that these recycled tiles are needed
              virtualEnd + recycledTiles < lastVirtualItemIndex &&
              // ensure that the tile is not visible
              _physicalTop + _physicalSizes[kth] < scrollTop) {
        tileHeight = _physicalSizes[kth];
        currentRatio += tileHeight / hiddenContentSize;

        _physicalTop += tileHeight;
        recycledTileSet.add(kth);
        recycledTiles++;
        kth = (kth + 1) % _physicalCount;
      }
    }

    if (recycledTiles == 0) {
      // If the list ever reach this case, the physical average is not significant enough
      // to create all the items needed to cover the entire viewport.
      // e.g. A few items have a height that differs from the average by serveral order of magnitude.
      if (physicalBottom < scrollBottom || _physicalTop > scrollTop) {
        new Future.delayed(const Duration(milliseconds: 1), _increasePool);
      }
    } else {
      _virtualStart = _virtualStart + recycledTiles;
      _update(recycledTileSet, movingUp);
    }
  }

  /// Update the list of items, starting from the `_virtualStartVal` item.
  /// @param {!Array<number>=} itemSet
  /// @param {!Array<number>=} movingUp

  void _update(List<int> itemSet, List<int> movingUp) {
    // update models
    _assignModels(itemSet);

    // measure heights
    _updateMetrics(itemSet);

    // adjust offset after measuring
    if (movingUp != null && movingUp.isNotEmpty) {
      while (movingUp.length > 0) {
        _physicalTop -= _physicalSizes[movingUp.removeLast()];
      }
    }
    // update the position of the items
    _positionItems();

    // set the scroller size
    _updateScrollerSize();

    // increase the pool of physical items
    _increasePoolIfNeeded();
  }

  /// Creates a pool of DOM elements and attaches them to the local dom.

  _createPool(int size) {
    var physicalItems = new List(size);

    _ensureTemplatized();

    for (var i = 0; i < size; i++) {
      var inst = stamp(null);
      // First element child is item; Safari doesn't support children[0]
      // on a doc fragment
      physicalItems[i] = inst.root.querySelector('*');
      Polymer.dom(this).appendChild(inst.root);
    }

    return physicalItems;
  }

  /// Increases the pool of physical items only if needed.
  /// This function will allocate additional physical items
  /// if the physical size is shorter than `_optPhysicalSize`

  void _increasePoolIfNeeded() {
    if (_viewportSize != 0 && _physicalSize < _optPhysicalSize) {
      // 0 <= `currentPage` <= `_maxPages`
      var currentPage = (_physicalSize / _viewportSize).floor();

      if (currentPage == 0) {
        // fill the first page
        new Future.delayed(
            new Duration(milliseconds: (_physicalCount * 0.5).round()),
            _increasePool);
      } else if (_lastPage != currentPage) {
        // once a page is filled up, paint it and defer the next increase
        window.requestAnimationFrame(() => _increasePool(1));
      } else {
        // fill the rest of the pages
        async(_increasePool.bind(this, 1));
      }
      _lastPage = currentPage;
      return true;
    }
    return false;
  }

  /// Increases the pool size.

  _increasePool(missingItems) {
    // limit the size
    var nextPhysicalCount =
        min(_physicalCount + missingItems, _virtualCount, MAX_PHYSICAL_COUNT);
    var prevPhysicalCount = _physicalCount;
    var delta = nextPhysicalCount - prevPhysicalCount;

    if (delta > 0) {
      [].push.apply(_physicalItems, _createPool(delta));
      [].push.apply(_physicalSizes, new List(delta));

      _physicalCount = prevPhysicalCount + delta;
      // tail call
      return _update();
    }
  }

  /// Render a new list of items. This method does exactly the same as `update`,
  /// but it also ensures that only one `update` cycle is created.

  _render() {
    var requiresUpdate = _virtualCount > 0 || _physicalCount > 0;

    if (isAttached && !_itemsRendered && _isVisible && requiresUpdate) {
      _lastPage = 0;
      _update();
      _itemsRendered = true;
    }
  }

  /// Templetizes the user template.

  _ensureTemplatized() {
    if (!ctor) {
      // Template instance props that should be excluded from forwarding
      var props = {};

      props.__key__ = true;
      props[as] = true;
      props[indexAs] = true;
      props[selectedAs] = true;

      _instanceProps = props;
      _userTemplate = Polymer.dom(this).querySelector('template');

      if (_userTemplate) {
        templatize(_userTemplate);
      } else {
        console
            .warn('iron-list requires a template to be provided in light-dom');
      }
    }
  }

  /// Implements extension point from Templatizer mixin.

  _getStampedChildren() {
    return _physicalItems;
  }

  /// Implements extension point from Templatizer
  /// Called as a side effect of a template instance path change, responsible
  /// for notifying items.<key-for-instance>.<path> change up to host.

  _forwardInstancePath(inst, path, value) {
    if (path.indexOf(as + '.') == 0) {
      notifyPath(
          'items.' + inst.__key__ + '.' + path.slice(as.length + 1), value);
    }
  }

  /// Implements extension point from Templatizer mixin
  /// Called as side-effect of a host property change, responsible for
  /// notifying parent path change on each row.

  _forwardParentProp(prop, value) {
    if (_physicalItems) {
      _physicalItems.forEach((item) {
        item._templateInstance[prop] = value;
      }, this);
    }
  }

  /// Implements extension point from Templatizer
  /// Called as side-effect of a host path change, responsible for
  /// notifying parent.<path> path change on each row.

  _forwardParentPath(path, value) {
    if (_physicalItems) {
      _physicalItems.forEach((item) {
        item._templateInstance.notifyPath(path, value, true);
      }, this);
    }
  }

  /// Called as a side effect of a host items.<key>.<path> path change,
  /// responsible for notifying item.<path> changes to row for key.

  _forwardItemPath(path, value) {
    if (_physicalIndexForKey) {
      var dot = path.indexOf('.');
      var key = path.substring(0, dot < 0 ? path.length : dot);
      var idx = _physicalIndexForKey[key];
      var row = _physicalItems[idx];
      if (row) {
        var inst = row._templateInstance;
        if (dot >= 0) {
          path = as + '.' + path.substring(dot + 1);
          inst.notifyPath(path, value, true);
        } else {
          inst[as] = value;
        }
      }
    }
  }

  /// Called when the items have changed. That is, ressignments
  /// to `items`, splices or updates to a single item.

  _itemsChanged(change) {
    if (change.path == 'items') {
      // render the new set
      _itemsRendered = false;

      // update the whole set
      _virtualStartVal = 0;
      _physicalTop = 0;
      _virtualCount = items ? items.length : 0;
      _collection = items ? Polymer.Collection.get(items) : null;
      _physicalIndexForKey = <dynamic, int>{};

      // scroll to the top
      _resetScrollPosition(0);

      // create the initial physical items
      if (!_physicalItems) {
        _physicalCount =
            Math.max(1, Math.min(DEFAULT_PHYSICAL_COUNT, _virtualCount));
        _physicalItems = _createPool(_physicalCount);
        _physicalSizes = new List(_physicalCount);
      }

      debounce('refresh', _render);
    } else if (change.path == 'items.splices') {
      // render the new set
      _itemsRendered = false;

      _adjustVirtualIndex(change.value.indexSplices);
      _virtualCount = items ? items.length : 0;

      debounce('refresh', _render);
    } else {
      // update a single item
      _forwardItemPath(change.path.split('.').slice(1).join('.'), change.value);
    }
  }

  /// @param {!Array<!PolymerSplice>} splices

  _adjustVirtualIndex(splices) {
    var i, splice, idx;

    for (i = 0; i < splices.length; i++) {
      splice = splices[i];

      // deselect removed items
      splice.removed.forEach($.selector.deselect, $.selector);

      idx = splice.index;
      // We only need to care about changes happening above the current position
      if (idx >= _virtualStartVal) {
        break;
      }

      _virtualStart = _virtualStart +
          Math.max(splice.addedCount - splice.removed.length,
              idx - _virtualStartVal);
    }
  }

  _scrollHandler() {
    _refresh();
  }

  /// Executes a provided function per every physical index in `itemSet`
  /// `itemSet` default value is equivalent to the entire set of physical indexes.
  ///
  /// @param {!function(number, number)} fn
  /// @param {!Array<number>=} itemSet

  _iterateItems(Function fn, List<int> itemSet) {
    var pidx, vidx, rtn, i;

    if (arguments.length == 2 && itemSet) {
      for (i = 0; i < itemSet.length; i++) {
        pidx = itemSet[i];
        if (pidx >= _physicalStart) {
          vidx = _virtualStartVal + (pidx - _physicalStart);
        } else {
          vidx = _virtualStartVal + (_physicalCount - _physicalStart) + pidx;
        }
        if ((rtn = fn.call(this, pidx, vidx)) != null) {
          return rtn;
        }
      }
    } else {
      pidx = _physicalStart;
      vidx = _virtualStartVal;

      for (; pidx < _physicalCount; pidx++, vidx++) {
        if ((rtn = fn.call(this, pidx, vidx)) != null) {
          return rtn;
        }
      }

      pidx = 0;

      for (; pidx < _physicalStart; pidx++, vidx++) {
        if ((rtn = fn.call(this, pidx, vidx)) != null) {
          return rtn;
        }
      }
    }
  }

  /// Assigns the data models to a given set of items.
  /// @param {!Array<number>=} itemSet

  _assignModels(itemSet) {
    _iterateItems((pidx, vidx) {
      var el = _physicalItems[pidx];
      var inst = el._templateInstance;
      var item = items && items[vidx];

      if (item) {
        inst[as] = item;
        inst.__key__ = _collection.getKey(item);
        inst[selectedAs] =
            /* @type {!ArraySelectorElement} */ ($.selector).isSelected(item);
        inst[indexAs] = vidx;
        el.removeAttribute('hidden');
        _physicalIndexForKey[inst.__key__] = pidx;
      } else {
        inst.__key__ = null;
        el.setAttribute('hidden', '');
      }
    }, itemSet);
  }

  /// Updates the height for a given set of items.
  ///
  /// @param {!Array<number>=} itemSet

  _updateMetrics(itemSet) {
    var newPhysicalSize = 0;
    var oldPhysicalSize = 0;
    var prevAvgCount = _physicalAverageCount;
    var prevPhysicalAvg = _physicalAverage;
    // Make sure we distributed all the physical items
    // so we can measure them
    Polymer.dom.flush();

    _iterateItems((pidx, vidx) {
      oldPhysicalSize += _physicalSizes[pidx] || 0;
      _physicalSizes[pidx] = _physicalItems[pidx].offsetHeight;
      newPhysicalSize += _physicalSizes[pidx];
      _physicalAverageCount += _physicalSizes[pidx] ? 1 : 0;
    }, itemSet);

    _physicalSize = _physicalSize + newPhysicalSize - oldPhysicalSize;
    _viewportSize = _scroller.offsetHeight;

    // update the average if we measured something
    if (_physicalAverageCount != prevAvgCount) {
      _physicalAverage = Math.round(
          ((prevPhysicalAvg * prevAvgCount) + newPhysicalSize) /
              _physicalAverageCount);
    }
  }

  /// Updates the position of the physical items.

  _positionItems() {
    _adjustScrollPosition();

    var y = _physicalTop;

    _iterateItems((pidx) {
      transform('translate3d(0, ' + y + 'px, 0)', _physicalItems[pidx]);
      y += _physicalSizes[pidx];
    });
  }

  /// Adjusts the scroll position when it was overestimated.

  _adjustScrollPosition() {
    var deltaHeight = _virtualStartVal == 0
        ? _physicalTop
        : Math.min(_scrollPosition + _physicalTop, 0);

    if (deltaHeight) {
      _physicalTop = _physicalTop - deltaHeight;

      // juking scroll position during interial scrolling on iOS is no bueno
      if (!IOS_TOUCH_SCROLLING) {
        _resetScrollPosition(_scroller.scrollTop - deltaHeight);
      }
    }
  }

  /// Sets the position of the scroll.

  _resetScrollPosition(pos) {
    if (_scroller) {
      _scroller.scrollTop = pos;
      _scrollPosition = _scroller.scrollTop;
    }
  }

  /// Sets the scroll height, that's the height of the content,
  ///
  /// @param {boolean=} forceUpdate If true, updates the height no matter what.

  _updateScrollerSize([bool forceUpdate = false]) {
    _estScrollHeight = (_physicalBottom +
        Math.max(_virtualCount - _physicalCount - _virtualStartVal, 0) *
            _physicalAverage);

    forceUpdate = forceUpdate || _scrollHeight == 0;
    forceUpdate =
        forceUpdate || _scrollPosition >= _estScrollHeight - _physicalSize;

    // amortize height adjustment, so it won't trigger repaints very often
    if (forceUpdate ||
        Math.abs(_estScrollHeight - _scrollHeight) >= _optPhysicalSize) {
      $.items.style.height = _estScrollHeight + 'px';
      _scrollHeight = _estScrollHeight;
    }
  }

  /// Scroll to a specific item in the virtual list regardless
  /// of the physical items in the DOM tree.
  ///
  /// @method scrollToIndex
  /// @param {number} idx The index of the item

  scrollToIndex(idx) {
    if (idx is! num) {
      return;
    }

    var firstVisible = firstVisibleIndex;

    idx = Math.min(Math.max(idx, 0), _virtualCount - 1);

    // start at the previous virtual item
    // so we have a item above the first visible item
    _virtualStart = idx - 1;

    // assign new models
    _assignModels();

    // measure the new sizes
    _updateMetrics();

    // estimate new physical offset
    _physicalTop = _virtualStart * _physicalAverage;

    var currentTopItem = _physicalStart;
    var currentVirtualItem = _virtualStart;
    var targetOffsetTop = 0;
    var hiddenContentSize = _hiddenContentSize;

    // scroll to the item as much as we can
    while (currentVirtualItem < idx && targetOffsetTop < hiddenContentSize) {
      targetOffsetTop = targetOffsetTop + _physicalSizes[currentTopItem];
      currentTopItem = (currentTopItem + 1) % _physicalCount;
      currentVirtualItem++;
    }

    // update the scroller size
    _updateScrollerSize(true);

    // update the position of the items
    _positionItems();

    // set the new scroll position
    _resetScrollPosition(_physicalTop + targetOffsetTop + 1);

    // increase the pool of physical items if needed
    _increasePoolIfNeeded();

    // clear cached visible index
    _firstVisibleIndexVal = null;
    _lastVisibleIndexVal = null;
  }

  /// Reset the physical average and the average count.

  _resetAverage() {
    _physicalAverage = 0;
    _physicalAverageCount = 0;
  }

  /// A handler for the `iron-resize` event triggered by `IronResizableBehavior`
  /// when the element is resized.

  _resizeHandler() {
    debounce('resize', () {
      _render();
      if (_itemsRendered && _physicalItems && _isVisible) {
        _resetAverage();
        updateViewportBoundaries();
        scrollToIndex(firstVisibleIndex);
      }
    });
  }

  _getModelFromItem(item) {
    var key = _collection.getKey(item);
    var pidx = _physicalIndexForKey[key];

    if (pidx != null) {
      return _physicalItems[pidx]._templateInstance;
    }
    return null;
  }

  /// Gets a valid item instance from its index or the object value.
  ///
  /// @param {(Object|number)} item The item object or its index

  _getNormalizedItem(item) {
    if (item is num) {
      item = items[item];
      if (!item) {
        throw new RangeError('<item> not found');
      }
    } else if (_collection.getKey(item) == undefined) {
      throw new TypeError('<item> should be a valid item');
    }
    return item;
  }

  /// Select the list item at the given index.
  ///
  /// @method selectItem
  /// @param {(Object|number)} item The item object or its index

  selectItem(item) {
    item = _getNormalizedItem(item);
    var model = _getModelFromItem(item);

    if (!multiSelection && selectedItem) {
      deselectItem(selectedItem);
    }
    if (model) {
      model[selectedAs] = true;
    }
    $.selector.select(item);
  }

  /// Deselects the given item list if it is already selected.
  ///

  /// @method deselect
  /// @param {(Object|number)} item The item object or its index

  deselectItem(item) {
    item = _getNormalizedItem(item);
    var model = _getModelFromItem(item);

    if (model) {
      model[selectedAs] = false;
    }
    $.selector.deselect(item);
  }

  /// Select or deselect a given item depending on whether the item
  /// has already been selected.
  ///
  /// @method toggleSelectionForItem
  /// @param {(Object|number)} item The item object or its index

  toggleSelectionForItem(item) {
    item = _getNormalizedItem(item);
    if (/*@type {!ArraySelectorElement} */ ($.selector).isSelected(item)) {
      deselectItem(item);
    } else {
      selectItem(item);
    }
  }

  /// Clears the current selection state of the list.
  ///
  /// @method clearSelection

  clearSelection() {
    unselect(item) {
      var model = _getModelFromItem(item);
      if (model) {
        model[selectedAs] = false;
      }
    }

    if (Array.isArray(selectedItems)) {
      selectedItems.forEach(unselect, this);
    } else if (selectedItem) {
      unselect.call(this, selectedItem);
    }

    /*@type {!ArraySelectorElement} */ ($.selector).clearSelection();
  }

  /// Add an event listener to `tap` if `selectionEnabled` is true,
  /// it will remove the listener otherwise.

  _selectionEnabledChanged(selectionEnabled) {
    if (selectionEnabled) {
      listen(this, 'tap', '_selectionHandler');
      listen(this, 'keypress', '_selectionHandler');
    } else {
      unlisten(this, 'tap', '_selectionHandler');
      unlisten(this, 'keypress', '_selectionHandler');
    }
  }

  /// Select an item from an event object.

  _selectionHandler(e) {
    if (e.type != 'keypress' || e.keyCode == 13) {
      var model = modelForElement(e.target);
      if (model) {
        toggleSelectionForItem(model[as]);
      }
    }
  }

  _multiSelectionChanged(multiSelection) {
    clearSelection();
    $.selector.multi = multiSelection;
  }

  /// Updates the size of an item.
  ///
  /// @method updateSizeForItem
  /// @param {(Object|number)} item The item object or its index

  updateSizeForItem(item) {
    item = _getNormalizedItem(item);
    var key = _collection.getKey(item);
    var pidx = _physicalIndexForKey[key];

    if (pidx != undefined) {
      _updateMetrics([pidx]);
      _positionItems();
    }
  }
}
@zoechi
Copy link
Contributor Author

zoechi commented Jan 7, 2016

This worked wile I tried to port the JS code to Dart yesterday.
I updated Dart from

Dart VM version: 1.14.0-edge.41b0e45f73083e5558d171204a0d90f017fe6763 (Wed Jan 6 05:05:40 2016) on "linux_x64"

to

Dart VM version: 1.14.0-edge.a7ebeb00fbb09b774836239b31d2c7defcc12c9c (Wed Jan 6 17:25:11 2016) on "linux_x64"

@zoechi
Copy link
Contributor Author

zoechi commented Jan 7, 2016

Reverting to

Dart VM version: 1.14.0-edge.41b0e45f73083e5558d171204a0d90f017fe6763 (Wed Jan 6 05:05:40 2016) on "linux_x64"

fixes the issue

@bwilkerson bwilkerson added Type-Defect P1 A high priority bug; for example, a single project is unusable or has many test failures area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. analyzer-completion Issues with the analysis server's code completion feature labels Jan 7, 2016
@bwilkerson bwilkerson assigned danrubel and scheglov and unassigned danrubel Jan 7, 2016
@zoechi
Copy link
Contributor Author

zoechi commented Mar 1, 2016

Can't reproduce.

@zoechi zoechi closed this as completed Mar 1, 2016
@kevmoo kevmoo added type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) and removed Type-Defect labels Mar 1, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
analyzer-completion Issues with the analysis server's code completion feature analyzer-stability area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P1 A high priority bug; for example, a single project is unusable or has many test failures type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

5 participants