[
  {
    "path": ".babelrc",
    "content": "{\n  \"presets\": [\n    [\"env\", { \"targets\": { \"node\": \"current\" } }]\n  ],\n  \"sourceMap\": \"inline\",\n  \"plugins\": [\n    \"transform-class-properties\",\n    \"transform-object-rest-spread\",\n    \"transform-flow-strip-types\"\n  ]\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = space\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.md]\ntrim_trailing_whitespace = false"
  },
  {
    "path": ".eslintignore",
    "content": "decls\n"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"extends\": \"steelbrain\",\n  \"plugins\": [\n    \"flowtype\"\n  ],\n  \"rules\": {\n    \"import/prefer-default-export\": \"off\",\n    \"no-duplicate-imports\": \"off\",\n    \"flowtype/define-flow-type\": \"error\",\n    \"flowtype/use-flow-type\": \"error\"\n  },\n  \"globals\": {\n    \"waitsForPromise\": true\n  }\n}\n"
  },
  {
    "path": ".flowconfig",
    "content": "[ignore]\n\n[include]\n\n[libs]\ndecls\n\n[options]\nmodule.system=node\ninclude_warnings=true\nsuppress_comment= \\\\(.\\\\|\\n\\\\)*\\\\$FlowIgnore\n\n[lints]\nall=warn\n\n# turned off because there are lot of types missing atm...\nunclear-type=off\nuntyped-import=off\n"
  },
  {
    "path": ".gitignore",
    "content": ".idea\nnode_modules\n*.log\n.DS_Store\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "#### 1.13.0\n\n- Use the official [language server protocol](https://microsoft.github.io/language-server-protocol/) to communicate with `flow`\n\n#### 1.12.1\n\n- Support for Tree-Sitter Flow grammar\n\n#### 1.12.0\n\n- Add config to stop flow server when flow-ide is stopped\n- Fix autocomplete selector\n\n#### 1.11.1\n\n- Support for Tree-Sitter Flow grammar\n\n#### 1.11.0\n\n- Support new errors messages since [flow 0.66.0](https://github.com/facebook/flow/releases/tag/v0.66.0)\n- Fix goto definition (via hyperclick) if the cursor is at the end of the word\n- Fix outline for rest/spread operators\n\n#### 1.10.0\n\n- [Outline](https://github.com/facebook-atom/atom-ide-ui/blob/2767934/docs/outline-view.md) of classes, functions, types and variables (using [atom-ide-ui](https://github.com/facebook-atom/atom-ide-ui/))\n- Minor bug fixes regarding markdown rendering of flow errors\n\n#### 1.9.0\n\n- Support [datatip](https://github.com/facebook-atom/atom-ide-ui/blob/508ecfd6aa8121ae2e423b2becbe22e34cf191fb/docs/datatips.md) from [atom-ide-ui](https://github.com/facebook-atom/atom-ide-ui/)\n- Fix wrong coverage (#112)\n- Fix minor markdown rendering issue\n\n#### 1.8.1\n\n- Hide coverage view instead of emptying to fix extra padding\n\n#### 1.8.0\n\n- Add linting in flow support\n- Show a restart notification after `hyperclickPriority` is updated\n\n#### 1.7.0\n\n- Change search order of `flow` executable (_Executable Path_ setting > `node_modules/.bin/flow` > global `flow`)\n\n#### 1.6.0\n\n- Add \"jump to definition\" via `hyperclick`\n- Show the complete flow error message as error description\n\n#### 1.5.0\n\n- Add option to show uncovered code\n- Fix process exited with non-zero status code for autocomplete\n- Fix invalid behavior of `onlyIfAppropriate` config\n\n#### 1.4.2\n\n- Limit concurrent spawned processes\n\n#### 1.4.1\n\n- Increase exec timeout to 60 seconds\n\n#### 1.4.0\n\n- Upgrade for linter v2 support\n\n#### 1.3.0\n\n- Terminate flow servers on deactivate\n- Fix path.dirname deprecation by ignoring autocomplete requests on files not yet saved\n\n#### 1.2.4\n\n- Had to bump version because of some issues in deployment (network)\n\n#### 1.2.2\n\n- Handle coverage count zero (#52)\n\n#### 1.2.1\n\n- Fix flow type checking (#49)\n\n#### 1.2\n\n- Add Flow coverage view\n\n#### 1.1.10\n- Provide a default .flowconfig file if onlyIfAppropriate is enabled and a .flowconfig file is not found already\n\n#### 1.1.9\n\n- Fix autocompletion for properties (#33)\n- Remove types from function params (#8)\n\n#### 1.1.8\n\n- APM was having hiccups back then so didn't publish properly\n\n#### 1.1.7\n\n- Fix a bug in last release\n\n#### 1.1.6\n\n- Workaround a Atom's builtin babel bug\n\n#### 1.1.5\n\n- Just another patch to catch more flow errors gracefully\n\n#### 1.1.4\n\n- Handle flow crashes/respawns gracefully\n\n#### 1.1.3\n\n- Show entire linter error message\n\n#### 1.1.1-1.1.2\n\n- Fix a bug introduced in 1.1.0 where autocomplete wouldn't work\n- Fix a reference to undefined variable in case of error ( Fixes #12 )\n\n#### 1.1.0\n\n- Add support for locally installed flow bins\n- Bump `atom-linter` to v5\n\n#### 1.0.6\n\n- Show a correct type for Objects in autocomplete\n- Only run autocomplete at appropriate times ( Fixes #3 )\n\n#### 1.0.5\n\n- Fix a bug in retrying for server\n- Fix a bug where deep nested objects would mess up autocomplete\n\n#### 1.0.4\n\n- Bump `atom-package-deps` version\n\n#### 1.0.3\n\n- Bump `atom-linter` dependency to include fix for projects that don't have a `.flowcofig`\n\n#### 1.0.2\n\n- Improve handling of fatal errors\n\n#### 1.0.1\n\n- Implement smart sorting and filtering of autocomplete suggestions\n- Make linter messages more user friendly\n\n#### 1.0.0\n\n- Linting support added\n- Autocomplete support added\n"
  },
  {
    "path": "LICENSE.md",
    "content": "Copyright (c) 2016 steelbrain\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "Flow-IDE\n=======\n\nFlow IDE is a lightweight package that provides IDE features for [FlowType][FlowType] for [Atom Editor][Atom]. It's pretty lightweight and robust.\n\n#### Installation\n```\napm install flow-ide\n```\n\n#### Setup\n 1) You will need to install flow-bin into your project!\n```\nnpm install --save-dev flow-bin\n```\nor\n```\nyarn add --dev flow-bin\n```\n\n 2) You will need ` // @flow ` at the top of all files you wish to lint\n\n\n3) You will need a `.flowconfig` which can be initialized with `flow init` if you have flow installed, if not you can use [this flowconfig](https://github.com/steelbrain/flow-ide/blob/master/.flowconfig)\n\n4) Window: Reload (Ctrl+Shift+F5) to apply changes\n\n\n#### Features\n\n - Linting\n - Autocomplete\n - Jump to declaration (using [facebook-atom/hyperclick][hyperclick] or [facebook-atom/atom-ide-ui][atom-ide-ui])\n - Datatip on hover (using [facebook-atom/atom-ide-ui][atom-ide-ui])\n - Outline of classes, functions, types and variables (using [facebook-atom/atom-ide-ui][atom-ide-ui])\n\n#### Differences to other packages\n\nDifferences to [facebook/nuclide][nuclide]\n - Nuclide is nice and all but it's mostly bloatware for lightweight flow programming\n\nDifferences to [AtomLinter/linter-flow][linter-flow]\n - It tries to manage flow servers by itself, I find it annoying\n\nDifferences to [nmn/autocomplete-flow][autocomplete-flow]\n - Never worked for me\n\nDifferences to [LukeHoban/ide-flow][ide-flow]\n - Outdated and buggy\n - No longer maintained\n\n#### Screenshots\n\n![Autocomplete](https://cloud.githubusercontent.com/assets/4278113/12857027/bb8e2c80-cc69-11e5-918d-4451d0679e66.png)\n\n\n#### License\n\nThis project is licensed under the terms of MIT License. Check the LICENSE file for more info.\n\n[FlowType]:http://flowtype.org/\n[Atom]:https://atom.io/\n[nuclide]:https://github.com/facebook/nuclide\n[hyperclick]:https://github.com/facebook-atom/hyperclick\n[atom-ide-ui]:https://github.com/facebook-atom/atom-ide-ui\n[ide-flow]:https://github.com/lukehoban/atom-ide-flow\n[linter-flow]:https://github.com/AtomLinter/linter-flow\n[autocomplete-flow]:https://github.com/nmn/autocomplete-flow\n"
  },
  {
    "path": "decls/atom.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the license found in the LICENSE file in\n * the root directory of this source tree.\n *\n * @flow\n */\n\n/**\n * Private Classes\n */\n\ntype IDisposable = { dispose(): void }\n\n// Octicons v4.4.0. List extracted from the atom-styleguide package.\ntype atom$Octicon = 'alert' | 'alignment-align' | 'alignment-aligned-to' | 'alignment-unalign' |\n  'arrow-down' | 'arrow-left' | 'arrow-right' | 'arrow-small-down' | 'arrow-small-left' |\n  'arrow-small-right' | 'arrow-small-up' | 'arrow-up' | 'beaker' | 'beer' | 'bell' | 'bold' |\n  'book' | 'bookmark' | 'briefcase' | 'broadcast' | 'browser' | 'bug' | 'calendar' | 'check' |\n  'checklist' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'circle-slash' |\n  'circuit-board' | 'clippy' | 'clock' | 'cloud-download' | 'cloud-upload' | 'code' | 'color-mode' |\n  'comment' | 'comment-add' | 'comment-discussion' | 'credit-card' | 'dash' | 'dashboard' |\n  'database' | 'desktop-download' | 'device-camera' | 'device-camera-video' | 'device-desktop' |\n  'device-mobile' | 'diff' | 'diff-added' | 'diff-ignored' | 'diff-modified' | 'diff-removed' |\n  'diff-renamed' | 'ellipses' | 'ellipsis' | 'eye' | 'eye-unwatch' | 'eye-watch' | 'file' |\n  'file-add' | 'file-binary' | 'file-code' | 'file-directory' | 'file-directory-create' |\n  'file-media' | 'file-pdf' | 'file-submodule' | 'file-symlink-directory' | 'file-symlink-file' |\n  'file-text' | 'file-zip' | 'flame' | 'fold' | 'gear' | 'gift' | 'gist' | 'gist-fork' |\n  'gist-new' | 'gist-private' | 'gist-secret' | 'git-branch' | 'git-branch-create' |\n  'git-branch-delete' | 'git-commit' | 'git-compare' | 'git-fork-private' | 'git-merge' |\n  'git-pull-request' | 'git-pull-request-abandoned' | 'globe' | 'grabber' | 'graph' | 'heart' |\n  'history' | 'home' | 'horizontal-rule' | 'hourglass' | 'hubot' | 'inbox' | 'info' |\n  'issue-closed' | 'issue-opened' | 'issue-reopened' | 'italic' | 'jersey' | 'jump-down' |\n  'jump-left' | 'jump-right' | 'jump-up' | 'key' | 'keyboard' | 'law' | 'light-bulb' | 'link' |\n  'link-external' | 'list-ordered' | 'list-unordered' | 'location' | 'lock' | 'log-in' | 'log-out' |\n  'logo-gist' | 'logo-github' | 'mail' | 'mail-read' | 'mail-reply' | 'mark-github' | 'markdown' |\n  'megaphone' | 'mention' | 'microscope' | 'milestone' | 'mirror' | 'mirror-private' |\n  'mirror-public' | 'mortar-board' | 'move-down' | 'move-left' | 'move-right' | 'move-up' | 'mute' |\n  'no-newline' | 'octoface' | 'organization' | 'package' | 'paintcan' | 'pencil' | 'person' |\n  'person-add' | 'person-follow' | 'pin' | 'playback-fast-forward' | 'playback-pause' |\n  'playback-play' | 'playback-rewind' | 'plug' | 'plus-small' | 'plus' | 'podium' |\n  'primitive-dot' | 'primitive-square' | 'pulse' | 'puzzle' | 'question' | 'quote' | 'radio-tower' |\n  'remove-close' | 'reply' | 'repo' | 'repo-clone' | 'repo-create' | 'repo-delete' |\n  'repo-force-push' | 'repo-forked' | 'repo-pull' | 'repo-push' | 'repo-sync' | 'rocket' | 'rss' |\n  'ruby' | 'screen-full' | 'screen-normal' | 'search' | 'search-save' | 'server' | 'settings' |\n  'shield' | 'sign-in' | 'sign-out' | 'smiley' | 'split' | 'squirrel' | 'star' | 'star-add' |\n  'star-delete' | 'steps' | 'stop' | 'sync' | 'tag' | 'tag-add' | 'tag-remove' | 'tasklist' |\n  'telescope' | 'terminal' | 'text-size' | 'three-bars' | 'thumbsdown' | 'thumbsup' | 'tools' |\n  'trashcan' | 'triangle-down' | 'triangle-left' | 'triangle-right' | 'triangle-up' | 'type-array'|\n  'type-boolean'| 'type-class'| 'type-constant'| 'type-constructor'| 'type-enum'| 'type-field'|\n  'type-file'| 'type-function'| 'type-interface'| 'type-method'| 'type-module'| 'type-namespace'|\n  'type-number'| 'type-package'| 'type-property'| 'type-string'| 'type-variable' | 'unfold' |\n  'unmute' | 'unverified' | 'verified' | 'versions' | 'watch' | 'x' | 'zap';\n\ntype atom$PaneLocation = 'left' | 'right' | 'bottom' | 'center';\n\ndeclare type atom$Color  = {\n  // Returns a String in the form '#abcdef'.\n  toHexString(): string;\n  // Returns a String in the form 'rgba(25, 50, 75, .9)'.\n  toRGBAString(): string;\n}\n\ndeclare class atom$Model {\n  destroy(): void,\n  isDestroyed(): boolean,\n}\n\ndeclare class atom$Package {\n  path: string,\n  activateTime: number,\n  mainModule: any,\n  mainModulePath: string,\n  metadata: Object,\n  name: string,\n  loadTime: number,\n  getType(): 'atom' | 'textmate' | 'theme',\n  hasActivationCommands(): boolean,\n  hasActivationHooks(): boolean,\n  initializeTime: number,\n  getActivationHooks(): Array<string>,\n  onDidDeactivate(cb: () => mixed): IDisposable,\n  activateNow(): void,\n  // Undocumented\n  bundledPackage: boolean,\n  getCanDeferMainModuleRequireStorageKey(): string,\n  initializeIfNeeded(): void,\n}\n\n/**\n * Essential Classes\n */\n\ndeclare type atom$CustomEvent  = CustomEvent & {\n  originalEvent?: Event;\n}\n\ntype atom$CommandCallback = (event: atom$CustomEvent) => mixed;\n\ntype atom$CommandDescriptor = {\n  name: string,\n  displayName: string,\n  description?: string,\n  hiddenInCommandPalette?: boolean,\n  tags?: Array<string>,\n};\n\ntype atom$CommandListener = atom$CommandCallback | {\n  displayName?: string,\n  description?: string,\n  didDispatch: atom$CommandCallback,\n};\n\ndeclare class atom$CommandRegistry {\n  // Methods\n  add(\n    target: string | HTMLElement,\n    commandNameOrCommands: string | {[commandName: string]: atom$CommandListener},\n    listener?: atom$CommandListener,\n    throwOnInvalidSelector?: boolean,\n  ): IDisposable,\n  dispatch(target: HTMLElement, commandName: string, detail?: Object): void,\n  onDidDispatch(callback: (event: atom$CustomEvent) => mixed): IDisposable,\n  onWillDispatch(callback: (event: atom$CustomEvent) => mixed): IDisposable,\n  findCommands(opts: {target: Node}): Array<atom$CommandDescriptor>,\n}\n\ndeclare class atom$CompositeDisposable {\n  constructor(...disposables: Array<IDisposable>): void,\n  dispose(): void,\n\n  add(...disposables: Array<IDisposable>): void,\n  remove(disposable: IDisposable): void,\n  clear(): void,\n}\n\ntype atom$ConfigParams = {\n  saveCallback?: Object => void,\n  mainSource?: string,\n  projectHomeSchema?: atom$ConfigSchema,\n};\n\ntype atom$ConfigType =\n  'boolean' | 'string' | 'integer' | 'number' |\n  'array' | 'object' | 'color' | 'any';\n\ntype atom$ConfigSchema = {\n  default?: mixed,\n  description?: string,\n  enum?: Array<string | {value: string, description: string}>,\n  maximum?: number,\n  minimum?: number,\n  properties?: Object,\n  title?: string,\n  type: Array<atom$ConfigType> | atom$ConfigType,\n};\n\ndeclare class atom$Config {\n  defaultSettings: Object,\n  settings: Object,\n\n  // Config Subscription\n  observe(\n    keyPath: string,\n    optionsOrCallback?:\n      | {scope?: atom$ScopeDescriptorLike}\n      | (value: mixed) => void,\n    callback?: (value: mixed) => mixed,\n  ): IDisposable,\n\n  onDidChange(\n    keyPathOrCallback:\n      | string\n      | (event: {oldValue: mixed, newValue: mixed}) => mixed,\n    optionsOrCallback?:\n      | {scope?: atom$ScopeDescriptorLike}\n      | (event: {oldValue: mixed, newValue: mixed}) => mixed,\n    callback?: (event: {oldValue: mixed, newValue: mixed}) => mixed\n  ): IDisposable,\n\n  // Managing Settings\n  get(\n    keyPath?: string,\n    options?: {\n      excludeSources?: Array<string>,\n      sources?: Array<string>,\n      scope?: atom$ScopeDescriptorLike,\n    }\n  ): mixed,\n\n  set(\n    keyPath: string,\n    value: ?mixed,\n    options?: {\n      scopeSelector?: string,\n      source?: string,\n    },\n  ): boolean,\n\n  unset(\n    keyPath: string,\n    options?: {\n      scopeSelector?: string,\n      source?: string,\n    }\n  ): void,\n\n  getUserConfigPath(): string,\n\n  // Undocumented Methods\n  constructor(params?: atom$ConfigParams): atom$Config,\n  getRawValue(keyPath: ?string, options: {excludeSources?: string, sources?: string}): mixed,\n  getSchema(keyPath: string): atom$ConfigSchema,\n  save(): void,\n  setRawValue(keyPath: string, value: mixed): void,\n  setSchema(\n    keyPath: string,\n    schema: atom$ConfigSchema,\n  ): void,\n  removeAtKeyPath(keyPath: ?string, value: ?mixed): mixed,\n\n  // Used by nuclide-config to set the initial settings from disk\n  resetUserSettings(newSettings: Object, options?: {source?: string}): void,\n}\n\ndeclare class atom$Cursor {\n  // Cursor Marker\n  marker: atom$Marker;\n  editor: atom$TextEditor;\n\n  // Event Subscription\n  onDidChangePosition(\n    callback: (event: {\n      oldBufferPosition: atom$Point,\n      oldScreenPosition: atom$Point,\n      newBufferPosition: atom$Point,\n      newScreenPosition: atom$Point,\n      textChanged: boolean,\n      Cursor: atom$Cursor,\n    }) => mixed,\n  ): IDisposable,\n\n  // Managing Cursor Position\n  getBufferRow(): number,\n  getBufferColumn(): number,\n  getBufferPosition(): atom$Point,\n\n  // Cursor Position Details\n  // Moving the Cursor\n  moveUp(rowCount: number, {moveToEndOfSelection?: boolean}): void,\n  moveDown(rowCount: number, {moveToEndOfSelection?: boolean}): void,\n\n  // Local Positions and Ranges\n  getCurrentWordBufferRange(options?: {wordRegex: RegExp}): atom$Range,\n  getCurrentWordPrefix(): string,\n\n  // Visibility\n  // Comparing to another cursor\n  // Utilities\n  wordRegExp(options?: {includeNonWordCharacters: boolean}): RegExp,\n}\n\ndeclare class atom$Decoration {\n  destroy(): void,\n  onDidChangeProperties(\n    callback: (event: {oldProperties: Object, newProperties: Object}) => mixed\n    ): IDisposable,\n  onDidDestroy(callback: () => mixed): IDisposable,\n  getMarker(): atom$Marker,\n  getProperties(): Object,\n  setProperties(properties: mixed): void,\n}\n\ndeclare class atom$DisplayMarkerLayer {\n  destroy(): void,\n  clear(): void,\n  isDestroyed(): boolean,\n  markBufferPosition(position: atom$PointLike, options?: MarkerOptions): atom$Marker,\n  markBufferRange(range: atom$Range | atom$RangeLike, options?: MarkerOptions): atom$Marker,\n  findMarkers(options: MarkerOptions): Array<atom$Marker>,\n  getMarkers(): Array<atom$Marker>,\n  onDidUpdate(callback: () => mixed): IDisposable\n}\n\ndeclare class atom$LayerDecoration {\n  destroy(): void,\n  isDestroyed(): boolean,\n  getProperties(): Object,\n  setProperties(properties: mixed): void,\n  setPropertiesForMarker(marker: atom$Marker, properties: mixed): void,\n}\n\ndeclare class atom$Disposable {\n  constructor(disposalAction?: (...args: Array<any>) => any): void,\n  disposed: boolean,\n  dispose(): void,\n}\n\ndeclare class atom$Emitter {\n  static onEventHandlerException(error: any): IDisposable,\n  dispose(): void,\n  on(name: string, callback: (v: any) => mixed): IDisposable,\n  once(name: string, callback: (v: any) => mixed): IDisposable,\n  preempt(name: string, callback: (v: any) => void): IDisposable,\n  // This is a flow hack to prevent emitting more than one value.\n  // `EventEmitter` allows emitting any number of values - making this a land\n  // mine, since we tend to think of `emit` as interchangeable.\n  // This hack only works if the extra value is not `undefined`, so this isn't\n  // full-proof, but it works for most cases.\n  emit(name: string, value: any, ...no_extra_args_allowed: Array<void>): void,\n}\n\ndeclare class atom$Gutter {\n  name: string,\n  destroy(): void,\n  decorateMarker(\n    marker: atom$Marker,\n    options?: {type?: string, 'class'?: string, item?: Object | HTMLElement},\n  ): atom$Decoration,\n  show(): void,\n  hide(): void,\n  onDidDestroy(callback: () => void): IDisposable,\n}\n\ndeclare type atom$MarkerChangeEvent = {\n  oldHeadScreenPosition: atom$Point,\n  newHeadScreenPosition: atom$Point,\n  oldTailScreenPosition: atom$Point,\n  newTailScreenPosition: atom$Point,\n\n  oldHeadBufferPosition: atom$Point,\n  newHeadBufferPosition: atom$Point,\n  oldTailBufferPosition: atom$Point,\n  newTailBufferPosition: atom$Point,\n\n  isValid: boolean,\n  textChanged: boolean,\n}\n\ndeclare class atom$Marker {\n  destroy(): void,\n  getBufferRange(): atom$Range,\n  getStartBufferPosition(): atom$Point,\n  onDidChange(callback: (event: atom$MarkerChangeEvent) => mixed): IDisposable,\n  isValid(): boolean,\n  isDestroyed(): boolean,\n  onDidDestroy(callback: () => mixed): IDisposable,\n  getScreenRange(): atom$Range,\n  setBufferRange(\n    range: atom$RangeLike,\n    properties?: {reversed: boolean},\n  ): void,\n  id: number,\n}\n\ndeclare class atom$ServiceHub {\n  provide<T>(keyPath: string, version: string, service: T): IDisposable,\n  consume<T>(\n    keyPath: string,\n    versionRange: string,\n    callback: (provider: T) => mixed\n  ): IDisposable,\n}\n\ntype atom$PackageMetadata = {\n  name: string,\n  version: string,\n};\n\ndeclare class atom$PackageManager {\n  +initialPackagesActivated: boolean,\n\n  // Event Subscription\n  onDidLoadInitialPackages(callback: () => void): IDisposable,\n  onDidActivateInitialPackages(callback: () => void): IDisposable,\n  onDidActivatePackage(callback: (pkg: atom$Package) => mixed): IDisposable,\n  onDidDeactivatePackage(callback: (pkg: atom$Package) => mixed): IDisposable,\n  onDidLoadPackage(callback: (pkg: atom$Package) => mixed): IDisposable,\n  onDidUnloadPackage(callback: (pkg: atom$Package) => mixed): IDisposable,\n  onDidTriggerActivationHook(activationHook: string, callback: () => mixed): IDisposable,\n\n  // Package system data\n  getApmPath(): string,\n  getPackageDirPaths(): Array<string>,\n\n  // General package data\n  resolvePackagePath(name: string): ?string,\n  isBundledPackage(name: string): boolean,\n\n  // Enabling and disabling packages\n  enablePackage(name: string): ?atom$Package,\n  disablePackage(name: string): ?atom$Package,\n  isPackageDisabled(name: string): boolean,\n\n  // Accessing active packages\n  getActivePackage(name: string): ?atom$Package,\n  getActivePackages(): Array<atom$Package>,\n  isPackageActive(name: string): boolean,\n  hasActivatedInitialPackages(): boolean,\n\n  // Activating and deactivating packages\n  activatePackage(name: string): Promise<atom$Package>,\n\n  // Accessing loaded packages\n  getLoadedPackage(name: string): ?atom$Package,\n  getLoadedPackages(): Array<atom$Package>,\n  isPackageLoaded(name: string): boolean,\n  hasLoadedInitialPackages(): boolean,\n\n  // Accessing available packages\n  getAvailablePackageNames(): Array<string>,\n  getAvailablePackageMetadata(): Array<atom$PackageMetadata>,\n\n  // (Undocumented.)\n  activate(): Promise<any>,\n  deactivatePackages(): Promise<void>,\n  deactivatePackage(name: string, suppressSerialization?: boolean): Promise<void>,\n  emitter: atom$Emitter,\n  loadedPackages: {[packageName: string]: atom$Package},\n  loadPackage(name: string): void,\n  loadPackages(): void,\n  serializePackage(pkg: atom$Package): void,\n  serviceHub: atom$ServiceHub,\n  packageDirPaths: Array<string>,\n  triggerActivationHook(hook: string): void,\n  triggerDeferredActivationHooks(): void,\n  unloadPackage(name: string): void,\n  unloadPackages(): void,\n}\n\ndeclare class atom$StyleManager {\n  // Event Subscription\n\n  // Reading Style Elements\n  getStyleElements(): Array<HTMLStyleElement>,\n\n  // Paths\n  getUserStyleSheetPath(): string,\n\n  // (Undocumented.)\n  addStyleSheet(\n    source: string,\n    params: {\n      sourcePath?: string,\n      context?: boolean,\n      priority?: number,\n      skipDeprecatedSelectorsTransformation?: boolean\n    }\n  ): IDisposable,\n}\n\ntype atom$PaneSplitParams = {\n  copyActiveItem?: boolean,\n  items?: Array<Object>,\n};\n\ntype atom$PaneSplitOrientation = 'horizontal' | 'vertical';\ntype atom$PaneSplitSide = 'before' | 'after';\n\n// Undocumented class\ndeclare class atom$applicationDelegate {\n  focusWindow(): Promise<mixed>,\n  open(params: {\n    pathsToOpen: Array<string>,\n    newWindow?: boolean,\n    devMode?: boolean,\n    safeMode?: boolean,\n  }): void,\n\n  // Used by nuclide-config to replicate atom.config saveCallback\n  setUserSettings(config: atom$Config, configFilePath: string): Promise<mixed>;\n}\n\ntype atom$PaneParams = {\n  activeItem?: Object,\n  applicationDelegate: atom$applicationDelegate,\n  focused?: boolean,\n  container: Object,\n  config: atom$Config,\n  notificationManager: atom$NotificationManager,\n  deserializerManager: atom$DeserializerManager,\n  items?: Array<Object>,\n  itemStackIndices?: Array<number>,\n  flexScale?: number,\n};\n\ndeclare class atom$Pane {\n  // Items\n  addItem(item: Object, options?: {index?: number, pending?: boolean}): Object,\n  getItems(): Array<Object>,\n  getActiveItem(): ?Object,\n  itemAtIndex(index: number): ?Object,\n  getActiveItemIndex(): number,\n  activateItem(item: Object): ?Object,\n  activateItemAtIndex(index: number): void,\n  moveItemToPane(item: Object, pane: atom$Pane, index: number): void,\n  destroyItem(item: Object, force?: boolean): Promise<boolean>,\n  itemForURI(uri: string): Object,\n\n  // Event subscriptions.\n  onDidAddItem(cb: (event: {item: Object, index: number}) => void): IDisposable,\n  onDidRemoveItem(cb: (event: {item: Object, index: number}) => void): IDisposable,\n  onWillRemoveItem(cb: (event: {item: Object, index: number}) => void): IDisposable,\n  onDidDestroy(cb: () => mixed): IDisposable,\n  onDidChangeFlexScale(cb: (newFlexScale: number) => void): IDisposable,\n  onWillDestroy(cb: () => void): IDisposable,\n  observeActiveItem(cb: (item: ?Object) => void): IDisposable,\n\n  // Lifecycle\n  isActive(): boolean,\n  activate(): void,\n  destroy(): void,\n  isDestroyed(): void,\n\n  // Splitting\n  splitLeft(params?: atom$PaneSplitParams): atom$Pane,\n  splitRight(params?: atom$PaneSplitParams): atom$Pane,\n  splitUp(params?: atom$PaneSplitParams): atom$Pane,\n  splitDown(params?: atom$PaneSplitParams): atom$Pane,\n  split(\n    orientation: atom$PaneSplitOrientation,\n    side: atom$PaneSplitSide,\n    params?: atom$PaneSplitParams,\n  ): atom$Pane,\n\n  // Undocumented Methods\n  constructor(params: atom$PaneParams): atom$Pane,\n  getPendingItem(): atom$PaneItem,\n  setPendingItem(item: atom$PaneItem): void,\n  clearPendingItem(): void,\n  getFlexScale(): number,\n  getElement(): HTMLElement,\n  getParent(): Object,\n  removeItem(item: Object, moved: ?boolean): void,\n  setActiveItem(item: Object): Object,\n  setFlexScale(flexScale: number): number,\n  getContainer(): atom$PaneContainer,\n\n  element: HTMLElement,\n}\n\ndeclare interface atom$PaneItem {\n  // These are all covariant, meaning that these props are read-only. Therefore we can assign an\n  // object with more strict requirements to an variable of this type.\n  +getTitle: () => string,\n  +getLongTitle?: () => string,\n  +getIconName?: () => string,\n  +getURI?: () => ?string,\n  +onDidChangeIcon?: (cb: (icon: string) => void) => IDisposable,\n  +onDidChangeTitle?: (cb: (title: string) => void) => IDisposable,\n  +onDidTerminatePendingState?: (() => mixed) => IDisposable;\n  +serialize?: () => Object,\n  +terminatePendingState?: () => void,\n}\n\n// Undocumented class\ndeclare class atom$PaneAxis {\n  getFlexScale(): number,\n  setFlexScale(flexScale: number): number,\n  getItems(): Array<Object>,\n}\n\n// Undocumented class\n// Note that this is not the same object returned by `atom.workspace.getPaneContainers()`. (Those\n// are typed here as AbstractPaneContainers and, in the current implementation, wrap these.)\ndeclare class atom$PaneContainer {\n  constructor({\n    config: atom$Config,\n    applicationDelegate: atom$applicationDelegate,\n    notificationManager: atom$NotificationManager,\n    deserializerManager: atom$DeserializerManager,\n  }): atom$PaneContainer,\n  destroy(): void,\n  getActivePane(): atom$Pane,\n  getActivePaneItem(): ?Object,\n  getLocation(): atom$PaneLocation,\n  getPanes(): Array<atom$Pane>,\n  getPaneItems(): Array<atom$PaneItem>,\n  observePanes(cb: (pane: atom$Pane) => void): IDisposable,\n  onDidAddPane(cb: (event: {pane: atom$Pane}) => void): IDisposable,\n  onDidDestroyPane(cb: (event: {pane: atom$Pane}) => void): IDisposable,\n  onWillDestroyPane(cb: (event: {pane: atom$Pane}) => void): IDisposable,\n  onDidAddPaneItem(cb: (item: atom$PaneItem) => void): IDisposable,\n  onDidDestroyPaneItem(cb: (item: atom$Pane) => void): IDisposable,\n  paneForItem(item: Object): ?atom$Pane,\n  serialize(): Object,\n}\n\ndeclare class atom$Panel {\n  // Construction and Destruction\n  destroy(): void,\n\n  // Event Subscription\n  onDidChangeVisible(callback: (visible: boolean) => any): IDisposable,\n  onDidDestroy(callback: (panel: atom$Panel) => any): IDisposable,\n\n  // Panel Details\n  getElement(): HTMLElement,\n  getItem(): any,\n  getPriority(): number,\n  isVisible(): boolean,\n  hide(): void,\n  show(): void,\n}\n\ntype atom$PointObject = {row: number, column: number};\n\ntype atom$PointLike = atom$Point\n| [number, number]\n| atom$PointObject;\n\ndeclare class atom$Point {\n  static fromObject(object: atom$PointLike, copy: ? boolean): atom$Point,\n  constructor(row: number, column: number): void,\n  row: number,\n  column: number,\n  copy(): atom$Point,\n  negate(): atom$Point,\n\n  // Comparison\n  min(point1: atom$PointLike, point2: atom$PointLike): atom$Point,\n  compare(other: atom$PointLike): -1 | 0 | 1,\n  isEqual(otherRange: atom$PointLike): boolean,\n  isLessThan(other: atom$PointLike): boolean,\n  isLessThanOrEqual(other: atom$PointLike): boolean,\n  isGreaterThan(other: atom$PointLike): boolean,\n  isGreaterThanOrEqual(other: atom$PointLike): boolean,\n\n  // Operations\n  translate(other: atom$PointLike): atom$Point,\n\n  // Conversion\n  serialize(): [number, number],\n  toArray(): [number, number],\n}\n\ntype atom$RangeObject = {\n  start: atom$PointObject,\n  end: atom$PointObject,\n};\n\ntype atom$RangeLike = atom$Range\n  | atom$RangeObject // TODO: Flow doesn't really handle the real signature below...\n  | [atom$PointLike, atom$PointLike]\n  | {\n    start: atom$PointLike,\n    end: atom$PointLike,\n  };\n\ndeclare class atom$Range {\n  static fromObject(\n    object: atom$RangeLike,\n    copy?: boolean,\n  ): atom$Range,\n  constructor(pointA: atom$PointLike, pointB: atom$PointLike): void,\n  compare(other: atom$Range): number,\n  start: atom$Point,\n  end: atom$Point,\n  isEmpty(): boolean,\n  isEqual(otherRange: atom$RangeLike): boolean,\n  intersectsWith(otherRange: atom$RangeLike, exclusive?: boolean): boolean,\n  containsPoint(point: atom$PointLike, exclusive?: boolean): boolean,\n  containsRange(other: atom$Range, exclusive?: boolean): boolean,\n  union(other: atom$Range): atom$Range,\n  serialize(): Array<Array<number>>,\n  translate(startDelta: atom$PointLike, endDelta?: atom$PointLike): atom$Range,\n  getRowCount(): number,\n  getRows(): Array<number>,\n}\n\ntype RawStatusBarTile = {\n  item: HTMLElement,\n  priority: number,\n};\n\ntype atom$StatusBarTile = {\n  getPriority(): number,\n  getItem(): HTMLElement,\n  destroy(): void,\n};\n\ndeclare class atom$ScopeDescriptor {\n  constructor(object: {scopes: Array<string>}): void,\n  getScopesArray(): Array<string>,\n}\n\ntype atom$ScopeDescriptorLike = atom$ScopeDescriptor | Array<string>;\n\n/**\n * This API is defined at https://github.com/atom/status-bar.\n */\ndeclare class atom$StatusBar {\n  addLeftTile(tile: RawStatusBarTile): atom$StatusBarTile,\n  addRightTile(tile: RawStatusBarTile): atom$StatusBarTile,\n  getLeftTiles(): Array<atom$StatusBarTile>,\n  getRightTiles(): Array<atom$StatusBarTile>,\n}\n\n// https://github.com/atom/atom/blob/v1.9.0/src/text-editor-registry.coffee\ndeclare class atom$TextEditorRegistry {\n  add(editor: atom$TextEditor): IDisposable,\n  remove(editor: atom$TextEditor): boolean,\n  observe(callback: (editor: atom$TextEditor) => void): IDisposable,\n  build: (params: atom$TextEditorParams) => atom$TextEditor,\n\n  // Private\n  editors: Set<atom$TextEditor>,\n}\n\ndeclare class atom$ThemeManager {\n  // Event Subscription\n  /**\n   * As recent as Atom 1.0.10, the implementation of this method was:\n   *\n   * ```\n   * onDidChangeActiveThemes: (callback) ->\n   *   @emitter.on 'did-change-active-themes', callback\n   *   @emitter.on 'did-reload-all', callback # TODO: Remove once deprecated pre-1.0 APIs are gone\n   * ```\n   *\n   * Due to the nature of CoffeeScript, onDidChangeActiveThemes returns a Disposable even though it\n   * is not documented as doing so. However, the Disposable that it does return removes the\n   * subscription on the 'did-reload-all' event (which is supposed to be deprecated) rather than the\n   * 'did-change-active-themes' one.\n   */\n  onDidChangeActiveThemes(callback: () => mixed): IDisposable,\n\n  // Accessing Loaded Themes\n  getLoadedThemeNames(): Array<string>,\n  getLoadedThemes(): Array<mixed>, // TODO: Define undocumented ThemePackage class.\n\n  // Accessing Active Themes\n  getActiveThemeNames(): Array<string>,\n  getActiveThemes(): Array<mixed>, // TODO: Define undocumented ThemePackage class.\n\n  // Managing Enabled Themes\n  getEnabledThemeNames(): Array<string>,\n\n  // Private\n  activateThemes(): Promise<any>,\n  requireStylesheet(stylesheetPath: string): IDisposable,\n}\n\ntype atom$TooltipsPlacementOption = 'top' | 'bottom' | 'left' | 'right' | 'auto';\n\ntype atom$TooltipsAddOptions = {\n  title?: string,\n  item?: HTMLElement,\n  keyBindingCommand?: string,\n  keyBindingTarget?: HTMLElement,\n  animation?: boolean,\n  container?: string | false,\n  delay?: number | {show: number, hide: number},\n  placement?: atom$TooltipsPlacementOption | () => atom$TooltipsPlacementOption,\n  trigger?: string,\n};\n\ntype atom$Tooltip = {\n  show(): void;\n  hide(): void;\n  getTooltipElement(): HTMLElement,\n};\n\ndeclare class atom$TooltipManager {\n  tooltips: Map<HTMLElement, Array<atom$Tooltip>>;\n  add(\n    target: HTMLElement,\n    options: atom$TooltipsAddOptions,\n  ): IDisposable,\n  findTooltips(HTMLElement): Array<atom$Tooltip>,\n}\n\ntype InsertTextOptions = {\n  select: boolean,\n  autoIndent: boolean,\n  autoIndentNewline: boolean,\n  autoDecreaseIndent: boolean,\n  normalizeLineEndings: ?boolean,\n  undo: string,\n};\n\ntype DecorateMarkerParams = {\n  type: 'line',\n  class: string,\n  onlyHead?: boolean,\n  onlyEmpty?: boolean,\n  onlyNonEmpty?: boolean,\n} | {\n  type: 'gutter',\n  item?: HTMLElement,\n  class?: string,\n  onlyHead?: boolean,\n  onlyEmpty?: boolean,\n  onlyNonEmpty?: boolean,\n  gutterName?: string,\n} | {\n  type: 'highlight',\n  class?: string,\n  gutterName?: string,\n} | {\n  type: 'overlay',\n  item: Object,\n  position?: 'head' | 'tail', // Defaults to 'head' when unspecified.\n} | {\n  type: 'block',\n  item: HTMLElement,\n  position?: 'before' | 'after', // Defaults to 'before' when unspecified.\n} | {\n  type: 'line-number',\n  class?: string,\n};\n\ntype ChangeCursorPositionEvent = {\n  oldBufferPosition: atom$Point,\n  oldScreenPosition: atom$Point,\n  newBufferPosition: atom$Point,\n  newScreenPosition: atom$Point,\n  textChanged: boolean,\n  cursor: atom$Cursor,\n};\n\ntype MarkerOptions = {\n  reversed?: boolean,\n  tailed?: boolean,\n  invalidate?: 'never' | 'surround' | 'overlap' | 'inside' | 'touch',\n  exclusive?: boolean,\n};\n\ntype atom$ChangeSelectionRangeEvent = {|\n  oldBufferRange: atom$Range,\n  oldScreenRange: atom$Range,\n  newBufferRange: atom$Range,\n  newScreenRange: atom$Range,\n  selection: atom$Selection,\n|};\n\ndeclare class atom$TextEditor extends atom$Model {\n  id: number,\n  verticalScrollMargin: number,\n\n  // Event Subscription\n  onDidChange(callback: () => void): IDisposable,\n  onDidChangePath(callback: (newPath: string) => mixed): IDisposable,\n  onDidStopChanging(callback: () => mixed): IDisposable,\n  onDidChangeCursorPosition(callback: (event: ChangeCursorPositionEvent) => mixed):\n    IDisposable,\n  onDidAddCursor(callback: (cursor: atom$Cursor) => mixed): IDisposable;\n  onDidRemoveCursor(callback: (cursor: atom$Cursor) => mixed): IDisposable;\n  onDidDestroy(callback: () => mixed): IDisposable,\n  onDidSave(callback: (event: {path: string}) => mixed): IDisposable,\n  getBuffer(): atom$TextBuffer,\n  observeGrammar(callback: (grammar: atom$Grammar) => mixed): IDisposable,\n  onWillInsertText(callback: (event: {cancel: () => void, text: string}) => void):\n      IDisposable,\n  // Note that the range property of the event is undocumented.\n  onDidInsertText(callback: (event: {text: string, range: atom$Range}) => mixed): IDisposable,\n  onDidChangeSoftWrapped(callback: (softWrapped: boolean) => mixed): IDisposable,\n  onDidChangeSelectionRange(callback: (event: atom$ChangeSelectionRangeEvent) => mixed): IDisposable,\n  observeSelections(callback: (selection: atom$Selection) => mixed): IDisposable,\n\n  // File Details\n  getTitle: () => string,\n  getLongTitle(): string,\n  /**\n   * If you open Atom via Spotlight such that it opens with a tab named\n   * \"untitled\" that does not correspond to a file on disk, this will return\n   * null.\n   */\n  getPath(): ?string,\n  getURI: () => ?string,\n  insertNewline(): void,\n  isModified: () => boolean,\n  isEmpty(): boolean,\n  getEncoding(): buffer$Encoding,\n  setEncoding(encoding: string): void,\n  getTabLength() : number,\n  getSoftTabs(): boolean,\n  getIconName(): string,\n  onDidChangeIcon(cb: (icon: string) => void): IDisposable,\n  onDidChangeTitle(cb: (title: string) => void): IDisposable,\n\n  // File Operations\n  save(): Promise<void>,\n  // DO NOT USE: Doesn't work with remote text buffers!\n  // saveAs(filePath: string): void,\n\n  // Reading Text\n  getText(): string,\n  getTextInBufferRange(range: atom$RangeLike): string,\n  getLineCount(): number,\n  getScreenLineCount(): number,\n  getLastScreenRow(): number,\n\n  // Mutating Text\n  setText(text: string, options?: InsertTextOptions): void,\n  setTextInBufferRange(\n    range: atom$RangeLike,\n    text: string,\n    options?: {\n      normalizeLineEndings?: boolean,\n      undo?: string,\n    },\n  ): atom$Range,\n  insertText(text: string): Array<atom$Range> | false,\n  mutateSelectedText(fn: (selection: atom$Selection, index: number) => void): void,\n  delete: () => void,\n  backspace: () => void,\n  duplicateLines: () => void,\n\n  // History\n  createCheckpoint(): atom$TextBufferCheckpoint,\n  revertToCheckpoint(checkpoint: atom$TextBufferCheckpoint): boolean,\n  terminatePendingState(): void,\n  transact(fn: () => mixed, _: void): void,\n  transact(groupingInterval: number, fn: () => mixed): void,\n  onDidTerminatePendingState(() => mixed): IDisposable;\n\n  // TextEditor Coordinates\n  screenPositionForBufferPosition(\n    bufferPosition: atom$PointLike,\n    options?: {\n      wrapBeyondNewlines?: boolean,\n      wrapAtSoftNewlines?: boolean,\n      screenLine?: boolean,\n    },\n  ): atom$Point,\n  bufferPositionForScreenPosition(\n    screenPosition: atom$PointLike,\n    options?: {\n      wrapBeyondNewlines?: boolean,\n      wrapAtSoftNewlines?: boolean,\n      screenLine?: boolean,\n    },\n  ): atom$Point,\n  getEofBufferPosition(): atom$Point,\n  getVisibleRowRange(): [number, number],\n  bufferRowForScreenRow(screenRow: number): number,\n  screenRangeForBufferRange(bufferRange: atom$RangeLike): atom$Range,\n\n  // Decorations\n  decorateMarker(marker: atom$Marker, decorationParams: DecorateMarkerParams): atom$Decoration,\n  decorateMarkerLayer(\n    markerLayer: atom$DisplayMarkerLayer,\n    decorationParams: DecorateMarkerParams,\n  ): atom$LayerDecoration,\n  decorationsForScreenRowRange(\n    startScreenRow: number,\n    endScreenRow: number,\n  ): {[markerId: string]: Array<Object>},\n  getDecorations(options?: {class?: string, type?: string}): Array<atom$Decoration>,\n\n  // Markers\n  addMarkerLayer(): atom$DisplayMarkerLayer,\n  getDefaultMarkerLayer(): atom$DisplayMarkerLayer,\n  markBufferPosition(position: atom$PointLike, options?: MarkerOptions): atom$Marker,\n  markBufferRange(range: atom$RangeLike, options?: MarkerOptions): atom$Marker,\n  markScreenRange(range: atom$RangeLike, options?: MarkerOptions): atom$Marker,\n  markScreenPosition(position: atom$PointLike, options?: MarkerOptions): atom$Marker,\n  findMarkers(options: MarkerOptions): Array<atom$Marker>,\n  getMarkerCount(): number,\n\n  // Cursors\n  getCursors(): Array<atom$Cursor>,\n  setCursorBufferPosition(\n    position: atom$PointLike,\n    options?: {\n      autoscroll?: boolean,\n      wrapBeyondNewlines?: boolean,\n      wrapAtSoftNewlines?: boolean,\n      screenLine?: boolean,\n    }): void,\n  getCursorBufferPosition(): atom$Point,\n  getCursorBufferPositions(): Array<atom$Point>,\n  getCursorScreenPosition(): atom$Point,\n  getCursorScreenPositions(): Array<atom$Point>,\n  getLastCursor(): atom$Cursor,\n  addCursorAtBufferPosition(point: atom$PointLike): atom$Cursor,\n  moveToBeginningOfLine(): void,\n  moveToEndOfLine(): void,\n  moveToBottom(): void,\n\n  // Folds\n  foldCurrentRow(): void,\n  unfoldCurrentRow(): void,\n  foldBufferRow(bufferRow: number): void,\n  unfoldBufferRow(bufferRow: number): void,\n\n  // Selections\n  getSelectedText(): string,\n  selectAll(): void,\n  getSelectedBufferRange(): atom$Range,\n  getSelectedBufferRanges(): Array<atom$Range>,\n  getSelections(): Array<atom$Selection>,\n  selectToBufferPosition(point: atom$Point): void,\n  setSelectedBufferRange(\n    bufferRange: atom$RangeLike,\n    options?: {\n      reversed?: boolean,\n      preserveFolds?: boolean,\n    },\n  ): void,\n  setSelectedBufferRanges(\n    bufferRanges: Array<atom$Range>,\n    options?: {\n      reversed?: boolean,\n      preserveFolds?: boolean,\n    },\n  ): void,\n  selectWordsContainingCursors(): void,\n\n  // Folds\n  unfoldAll(): void,\n\n  // Searching and Replacing\n  scanInBufferRange(\n    regex: RegExp,\n    range: atom$Range,\n    iterator: (foundMatch: {\n      match: mixed,\n      matchText: string,\n      range: atom$Range,\n      stop: () => mixed,\n      replace: (replaceWith: string) => mixed,\n    }) => mixed\n  ): void,\n\n  scan(\n    regex: RegExp,\n    iterator: (foundMatch: {\n      match: mixed,\n      matchText: string,\n      range: atom$Range,\n      stop: () => mixed,\n      replace: (replaceWith: string) => mixed,\n    }) => mixed\n  ): void,\n\n  // Tab Behavior\n  // Soft Wrap Behavior\n  // Indentation\n  indentationForBufferRow(bufferRow: number): number,\n  setTabLength(tabLength: number): void,\n  setSoftTabs(softTabs: boolean): void,\n\n  lineTextForBufferRow(bufferRow: number): string,\n  lineTextForScreenRow(screenRow: number): string,\n\n  // Grammars\n  getGrammar(): atom$Grammar,\n  setGrammar(grammar: ?atom$Grammar): void,\n\n  // Clipboard Operations\n  pasteText: (options?: Object) => void,\n  copySelectedText: () => void,\n\n  // Managing Syntax Scopes\n  getRootScopeDescriptor(): atom$ScopeDescriptor,\n  scopeDescriptorForBufferPosition(\n    bufferPosition: atom$PointLike,\n  ): atom$ScopeDescriptor,\n\n  // Gutter\n  addGutter(options: {\n    name: string,\n    priority?: number,\n    visible?: boolean,\n  }): atom$Gutter,\n  observeGutters(callback: (gutter: atom$Gutter) => void): IDisposable,\n  getGutters(): Array<atom$Gutter>,\n  gutterWithName(name: string): ?atom$Gutter,\n\n  // Scrolling the TextEditor\n  scrollToBufferPosition(\n    position: atom$Point | [?number, ?number],\n    options?: {center?: boolean}\n  ): void,\n  scrollToScreenPosition(\n    position: atom$Point | [?number, ?number],\n    options?: {center?: boolean}\n  ): void,\n  scrollToScreenRange(screenRange: atom$Range, options?: {clip?: boolean}): void,\n  scrollToCursorPosition(\n    options?: {center?: boolean}\n  ): void,\n  scrollToBottom(): void,\n  scrollToTop(): void,\n\n  // TextEditor Rendering\n  getPlaceholderText(): string,\n  setPlaceholderText(placeholderText: string): void,\n\n  // This is undocumented, but Nuclide uses it in the AtomTextEditor wrapper.\n  setLineNumberGutterVisible(lineNumberGutterVisible: boolean): void,\n\n  // Editor Options\n  setSoftWrapped(softWrapped: boolean): void,\n\n  isFoldedAtBufferRow(row: number): boolean,\n  getLastBufferRow(): number,\n\n  // Undocumented Methods\n  getElement(): atom$TextEditorElement,\n  getDefaultCharWidth(): number,\n  getLineHeightInPixels(): number,\n  moveToTop(): void,\n  tokenForBufferPosition(position: atom$Point | [?number, ?number]): atom$Token,\n  onDidConflict(callback: () => void): IDisposable,\n  serialize(): Object,\n  foldBufferRowRange(startRow: number, endRow: number): void,\n  getNonWordCharacters(position?: atom$PointLike): string,\n  scheduleComponentUpdate(): void,\n}\n\n/**\n * This is not part of the official Atom 1.0 API. Nevertheless, we need to reach into this object\n * via `atom$TextEditorElement` to do some things that we have no other way to do.\n */\ndeclare class atom$TextEditorComponent {\n  domNode: HTMLElement,\n  scrollViewNode: HTMLElement,\n  presenter: atom$TextEditorPresenter,\n  refs: atom$TextEditorComponentRefs,\n  linesComponent: atom$LinesComponent,\n  // NOTE: This is typed as a property to allow overwriting.\n  startCursorBlinking: () => void,\n  stopCursorBlinking(): void,\n  pixelPositionForScreenPosition(\n    screenPosition: atom$Point,\n    clip?: boolean,\n  ): {top: number, left: number},\n  screenPositionForMouseEvent(event: MouseEvent): atom$Point,\n  pixelPositionForMouseEvent(\n    event: MouseEvent,\n    linesClientRect?: {top: number, left: number, bottom: number, right: number},\n  ): {top: number, left: number, bottom: number, right: number},\n  invalidateBlockDecorationDimensions(decoration: atom$Decoration): void,\n  element: atom$TextEditorElement,\n  didFocus(): void,\n  setScrollTop(scrollTop: number): void,\n  getScrollTop(): number,\n\n  setScrollLeft(scrollLeft: number): void,\n  getScrollLeft(): number,\n  updateSync(useScheduler?: boolean): void,\n}\n\n/**\n * This is not part of the official Atom 1.0 API. Nevertheless, we need to reach into this object\n * via `atom$TextEditorComponent` to do some things that we have no other way to do.\n */\ndeclare class atom$TextEditorPresenter {\n  startBlinkingCursors: () => void,\n  stopBlinkingCursors(visible: boolean): void,\n  updateLineNumberGutterState(): void,\n}\n\n/**\n * This is not part of the official Atom 1.0 API. Nevertheless, we need it to access\n * the deepest dom element receiving DOM events.\n */\ndeclare class atom$LinesComponent {\n  domNode: HTMLElement,\n  getDomNode(): HTMLElement,\n}\n\n/**\n * This is not part of the official Atom 1.0 API. Nevertheless, we need it to access\n * the deepest dom element receiving DOM events.\n */\ndeclare class atom$TextEditorComponentRefs {\n  lineTiles: HTMLElement,\n}\n\n/**\n * This is not part of the official Atom 1.0 API, but it really should be. This is the element that\n * is returned when you run `atom.views.getView(<TextEditor>)`.\n */\ndeclare class atom$TextEditorElement extends HTMLElement {\n  component: ?atom$TextEditorComponent,\n  getModel(): atom$TextEditor,\n  setModel(model: atom$TextEditor): void,\n  pixelPositionForBufferPosition(\n    bufferPosition: atom$PointLike,\n  ): {top: number, left: number},\n  pixelPositionForScreenPosition(screenPosition: atom$Point): {\n    left: number,\n    top: number,\n  },\n\n  setScrollTop(scrollTop: number): void,\n  getScrollTop(): number,\n\n  setScrollLeft(scrollLeft: number): void,\n  getScrollLeft(): number,\n\n  getScrollHeight(): number,\n  getHeight(): number,\n\n  onDidChangeScrollTop(callback: (scrollTop: number) => mixed): IDisposable,\n  onDidChangeScrollLeft(callback: (scrollLeft: number) => mixed): IDisposable,\n\n  // Called when the editor is attached to the DOM.\n  onDidAttach(callback: () => mixed): IDisposable,\n  // Called when the editor is detached from the DOM.\n  onDidDetach(callback: () => mixed): IDisposable,\n\n  measureDimensions(): void,\n\n  // Undocumented Methods\n\n  // Returns a promise that resolves after the next update.\n  getNextUpdatePromise(): Promise<void>,\n\n  // `undefined` means no explicit width. `null` sets a zero width (which is almost certainly a\n  // mistake) so we don't allow it.\n  setWidth(width: number | void): void,\n}\n\ndeclare class atom$ViewProvider {\n  modelConstructor: Function,\n}\n\ndeclare class atom$ViewRegistry {\n  // Methods\n  addViewProvider(\n    modelConstructor: any,\n    createView?: (...args: Array<any>) => ?HTMLElement\n  ): IDisposable,\n  getView(textEditor: atom$TextEditor): atom$TextEditorElement,\n  getView(notification: atom$Notification): HTMLElement,\n  getView(gutter: atom$Gutter): HTMLElement,\n  getView(panel: atom$Panel): HTMLElement,\n  getView(workspace: atom$Workspace): HTMLElement,\n  getView(object: Object): HTMLElement,\n  providers: Array<atom$ViewProvider>,\n}\n\ntype atom$WorkspaceAddPanelOptions = {\n  item: Object,\n  visible?: boolean,\n  priority?: number,\n  className?: string,\n};\n\ntype atom$TextEditorParams = {\n  buffer?: atom$TextBuffer,\n  lineNumberGutterVisible?: boolean,\n};\n\ntype DestroyPaneItemEvent = {\n  item: atom$PaneItem,\n  pane: atom$Pane,\n  index: number,\n};\n\ntype AddPaneItemEvent = {\n  item: atom$PaneItem,\n  pane: atom$Pane,\n  index: number,\n};\n\ntype OnDidOpenEvent = {\n  uri: string,\n  item: mixed,\n  pane: atom$Pane,\n  index: number,\n};\n\ntype AddTextEditorEvent = {\n  textEditor: atom$TextEditor,\n  pane: atom$Pane,\n  index: number,\n};\n\ntype atom$WorkspaceOpenOptions = {\n  activatePane?: ?boolean,\n  activateItem?: ?boolean,\n  initialLine?: ?number,\n  initialColumn?: ?number,\n  pending?: ?boolean,\n  split?: ?string,\n  searchAllPanes?: ?boolean,\n  location?: atom$PaneLocation,\n}\n\ndeclare class atom$Workspace {\n  // Event Subscription\n  observePanes(cb: (pane: atom$Pane) => void): IDisposable,\n  observeTextEditors(callback: (editor: atom$TextEditor) => mixed): IDisposable,\n  observeActiveTextEditor(callback: (editor: ?atom$TextEditor) => mixed): IDisposable,\n  onDidAddTextEditor(callback: (event: AddTextEditorEvent) => mixed): IDisposable,\n  onDidChangeActivePaneItem(callback: (item: mixed) => mixed): IDisposable,\n  onDidDestroyPaneItem(callback: (event: DestroyPaneItemEvent) => mixed): IDisposable,\n  onDidAddPaneItem(callback: (event: AddPaneItemEvent) => mixed): IDisposable,\n  observeActivePaneItem(callback: (item: ?mixed) => mixed): IDisposable,\n  onDidStopChangingActivePaneItem(callback: (item: ?mixed) => mixed): IDisposable,\n  observePaneItems(callback: (item: mixed) => mixed): IDisposable,\n  onWillDestroyPaneItem(\n    callback: (event: {item: mixed, pane: mixed, index: number}) => mixed\n  ): IDisposable,\n  onDidOpen(callback: (event: OnDidOpenEvent) => mixed): IDisposable,\n\n  getElement(): HTMLElement,\n\n  // Opening\n  open(\n    uri?: string,\n    options?: atom$WorkspaceOpenOptions,\n  ): Promise<atom$TextEditor>,\n  openURIInPane(\n    uri?: string,\n    pane: atom$Pane,\n    options?: {\n      initialLine?: number,\n      initialColumn?: number,\n      activePane?: boolean,\n      searchAllPanes?: boolean,\n    }\n  ): Promise<atom$TextEditor>,\n  isTextEditor(item: ?mixed): boolean,\n  /* Optional method because this was added post-1.0. */\n  buildTextEditor: ((params: ?atom$TextEditorParams) => atom$TextEditor),\n  /* Optional method because this was added in 1.9.0 */\n  handleGrammarUsed?: (grammar: atom$Grammar) => void,\n  reopenItem(): Promise<?atom$TextEditor>,\n  addOpener(callback: (uri: string) => any): IDisposable,\n  hide(uriOrItem: string | Object): void,\n  toggle(uriOrItem: string | Object): void,\n\n  // Pane Containers\n  getPaneContainers(): Array<atom$AbstractPaneContainer>,\n  paneContainerForItem(item: ?mixed): ?atom$AbstractPaneContainer,\n\n  // Pane Items\n  getPaneItems(): Array<Object>,\n  getActivePaneItem(): ?Object,\n  getActivePaneContainer(): atom$PaneContainer,\n  getTextEditors(): Array<atom$TextEditor>,\n  getActiveTextEditor(): ?atom$TextEditor,\n  createItemForURI(uri: string, options: atom$WorkspaceOpenOptions): atom$PaneItem,\n\n  // Panes\n  getPanes(): Array<atom$Pane>,\n  getActivePane(): atom$Pane,\n  activateNextPane(): boolean,\n  activatePreviousPane(): boolean,\n  paneForURI(uri: string): atom$Pane,\n  paneForItem(item: mixed): ?atom$Pane,\n  paneContainers: {[location: atom$PaneLocation]: atom$AbstractPaneContainer},\n\n  // Panels\n  panelContainers: {[location: string]: atom$PanelContainer},\n  getBottomPanels(): Array<atom$Panel>,\n  addBottomPanel(options: atom$WorkspaceAddPanelOptions): atom$Panel,\n  getLeftPanels(): Array<atom$Panel>,\n  addLeftPanel(options: atom$WorkspaceAddPanelOptions): atom$Panel,\n  getRightPanels(): Array<atom$Panel>,\n  addRightPanel(options: atom$WorkspaceAddPanelOptions): atom$Panel,\n  getTopPanels(): Array<atom$Panel>,\n  addTopPanel(options: atom$WorkspaceAddPanelOptions): atom$Panel,\n  getModalPanels(): Array<atom$Panel>,\n  addModalPanel(options: atom$WorkspaceAddPanelOptions): atom$Panel,\n  getHeaderPanels(): Array<atom$Panel>,\n  addHeaderPanel(options: atom$WorkspaceAddPanelOptions): atom$Panel,\n\n  getLeftDock(): atom$Dock,\n  getRightDock(): atom$Dock,\n  getBottomDock(): atom$Dock,\n  getCenter(): atom$WorkspaceCenter,\n\n  // Searching and Replacing\n  scan(\n    regex: RegExp,\n    options: {\n      paths?: Array<string>,\n      onPathsSearched?: (numSearched: number) => mixed,\n      leadingContextLineCount?: number,\n      trailingContextLineCount?: number,\n    },\n    iterator: (\n      ?{\n        filePath: string,\n        matches: Array<{\n          leadingContextLines: Array<string>,\n          lineText: string,\n          lineTextOffset: number,\n          range: atom$RangeLike,\n          matchText: string,\n          trailingContextLines: Array<string>,\n        }>,\n      },\n      Error,\n    ) => mixed,\n  ): Promise<?string>,\n\n  destroyActivePaneItemOrEmptyPane(): void,\n  destroyActivePaneItem(): void,\n}\n\ndeclare class atom$AbstractPaneContainer {\n  activate(): void,\n  getLocation(): atom$PaneLocation,\n  getElement(): HTMLElement,\n  isVisible(): boolean,\n  show(): void,\n  hide(): void,\n  getActivePane(): atom$Pane,\n  getPanes(): Array<atom$Pane>,\n  onDidAddPaneItem((item: {item: Object}) => void): IDisposable,\n  observePanes(cb: (pane: atom$Pane) => void): IDisposable,\n  state: {\n    size: number,\n  }\n}\n\ndeclare class atom$Dock extends atom$AbstractPaneContainer {\n  // This is a woefully incomplete list, items can be added as needed from\n  // https://github.com/atom/atom/blob/master/src/dock.js\n  toggle(): void,\n}\n\ndeclare class atom$WorkspaceCenter extends atom$AbstractPaneContainer {\n  activate(): void;\n\n  // Pane Items\n  getPaneItems(): Array<atom$PaneItem>,\n  getActivePaneItem(): ?atom$PaneItem,\n  getTextEditors(): Array<atom$TextEditor>,\n  getActiveTextEditor(): ?atom$TextEditor,\n\n  observeActivePaneItem(callback: atom$PaneItem => mixed): IDisposable;\n  onDidChangeActivePaneItem(callback: (item: mixed) => mixed): IDisposable;\n  onDidAddTextEditor(\n    callback: (item: {\n      textEditor: atom$TextEditor,\n      pane: atom$Pane,\n      index: number,\n    }) => mixed,\n  ): IDisposable;\n  // This should be removed soon anyway, it's currently deprecated.\n  paneContainer: Object;\n}\n\n/**\n * Extended Classes\n */\n\ndeclare class atom$BufferedNodeProcess { }\n\ndeclare class atom$BufferedProcess {\n  // Event Subscription\n  onWillThrowError(\n    callback: (errorObject: {error: Object, handle: mixed}) => mixed\n  ): IDisposable,\n  // Helper Methods\n  kill(): void,\n}\n\ndeclare class atom$Clipboard {\n  // Methods\n  write(text: string, metadata?: mixed): void,\n  read(): string,\n  readWithMetadata(): {\n    metadata: ?mixed,\n    text: string,\n  },\n}\n\ndeclare class atom$ContextMenuManager {\n  add(itemsBySelector: {[cssSelector: string]: Array<atom$ContextMenuItem>}): IDisposable,\n  itemSets: Array<atom$ContextMenuItemSet>,\n\n  // Undocumented methods\n  showForEvent(event: Event): void,\n  templateForEvent(event: Event): Array<Object>,\n}\n\ndeclare class atom$ContextMenuItemSet {\n  items: Array<atom$ContextMenuItem>,\n  selector: string,\n}\n\ntype atom$ContextMenuItem = {\n  command?: string,\n  created?: (event: MouseEvent) => void,\n  enabled?: boolean,\n  label?: string,\n  shouldDisplay?: (event: MouseEvent) => boolean,\n  submenu?: Array<atom$ContextMenuItem>,\n  type?: string,\n  visible?: boolean,\n};\n\ntype atom$Deserializer = {\n  name: string,\n  deserialize: (state: Object) => mixed,\n};\n\ndeclare class atom$DeserializerManager {\n  add(...deserializers: Array<atom$Deserializer>): IDisposable,\n  deserialize(state: Object, params?: Object): mixed,\n}\n\n// Apparently it can sometimes include a `code` property.\ndeclare class atom$GetEntriesError extends Error {\n  code?: string,\n}\n\ndeclare class atom$Directory {\n  constructor(dirname?: string): atom$Directory,\n\n  symlink: boolean,\n\n  // Construction\n  create(mode?: number): Promise<boolean>,\n\n  // Event Subscription\n  onDidChange(callback: () => mixed): IDisposable,\n\n  // Directory Metadata\n  isFile(): boolean,\n  isDirectory(): boolean,\n  exists():Promise<boolean>,\n\n  // Managing Paths\n  getPath(): string,\n  getBaseName(): string,\n  relativize(fullPath: string): string,\n\n  // Event Subscription\n  onDidRename(callback: () => void): IDisposable,\n  onDidDelete(callback: () => void): IDisposable,\n\n  // Traversing\n  getParent(): atom$Directory,\n  getFile(filename: string): atom$File,\n  getSubdirectory(dirname: string): atom$Directory,\n  getEntries(\n    callback: (\n      error: ?atom$GetEntriesError,\n      entries: ?Array<atom$Directory | atom$File>,\n    ) => mixed): void,\n  contains(path: string): boolean,\n}\n\n// These are the methods called on a file by atom-text-buffer\ninterface atom$Fileish {\n  existsSync(): boolean,\n  setEncoding(encoding: string): void,\n  getEncoding(): ?string,\n\n  onDidRename(callback: () => void): IDisposable,\n  onDidDelete(callback: () => void): IDisposable,\n  onDidChange(callback: () => void): IDisposable,\n  onWillThrowWatchError(callback: () => mixed): IDisposable,\n\n  getPath(): string,\n  getBaseName(): string,\n\n  createReadStream(): stream$Readable,\n  createWriteStream(): stream$Writable,\n}\n\ndeclare class atom$File /* implements atom$Fileish */ {\n  constructor(filePath?: string, symlink?: boolean): atom$File,\n\n  symlink: boolean,\n\n  // Construction\n  create(): Promise<boolean>,\n\n  // File Metadata\n  isFile(): boolean,\n  isDirectory(): boolean,\n  exists(): Promise<boolean>,\n  existsSync(): boolean,\n  setEncoding(encoding: string): void,\n  getEncoding(): string,\n\n  // Event Subscription\n  onDidRename(callback: () => void): IDisposable,\n  onDidDelete(callback: () => void): IDisposable,\n  onDidChange(callback: () => void): IDisposable,\n  onWillThrowWatchError(callback: () => mixed): IDisposable,\n\n  // Managing Paths\n  getPath(): string,\n  getBaseName(): string,\n\n  // Traversing\n  getParent(): atom$Directory,\n\n  // Reading and Writing\n  read(flushCache?: boolean): Promise<string>,\n  write(text: string): Promise<void>,\n  writeSync(text: string): void,\n  createReadStream(): stream$Readable,\n  createWriteStream(): stream$Writable,\n}\n\ndeclare class atom$GitRepository extends atom$Repository {\n  // Unofficial API.\n  statuses: {[filePath: string]: number},\n  // Return the `git-utils` async repo.\n  getRepo(): atom$GitRepositoryInternal,\n}\n\ndeclare class atom$Grammar {\n  name: string,\n  scopeName: string,\n  tokenizeLines(text: string): Array<Array<atom$GrammarToken>>,\n  tokenizeLine(line: string, ruleStack: mixed, firstLine: boolean): {\n    line: string,\n    tags: Array<number>,\n    // Dynamic property: invoking it will incur additional overhead\n    tokens: Array<atom$GrammarToken>,\n    ruleStack: mixed\n  },\n}\n\ntype atom$GrammarToken = {\n  value: string,\n  scopes: Array<string>,\n};\n\ndeclare class atom$GrammarRegistry {\n  // Event Subscription\n  onDidAddGrammar(callback: (grammar: atom$Grammar) => void): IDisposable,\n\n  // Managing Grammars\n  grammarForScopeName(scopeName: string): ?atom$Grammar,\n  removeGrammarForScopeName(scopeName: string): ?atom$Grammar,\n  loadGrammarSync(grammarPath: string): atom$Grammar,\n  selectGrammar(filePath: string, fileContents: string): atom$Grammar,\n  autoAssignLanguageMode(buffer: atom$TextBuffer): void,\n  assignLanguageMode(buffer: atom$TextBuffer, languageId: string): void,\n\n  // Extended\n  getGrammarScore(grammar: atom$Grammar, filePath: string, contents?: string): number,\n  forEachGrammar(callback: (grammar: atom$Grammar) => mixed): void,\n\n  // Private API\n  clear(): IDisposable,\n}\n\ndeclare class atom$HistoryManager {\n  removeProject(paths: Array<string>): void,\n  getProjects(): Array<atom$HistoryProject>,\n}\n\ndeclare class atom$HistoryProject {\n  paths: Array<string>;\n  lastOpened: Date;\n}\n\n// https://github.com/atom/atom-keymap/blob/18f00ac307de5770bb8f98958bd9a13ecffa9e68/src/key-binding.coffee\ndeclare class atom$KeyBinding {\n  cachedKeyups: ?Array<string>,\n  command: string,\n  index: number,\n  keystrokeArray : Array<string>,\n  keystrokeCount: number,\n  keystrokes: string,\n  priority: number,\n  selector: string,\n  source: string,\n  specificity: number,\n\n  matches(keystroke: string): boolean,\n  compare(keybinding: atom$KeyBinding): number,\n  getKeyups(): ?Array<string>,\n  matchesKeystrokes(userKeystrokes: Array<string>): boolean | 'exact' | 'partial' | 'pendingKeyup',\n}\n\ndeclare class atom$KeymapManager {\n  // Event Subscription\n  onDidMatchBinding(callback: (event: {\n    keystrokes: string,\n    binding: atom$KeyBinding,\n    keyboardEventTarget: HTMLElement,\n  }) => mixed): IDisposable,\n\n  onDidPartiallyMatchBinding(callback: (event: {\n    keystrokes: string,\n    partiallyMatchedBindings: atom$KeyBinding,\n    keyboardEventTarget: HTMLElement,\n  }) => mixed): IDisposable,\n\n  onDidFailToMatchBinding(callback: (event: {\n    keystrokes: string,\n    partiallyMatchedBindings: atom$KeyBinding,\n    keyboardEventTarget: HTMLElement,\n  }) => mixed): IDisposable,\n\n  onDidFailToReadFile(callback: (error: {\n    message: string,\n    stack: string,\n  }) => mixed): IDisposable,\n\n  // Adding and Removing Bindings\n  add(source: string, bindings: Object): IDisposable,\n  removeBindingsFromSource(source: string): void,\n\n  // Accessing Bindings\n  getKeyBindings(): Array<atom$KeyBinding>,\n  findKeyBindings(params: {\n    keystrokes?: string,\n    command?: string,\n    target?: HTMLElement,\n  }): Array<atom$KeyBinding>,\n\n  // Managing Keymap Files\n  loadKeymap(path: string, options?: {watch: boolean}): void,\n  watchKeymap(path: string): void,\n\n  // Managing Keyboard Events\n  handleKeyboardEvent(event: Event): void,\n  keystrokeForKeyboardEvent(event: Event): string,\n  getPartialMatchTimeout(): number,\n\n  static buildKeydownEvent(\n    key: string,\n    options: {\n      target: HTMLElement,\n      alt?: boolean,\n      cmd?: boolean,\n      ctrl?: boolean,\n      shift?: boolean,\n    },\n  ): Event,\n}\n\ndeclare class atom$MenuManager {\n  add(items: Array<Object>): IDisposable,\n  update(): void,\n\n  // Private API\n  template: Array<Object>,\n}\n\ntype atom$ProjectSpecification = {\n  originPath: string,\n  paths?: Array<string>,\n  config?: {[string]: mixed}\n};\n\ndeclare class atom$Project {\n  // Event Subscription\n  onDidChangePaths(callback: (projectPaths: Array<string>) => mixed): IDisposable,\n  onDidAddBuffer(callback: (buffer: atom$TextBuffer) => mixed): IDisposable,\n  onDidReplace((settings: atom$ProjectSpecification) => mixed): IDisposable,\n  observeBuffers(callback: (buffer: atom$TextBuffer) => mixed): IDisposable,\n  replace?: (newSettings: atom$ProjectSpecification) => void,\n  // Accessing the git repository\n  getRepositories(): Array<?atom$Repository>,\n  repositoryForDirectory(directory: atom$Directory): Promise<?atom$Repository>,\n\n  // Managing Paths\n  getPaths(): Array<string>,\n  addPath(projectPath: string, options?: {\n    emitEvent?: boolean,\n    exact?: boolean,\n    mustExist?: boolean,\n  }): void,\n  setPaths(paths: Array<string>): void,\n  removePath(projectPath: string): void,\n  getDirectories(): Array<atom$Directory>,\n  relativizePath(relativizePath?: string): Array<string>, // [projectPath: ?string, relativePath: string]\n  relativize(filePath: string): string,\n  contains(path: string): boolean,\n\n  // Private API\n  findBufferForPath(path: string): ?atom$TextBuffer,\n  addBuffer(buffer: atom$TextBuffer): void,\n  removeBuffer(buffer: atom$TextBuffer): void,\n  getBuffers(): Array<atom$TextBuffer>,\n}\n\ntype TextBufferScanIterator = (arg: {\n  match: Array<string>,\n  matchText: string,\n  range: atom$Range,\n  stop(): void,\n  replace(replacement: string): void,\n}) => void;\n\n// This happens to be a number but it would be better if the type could be entirely opaque. All you\n// need to know is that if something needs a checkpoint you should only pass it values received from\n// TextBuffer::createCheckpoint\ntype atom$TextBufferCheckpoint = number;\n\n// TextBuffer did-change/will-change\ntype atom$TextEditEvent = {\n  oldRange: atom$Range,\n  newRange: atom$Range,\n  oldText: string,\n  newText: string,\n};\n\ntype atom$AggregatedTextEditEvent = {\n  changes: Array<atom$TextEditEvent>,\n};\n\ndeclare class atom$LanguageMode {\n  getLanguageId(): string,\n}\n\ndeclare class atom$TextBuffer {\n  constructor(text?: string): atom$TextBuffer,\n  constructor(params?: {\n    filePath?: string,\n    text?: string,\n  }): atom$TextBuffer,\n\n  file: ?atom$File,\n\n  // Mixin\n  static deserialize: (state: Object, params: Object) => mixed,\n  static load: (file: string | atom$Fileish, params: Object) => Promise<atom$TextBuffer>,\n\n  setFile(file: atom$Fileish): void,\n\n  // Events\n  onWillChange(callback: () => mixed): IDisposable,\n  onDidChangeText(callback: (event: atom$AggregatedTextEditEvent) => mixed): IDisposable,\n  onDidStopChanging(callback: () => mixed): IDisposable,\n  onDidConflict(callback: () => mixed): IDisposable,\n  onDidChangeModified(callback: () => mixed): IDisposable,\n  onDidUpdateMarkers(callback: () => mixed): IDisposable,\n  onDidCreateMarker(callback: () => mixed): IDisposable,\n  onDidChangePath(callback: () => mixed): IDisposable,\n  onDidChangeEncoding(callback: () => mixed): IDisposable,\n  onWillSave(callback: () => mixed): IDisposable,\n  onDidSave(callback: (event: {path: string}) => mixed): IDisposable,\n  onDidDelete(callback: () => mixed): IDisposable,\n  onWillReload(callback: () => mixed): IDisposable,\n  onDidReload(callback: () => mixed): IDisposable,\n  onDidDestroy(callback: () => mixed): IDisposable,\n  onWillThrowWatchError(callback: () => mixed): IDisposable,\n\n  // File Details\n  // DO NOT USE (T21363106): Doesn't work with remote text buffers!\n  // setPath(filePath: string): void,\n  getPath(): ?string,\n  setEncoding(encoding: string): void,\n  getEncoding(): string,\n  getUri(): string,\n  getId(): string,\n  getLanguageMode(): atom$LanguageMode,\n\n  // Reading Text\n  isEmpty(): boolean,\n  getText(): string,\n  getTextInRange(range: atom$RangeLike): string,\n  getLineCount(): number,\n  getLines(): Array<string>,\n  getLastLine(): string,\n  lineForRow(row: number): string,\n  lineEndingForRow(row: number): string,\n  lineLengthForRow(row: number): number,\n  isRowBlank(row: number): boolean,\n  previousNonBlankRow(startRow: number): ?number,\n  nextNonBlankRow(startRow: number): ?number,\n\n  // Mutating Text\n  setText: (text: string) => atom$Range,\n  setTextInRange(range: atom$RangeLike, text: string, options?: Object): atom$Range,\n  setTextViaDiff(text: string): void,\n  insert(\n    position: atom$Point,\n    text: string,\n    options?: {\n      normalizeLineEndings?: boolean,\n      undo?: string,\n    },\n  ): atom$Range,\n  append(text: string, options: ?{\n    normalizeLineEndings?: boolean,\n    undo?: string,\n  }): atom$Range,\n  delete(range: atom$Range): atom$Range,\n  deleteRows(startRow: number, endRow: number): atom$Range,\n\n  // History\n  undo(): void,\n  redo(): void,\n  transact(fn: () => mixed, _: void): void,\n  transact(groupingInterval: number, fn: () => mixed): void,\n  clearUndoStack(): void,\n  createCheckpoint(): atom$TextBufferCheckpoint,\n  revertToCheckpoint(checkpoint: atom$TextBufferCheckpoint): boolean,\n  groupChangesSinceCheckpoint(checkpoint: atom$TextBufferCheckpoint): boolean,\n  // TODO describe the return type more precisely.\n  getChangesSinceCheckpoint(checkpoint: atom$TextBufferCheckpoint): Array<mixed>,\n\n  // Search And Replace\n  scan(regex: RegExp, iterator: TextBufferScanIterator): void,\n  scanInRange(regex: RegExp, range: atom$Range, iterator: TextBufferScanIterator): void,\n  backwardsScanInRange(regex: RegExp, range: atom$Range, iterator: TextBufferScanIterator): void,\n\n  // Buffer Range Details\n  getLastRow(): number,\n  getRange(): atom$Range,\n  rangeForRow(row: number, includeNewLine?: boolean): atom$Range,\n  getLength(): number,\n\n  // Position/Index mapping\n  characterIndexForPosition(position: atom$PointLike): number,\n  positionForCharacterIndex(index: number): atom$Point,\n\n  // Buffer Operations\n  reload(): void,\n  load(): Promise<void>,\n  save(): Promise<void>,\n\n  isInConflict(): boolean,\n  isModified(): boolean,\n\n  // Private APIs\n  cachedDiskContents: ?string,\n  emitter: atom$Emitter,\n  refcount: number,\n  loaded: boolean,\n  wasModifiedBeforeRemove: boolean,\n  finishLoading(): atom$TextBuffer,\n  updateCachedDiskContents(flushCache?: boolean, callback?: () => mixed): Promise<void>,\n  emitModifiedStatusChanged(changed: boolean): void,\n  destroy(): void,\n  isDestroyed(): boolean,\n  applyChange: () => void,\n  shouldDestroyOnFileDelete?: () => boolean,\n}\n\ndeclare class atom$Notification {\n  // Event Subscription\n  onDidDismiss(callback: () => mixed): IDisposable,\n  onDidDisplay(callback: () => mixed): IDisposable,\n\n  // Methods\n  getType(): string,\n  getMessage(): string,\n  getOptions(): Object,\n  dismiss(): void,\n  isDismissed(): boolean,\n}\n\ntype atom$NotificationButton = {\n  text: string,\n  className?: string,\n  onDidClick?: () => mixed,\n};\n\ntype atom$NotificationOptions = {\n  detail?: string,\n  dismissable?: boolean,\n  description?: string,\n  icon?: string,\n  stack?: string,\n  buttons?: Array<atom$NotificationButton>,\n};\n\ndeclare class atom$NotificationManager {\n  // Events\n  onDidAddNotification(callback: (notification: atom$Notification) => void): IDisposable,\n\n  // Adding Notifications\n  add(type: string, message: string, options?: atom$NotificationOptions): atom$Notification,\n  addSuccess(message: string, options?: atom$NotificationOptions): atom$Notification,\n  addInfo(message: string, options?: atom$NotificationOptions): atom$Notification,\n  addWarning(message: string, options?: atom$NotificationOptions): atom$Notification,\n  addError(message: string, options?: atom$NotificationOptions): atom$Notification,\n  addFatalError(message: string, options?: atom$NotificationOptions): atom$Notification,\n  addNotification(notification: atom$Notification): atom$Notification,\n\n  // Getting Notifications\n  getNotifications(): Array<atom$Notification>,\n}\n\n// The items in this declaration are available off of `require('atom')`.\n// This list is not complete.\ndeclare module 'atom' {\n  declare var BufferedNodeProcess: typeof atom$BufferedNodeProcess;\n  declare var BufferedProcess: typeof atom$BufferedProcess;\n  declare var CompositeDisposable: typeof atom$CompositeDisposable;\n  declare var Directory: typeof atom$Directory;\n  declare var Disposable: typeof atom$Disposable;\n  declare var Emitter: typeof atom$Emitter;\n  declare var File: typeof atom$File;\n  declare var GitRepository: typeof atom$GitRepository;\n  declare var Notification: typeof atom$Notification;\n  declare var Point: typeof atom$Point;\n  declare var Range: typeof atom$Range;\n  declare var TextBuffer: typeof atom$TextBuffer;\n  declare var TextEditor: typeof atom$TextEditor;\n}\n\n// Make sure that common types can be referenced without the `atom$` prefix\n// in type declarations.\ndeclare var Cursor: typeof atom$Cursor;\ndeclare var Panel: typeof atom$Panel;\ndeclare var TextEditor: typeof atom$TextEditor;\n\ntype atom$UnhandledErrorEvent = {\n  originalError: Object,\n  message: string,\n  url: string,\n  line: number,\n  column: number,\n};\n\n// The properties of this type match the properties of the `atom` global.\n// This list is not complete.\ntype AtomGlobal = {\n  // Properties\n  appVersion: string,\n  atomScriptMode: ?boolean, // Added by nuclide-atom-script.\n  clipboard: atom$Clipboard,\n  commands: atom$CommandRegistry,\n  config: atom$Config,\n  contextMenu: atom$ContextMenuManager,\n  applicationDelegate: atom$applicationDelegate,\n  deserializers: atom$DeserializerManager,\n  grammars: atom$GrammarRegistry,\n  history: atom$HistoryManager,\n  keymaps: atom$KeymapManager,\n  menu: atom$MenuManager,\n  notifications: atom$NotificationManager,\n  packages: atom$PackageManager,\n  styles: atom$StyleManager,\n  themes: atom$ThemeManager,\n  textEditors: atom$TextEditorRegistry,\n  tooltips: atom$TooltipManager,\n  views: atom$ViewRegistry,\n  workspace: atom$Workspace,\n  project: atom$Project,\n  devMode: boolean,\n\n  // Event Subscription\n  onWillThrowError(callback: (event: atom$UnhandledErrorEvent) => mixed): IDisposable,\n  onDidThrowError(callback: (event: atom$UnhandledErrorEvent) => mixed): IDisposable,\n  whenShellEnvironmentLoaded(callback: () => mixed): IDisposable,\n\n  // Atom Details\n  inDevMode(): boolean,\n  inSafeMode(): boolean,\n  inSpecMode(): boolean,\n  getVersion(): string,\n  isReleasedVersion(): boolean,\n  getWindowLoadTime(): number,\n\n  // This is an undocumented way to reach the Electron BrowserWindow.\n  // Use `electron.remote.getCurrentWindow` instead.\n  getCurrentWindow: void,\n\n  // Messaging the User\n  +confirm:\n    & ((\n      {\n        message: string,\n        detail?: string,\n        buttons?: Array<string>,\n      },\n      (number) => void,\n    ) => void)\n    // The synchronous form. You really shouldn't use this.\n    & (({\n        message: string,\n        detailedMessage?: string,\n        buttons?: Array<string> | {[buttonName: string]: () => mixed},\n      }) => ?number),\n\n  open(params: {\n    pathsToOpen?: Array<string>,\n    newWindow?: boolean,\n    devMode?: boolean,\n    safeMode?: boolean,\n  }): void,\n  reload(): void,\n  restartApplication(): void,\n\n  // Undocumented Methods\n  getConfigDirPath(): string,\n  showSaveDialogSync(options: Object): string,\n  loadState(): Promise<?Object>,\n  getLoadSettings(): Object,\n};\n\ndeclare var atom: AtomGlobal;\n\ntype RepositoryDidChangeStatusCallback = (event: {path: string, pathStatus: number}) => mixed;\ntype RepositoryLineDiff = {\n  oldStart: number,\n  newStart: number,\n  oldLines: number,\n  newLines: number,\n};\n\n// Taken from the interface of [`GitRepository`][1], which is also implemented by\n// `HgRepositoryClient`.\n//\n// [1]: https://github.com/atom/atom/blob/v1.7.3/src/git-repository.coffee\ndeclare class atom$Repository {\n  constructor(path: string, options?: {refreshOnWindowFocus?: boolean}): void,\n\n  // Event Subscription\n  onDidChangeStatus: (callback: RepositoryDidChangeStatusCallback) => IDisposable,\n  onDidChangeStatuses: (callback: () => mixed) => IDisposable,\n\n  // Repository Details\n  getType: () => string,\n  getPath: () => string,\n  getWorkingDirectory: () => string,\n  isProjectAtRoot: () => boolean,\n  relativize: (aPath: string) => string,\n  getOriginURL: (aPath: ?string) => ?string,\n\n  // Reading Status\n  isPathModified: (aPath: string) => boolean,\n  isPathNew: (aPath: string) => boolean,\n  isPathIgnored: (aPath: string) => boolean,\n  getDirectoryStatus: (aPath: string) => number,\n  getPathStatus: (aPath: string) => number,\n  getCachedPathStatus: (aPath: string) => ?number,\n  isStatusModified: (status: number) => boolean,\n  isStatusNew: (status: number) => boolean,\n  refreshStatus: () => Promise<void>,\n\n  // Retrieving Diffs\n  getDiffStats: (filePath: string) => {added: number, deleted: number},\n  getLineDiffs: (aPath: string, text: string) => Array<RepositoryLineDiff>,\n\n  // Checking Out\n  checkoutHead: (aPath: string) => boolean,\n  checkoutReference: (reference: string, create: boolean) => Promise<void>,\n\n  // Event Subscription\n  onDidDestroy(callback: () => mixed): IDisposable,\n  isDestroyed(): boolean,\n}\n\ndeclare class atom$GitRepositoryInternal {\n  // Reading Status\n  isStatusModified: (status: number) => boolean,\n  isStatusNew: (status: number) => boolean,\n  isStatusIgnored: (status: number) => boolean,\n  isStatusStaged: (status: number) => boolean,\n  isStatusDeleted: (status: number) => boolean,\n}\n\n// One of text or snippet is required.\n// TODO(hansonw): use a union + intersection type\ntype atom$AutocompleteSuggestion = {\n  text?: string,\n  snippet?: string,\n  displayText?: string,\n  replacementPrefix?: string,\n  type?: ?string,\n  leftLabel?: ?string,\n  leftLabelHTML?: ?string,\n  rightLabel?: ?string,\n  rightLabelHTML?: ?string,\n  className?: ?string,\n  iconHTML?: ?string,\n  description?: ?string,\n  descriptionMarkdown?: ?string,\n  descriptionMoreURL?: ?string,\n};\n\ntype atom$AutocompleteRequest = {\n  editor: TextEditor,\n  bufferPosition: atom$Point,\n  scopeDescriptor: atom$ScopeDescriptor,\n  prefix: string,\n  activatedManually?: boolean,\n};\n\ntype atom$AutocompleteProvider = {\n  +selector: string,\n  +getSuggestions: (\n    request: atom$AutocompleteRequest,\n  ) => Promise<?Array<atom$AutocompleteSuggestion>> | ?Array<atom$AutocompleteSuggestion>,\n  +getSuggestionDetailsOnSelect?: (\n    suggestion: atom$AutocompleteSuggestion\n  ) => Promise<?atom$AutocompleteSuggestion>,\n  +disableForSelector?: string,\n  +inclusionPriority?: number,\n  +excludeLowerPriority?: boolean,\n  +suggestionPriority?: number,\n  +filterSuggestions?: boolean,\n  +disposable?: () => void,\n  +onDidInsertSuggestion?: (\n    insertedSuggestion: atom$SuggestionInsertedRequest,\n  ) => void,\n};\n\ntype atom$SuggestionInsertedRequest = {\n  +editor: atom$TextEditor,\n  +triggerPosition: atom$Point,\n  +suggestion: atom$AutocompleteSuggestion,\n};\n\n// https://github.com/atom/autocomplete-plus/blob/master/README.md#the-watcheditor-api\ntype atom$AutocompleteWatchEditor = (\n  editor: atom$TextEditor,\n  labels?: Array<string>,\n) => IDisposable;\n\n// Undocumented API.\ndeclare class atom$Token {\n  value: string,\n  matchesScopeSelector(selector: string): boolean,\n}\n\ndeclare class atom$Selection {\n  clear(): void,\n  getText(): string,\n  getBufferRange(): atom$Range,\n  insertText(\n    text: string,\n    options?: {\n      select?: boolean,\n      autoIndent?: boolean,\n      autoIndentNewLine?: boolean,\n      autoDecreaseIdent?: boolean,\n      normalizeLineEndings?: boolean,\n      undo?: boolean,\n    },\n  ): string,\n}\n\ndeclare class atom$PanelContainer {\n  dock: atom$Dock,\n  element: HTMLElement,\n  emitter: atom$Emitter,\n  location: atom$PaneLocation,\n  panels: Array<atom$Panel>,\n  subscriptions: atom$CompositeDisposable,\n  viewRegistry: atom$ViewRegistry,\n\n  getPanels(): Array<atom$Panel>,\n};\n"
  },
  {
    "path": "decls/hyperclick.js",
    "content": "/* @flow */\n\ndeclare module 'atom-ide-ui/hyperclick' {\n  import type { Point, Range, TextEditor } from 'atom'\n\n  declare type HyperclickProvider = {\n    // Use this to provide a suggestion for single-word matches.\n    // Optionally set `wordRegExp` to adjust word-matching.\n    getSuggestionForWord?: (\n      textEditor: TextEditor,\n      text: string,\n      range: Range,\n    ) => Promise<?HyperclickSuggestion>,\n\n    wordRegExp?: RegExp,\n\n    // Use this to provide a suggestion if it can have non-contiguous ranges.\n    // A primary use-case for this is Objective-C methods.\n    getSuggestion?: (\n      textEditor: TextEditor,\n      position: Point,\n    ) => Promise<?HyperclickSuggestion>,\n\n    // The higher this is, the more precedence the provider gets. Defaults to 0.\n    priority?: number,\n\n    // Must be unique. Used for analytics.\n    providerName?: string,\n  };\n\n  declare type HyperclickSuggestion = {\n    // The range(s) to underline to provide as a visual cue for clicking.\n    range: ?Range | ?Array<Range>,\n\n    // The function to call when the underlined text is clicked.\n    callback: (() => mixed) | Array<{rightLabel?: string, title: string, callback: () => mixed}>,\n  };\n}\n"
  },
  {
    "path": "decls/jasmine-atom.js",
    "content": "/* @flow */\n\ndeclare function waitsForPromise(\n  optionsOrFunc: {timeout?: number, shouldReject?: boolean, label?: string} | () => Promise<mixed>,\n  func?: () => Promise<mixed>\n): void;\n"
  },
  {
    "path": "decls/jasmine.js",
    "content": "/* @flow */\n\ndeclare var jasmine: Object;\ndeclare function it(name: string, callback: (() => void)): void;\ndeclare function fit(name: string, callback: (() => void)): void;\ndeclare function spyOn(object: Object, property: string): Object;\ndeclare function expect(value: any): Object;\ndeclare function describe(name: string, callback: (() => void)): void;\ndeclare function fdescribe(name: string, callback: (() => void)): void;\ndeclare function beforeEach(callback: (() => void)): void;\ndeclare function afterEach(callback: (() => void)): void;\n"
  },
  {
    "path": "decls/linter.js",
    "content": "/* @flow */\n\ndeclare module 'linter' {\n  import type { Point, Range } from 'atom'\n\n  declare type LinterProvider = {\n  }\n\n  declare type Message = {\n    location: {\n      file: string,\n      position: Range,\n    },\n    reference: ?{\n      file: string,\n      position?: Point,\n    },\n    url?: string,\n    icon?: string,\n    excerpt: string,\n    severity: 'error' | 'warning' | 'info',\n    solutions?: Array<{\n      title?: string,\n      position: Range,\n      priority?: number,\n      currentText?: string,\n      replaceWith: string,\n    } | {\n      title?: string,\n      position: Range,\n      priority?: number,\n      apply: (() => any),\n    }>,\n    description?: string | (() => Promise<string> | string),\n    linterName?: string,\n  }\n}\n"
  },
  {
    "path": "decls/outline.js",
    "content": "/* @flow */\n\ndeclare module 'atom-ide-ui/outline' {\n  import type { Point, TextEditor } from 'atom'\n\n  declare type TokenKind =\n    | 'keyword'\n    | 'class-name'\n    | 'constructor'\n    | 'method'\n    | 'param'\n    | 'string'\n    | 'whitespace'\n    | 'plain'\n    | 'type';\n\n  declare type TextToken = {\n    kind: TokenKind,\n    value: string,\n  };\n\n  declare type TokenizedText = Array<TextToken>;\n\n  declare type OutlineTreeKind =\n    | 'file'\n    | 'module'\n    | 'namespace'\n    | 'package'\n    | 'class'\n    | 'method'\n    | 'property'\n    | 'field'\n    | 'constructor'\n    | 'enum'\n    | 'interface'\n    | 'function'\n    | 'variable'\n    | 'constant'\n    | 'string'\n    | 'number'\n    | 'boolean'\n    | 'array';\n\n  declare type OutlineTree = {\n    icon?: string, // from atom$Octicon (that type's not allowed over rpc so we use string)\n    kind?: OutlineTreeKind, // kind you can pass to the UI for theming\n\n    // Must be one or the other. If both are present, tokenizedText is preferred.\n    plainText?: string,\n    tokenizedText?: TokenizedText,\n\n    // If user has atom-ide-outline-view.nameOnly then representativeName is used instead.\n    representativeName?: string,\n\n    startPosition: Point,\n    endPosition?: Point,\n    landingPosition?: Point,\n    children: Array<OutlineTree>,\n  };\n\n  declare type Outline = {\n    outlineTrees: Array<OutlineTree>,\n  };\n\n  declare type OutlineProvider = {\n    name: string,\n    // If there are multiple providers for a given grammar, the one with the highest priority will be\n    // used.\n    priority: number,\n    grammarScopes: Array<string>,\n    updateOnEdit?: boolean,\n    getOutline(editor: TextEditor): Promise<?Outline>,\n  };\n}\n"
  },
  {
    "path": "lib/coverage-view.js",
    "content": "/* @flow */\n\nimport type { CoverageObject } from './types'\n\nclass CoverageView extends HTMLElement {\n  tooltipDisposable: ?IDisposable = null;\n\n  initialize(): void {\n    this.classList.add('inline-block')\n\n    this.addEventListener('click', () => {\n      atom.config.set('flow-ide.showUncovered', !atom.config.get('flow-ide.showUncovered'))\n    })\n  }\n\n  update(json: CoverageObject): void {\n    const covered: number = json.expressions.covered_count\n    const uncovered: number = json.expressions.uncovered_count\n    const total: number = covered + uncovered\n    const percent: number = total === 0 ? 100 : Math.round((covered / total) * 100)\n\n    this.textContent = `Flow Coverage: ${percent}%`\n\n    if (this.tooltipDisposable) {\n      this.tooltipDisposable.dispose()\n    }\n\n    this.classList.remove('flow-ide-hide')\n    this.tooltipDisposable = atom.tooltips.add(this, {\n      title: `Covered ${percent}% (${covered} of ${total} expressions)<br>Click to toggle uncovered code`,\n    })\n  }\n\n  reset() {\n    this.classList.add('flow-ide-hide')\n    this.textContent = ''\n    if (this.tooltipDisposable) {\n      this.tooltipDisposable.dispose()\n    }\n  }\n\n  destroy(): void {\n    if (this.tooltipDisposable) {\n      this.tooltipDisposable.dispose()\n    }\n  }\n}\n\nexport default document.registerElement('flow-ide-coverage', {\n  prototype: CoverageView.prototype,\n  extends: 'a',\n})\n"
  },
  {
    "path": "lib/helpers.js",
    "content": "/* @flow */\n\nimport { findCached, findCachedAsync } from 'atom-linter'\nimport * as Path from 'path'\n\nconst executable = process.platform === 'win32' ? 'flow.cmd' : 'flow'\n\nexport const defaultFlowFile = Path.resolve(__dirname, '..', 'vendor', '.flowconfig')\nexport const defaultFlowBinLocation = Path.join('node_modules', '.bin', executable)\nexport const grammarScopes = [\n  'source.js', 'source.jsx', 'source.js.jsx',\n  'source.flow', 'flow-javascript',\n]\n\nexport async function getExecutablePath(fileDirectory: string): Promise<string> {\n  return (\n    (atom.config.get('flow-ide.executablePath'): any) ||\n    await findCachedAsync(fileDirectory, defaultFlowBinLocation) ||\n    'flow'\n  )\n}\n\nexport function getExecutablePathSync(fileDirectory: string): string {\n  return (\n    (atom.config.get('flow-ide.executablePath'): any) ||\n    findCached(fileDirectory, defaultFlowBinLocation) ||\n    'flow'\n  )\n}\n\nexport async function getConfigFile(fileDirectory: string): Promise<?string> {\n  return findCachedAsync(fileDirectory, '.flowconfig')\n}\n"
  },
  {
    "path": "lib/index.js",
    "content": "/* @flow */\n\nimport { CompositeDisposable } from 'atom'\nimport type { TextEditor, Point, Range } from 'atom'\nimport { shouldTriggerAutocomplete } from 'atom-autocomplete'\nimport { exec } from 'atom-linter'\nimport type { HyperclickProvider, HyperclickSuggestion } from 'atom-ide-ui/hyperclick'\nimport type { OutlineProvider } from 'atom-ide-ui/outline'\nimport * as Path from 'path'\nimport type { Message } from 'linter'\nimport prettyPrintTypes from 'flow-language-server/lib/pkg/nuclide-flow-rpc/lib/prettyPrintTypes'\nimport score from 'sb-string_score'\nimport * as semver from 'semver'\nimport CoverageView from './coverage-view'\nimport * as LinterV1 from './linter/v1'\nimport * as LinterV2 from './linter/v2'\nimport * as Helpers from './helpers'\nimport { toOutline } from './outline'\nimport type { OutlineOptions } from './outline/types'\nimport type { CoverageObject, TypeAtPosObject } from './types'\n\nexport const INIT_MESSAGE = 'flow server'\nexport const RECHECKING_MESSAGE = 'flow is'\n\ntype Server = {\n  version: ?Promise<string>,\n}\nconst servers: Map<string, Server> = new Map()\n\nexport class Flow {\n  subscriptions: CompositeDisposable\n  executablePath: string\n  onlyIfAppropriate: boolean\n  hyperclickPriority: number\n  showUncovered: boolean\n  coverageView: any\n  coverages: WeakMap<TextEditor, CoverageObject>\n  statusBar: ?atom$StatusBarTile\n\n  activate() {\n    // eslint-disable-next-line global-require\n    require('atom-package-deps').install('flow-ide', true)\n\n    this.subscriptions = new CompositeDisposable()\n    this.subscriptions.add(atom.config.observe('flow-ide.executablePath', (executablePath) => {\n      this.executablePath = executablePath\n    }))\n    this.subscriptions.add(atom.config.observe('flow-ide.onlyIfAppropriate', (onlyIfAppropriate) => {\n      this.onlyIfAppropriate = onlyIfAppropriate\n    }))\n\n    let restartNotification\n    this.subscriptions.add(atom.config.observe('flow-ide.hyperclickPriority', (hyperclickPriority) => {\n      if (this.hyperclickPriority != null) {\n        if (hyperclickPriority !== this.hyperclickPriority && restartNotification === undefined) {\n          restartNotification = atom.notifications.addSuccess('Restart atom to update flow-ide priority?', {\n            dismissable: true,\n            buttons: [{\n              text: 'Restart',\n              onDidClick: () => atom.restartApplication(),\n            }],\n          })\n          restartNotification.onDidDismiss(() => { restartNotification = undefined })\n        }\n      }\n      this.hyperclickPriority = hyperclickPriority\n    }))\n    this.subscriptions.add(atom.config.observe('flow-ide.showUncovered', (showUncovered) => {\n      this.showUncovered = showUncovered\n      // lint again so that the coverage actually updates\n      const editor = atom.workspace.getActiveTextEditor()\n      if (!editor) {\n        return\n      }\n      const view = atom.views.getView(editor)\n      if (view) {\n        atom.commands.dispatch(view, 'linter:lint')\n      }\n    }))\n    this.subscriptions.add(atom.workspace.onDidChangeActivePaneItem((item: any): void => {\n      if (this.coverageView) {\n        const coverage = this.coverages.get(item)\n        if (coverage) {\n          this.coverageView.update(coverage)\n        } else {\n          this.coverageView.reset()\n        }\n      }\n    }))\n\n    this.coverages = new WeakMap()\n  }\n\n  async getConfigFile(fileDirectory: string): Promise<?string> {\n    const configFile = await Helpers.getConfigFile(fileDirectory)\n    if (configFile != null) {\n      const dir = Path.dirname(configFile)\n      if (!servers.has(dir)) {\n        servers.set(Path.dirname(configFile), { version: null })\n      }\n    }\n    return configFile\n  }\n\n  deactivate() {\n    this.subscriptions.dispose()\n    if (atom.config.get('flow-ide.stopServer')) {\n      this.stopServer()\n    }\n  }\n\n  stopServer() {\n    servers.forEach((server, rootDirectory) => {\n      const executable = Helpers.getExecutablePathSync(rootDirectory)\n      exec(executable, ['stop'], {\n        cwd: rootDirectory,\n        timeout: 60 * 1000,\n        detached: true,\n        ignoreExitCode: true,\n      }).catch(() => null) // <-- ignore all errors\n    })\n  }\n\n  async getVersion(configFile: string, executable: string): Promise<?string> {\n    const dir = Path.dirname(configFile)\n    const server = servers.get(dir)\n    if (server && server.version != null) {\n      return server.version\n    }\n\n    const p = exec(executable, ['version', '--json'], {\n      timeout: 60 * 1000,\n      uniqueKey: 'flow-ide-version',\n      ignoreExitCode: true,\n    }).then((result) => {\n      if (result === null) {\n        // reset the version because something went wrong...\n        servers.set(dir, { ...server, version: null })\n        return null\n      }\n      return JSON.parse(result).semver\n    })\n    .catch((error) => {\n      this.handleError(error, configFile)\n      return this.getVersion(configFile, executable)\n    })\n\n    servers.set(dir, { ...server, version: p })\n    return p\n  }\n\n  provideLinter(): Object[] {\n    return [this.provideStatusLinter(), this.provideCoverageLinter()]\n  }\n\n  provideStatusLinter(): Object {\n    const linter = {\n      name: 'Flow IDE',\n      scope: 'project',\n      grammarScopes: Helpers.grammarScopes,\n      lintsOnChange: false,\n      // eslint-disable-next-line arrow-parens\n      lint: async (textEditor: TextEditor) => {\n        const filePath = textEditor.getPath()\n        if (filePath == null) {\n          return []\n        }\n\n        const fileDirectory = Path.dirname(filePath)\n\n        let configFile = await this.getConfigFile(fileDirectory)\n        if (configFile == null) {\n          if (this.onlyIfAppropriate) {\n            return []\n          }\n          configFile = ((configFile: any): string)\n        }\n\n        const executable = await Helpers.getExecutablePath(fileDirectory)\n\n        const version = await this.getVersion(configFile, executable)\n        if (version == null) {\n          return null\n        }\n\n        return semver.gte(version, '0.66.0')\n          ? this.lintV2(textEditor, filePath, fileDirectory, configFile, executable)\n          : this.lintV1(textEditor, filePath, fileDirectory, configFile, executable)\n      },\n    }\n    return linter\n  }\n  async lintV1(textEditor: TextEditor, filePath: string, fileDirectory: string, configFile: string, executable: string) {\n    let result\n    try {\n      result = await exec(executable, ['status', '--json'], {\n        cwd: fileDirectory,\n        timeout: 60 * 1000,\n        uniqueKey: 'flow-ide-linter',\n        ignoreExitCode: true,\n      })\n    } catch (error) {\n      this.handleError(error, configFile)\n      return this.lintV1(textEditor, filePath, fileDirectory, configFile, executable)\n    }\n\n    if (result === null) {\n      return null\n    }\n    return LinterV1.toLinterMessages(result)\n  }\n  async lintV2(textEditor: TextEditor, filePath: string, fileDirectory: string, configFile: string, executable: string) {\n    let result\n    try {\n      result = await exec(executable, ['status', '--json', '--json-version=2'], {\n        cwd: fileDirectory,\n        timeout: 60 * 1000,\n        uniqueKey: 'flow-ide-linter',\n        ignoreExitCode: true,\n      })\n    } catch (error) {\n      this.handleError(error, configFile)\n      return this.lintV2(textEditor, filePath, fileDirectory, configFile, executable)\n    }\n\n    if (result === null) {\n      return null\n    }\n    return LinterV2.toLinterMessages(result, filePath)\n  }\n\n  provideCoverageLinter(): Object {\n    const linter = {\n      name: 'Flow IDE Coverage',\n      scope: 'file',\n      grammarScopes: Helpers.grammarScopes,\n      lintsOnChange: false,\n      lint: async (textEditor: TextEditor) => {\n        const filePath = textEditor.getPath()\n        if (filePath == null) {\n          return []\n        }\n\n        const fileDirectory = Path.dirname(filePath)\n\n        let configFile\n        if (this.onlyIfAppropriate) {\n          configFile = await this.getConfigFile(fileDirectory)\n          if (configFile == null) {\n            return []\n          }\n        }\n\n        const executable = await Helpers.getExecutablePath(fileDirectory)\n\n        let result: string\n        try {\n          result = await exec(executable, ['coverage', filePath, '--json'], {\n            cwd: fileDirectory,\n            timeout: 60 * 1000,\n            uniqueKey: 'flow-ide-coverage',\n            ignoreExitCode: true,\n          })\n          if (result === null) {\n            return null\n          }\n        } catch (error) {\n          this.handleError(error, configFile)\n          return linter.lint(textEditor)\n        }\n\n        const coverage: CoverageObject = JSON.parse(result)\n        this.coverages.set(textEditor, coverage)\n        if (this.coverageView) {\n          this.coverageView.update(coverage)\n        }\n        return this.showUncovered ? this.toCoverageLinterMessages(coverage) : []\n      },\n    }\n    return linter\n  }\n\n  provideAutocomplete(): Object {\n    const provider = {\n      selector: Helpers.grammarScopes.map(x => (x.includes('.') ? `.${x}` : x)).join(', '),\n      disableForSelector: '.comment',\n      inclusionPriority: 100,\n      // eslint-disable-next-line arrow-parens\n      getSuggestions: async (params) => {\n        const { editor, bufferPosition, activatedManually } = params\n        let prefix = params.prefix\n        const filePath = editor.getPath()\n        if (!filePath) {\n          return []\n        }\n\n        const fileDirectory = Path.dirname(filePath)\n        const fileContents = this.injectPosition(editor.getText(), editor, bufferPosition)\n        let flowOptions = ['autocomplete', '--json', filePath]\n\n        let configFile = await this.getConfigFile(fileDirectory)\n        if (configFile == null) {\n          if (this.onlyIfAppropriate) {\n            return []\n          }\n          configFile = ((configFile: any): string)\n          flowOptions = ['autocomplete', '--root', Helpers.defaultFlowFile, '--json', filePath]\n        }\n\n        // NOTE: Fix for class properties autocompletion\n        if (prefix === '.') {\n          prefix = ''\n        }\n\n        if (!shouldTriggerAutocomplete({ activatedManually, bufferPosition, editor })) {\n          return []\n        }\n\n        let result\n        try {\n          result = await exec(await Helpers.getExecutablePath(fileDirectory), flowOptions, {\n            cwd: fileDirectory,\n            stdin: fileContents,\n            timeout: 60 * 1000,\n            uniqueKey: 'flow-ide-autocomplete',\n            ignoreExitCode: true,\n          })\n          if (result === null) {\n            return []\n          }\n        } catch (error) {\n          this.handleError(error, configFile)\n          return provider.getSuggestions(params)\n        }\n\n        return this.toAutocompleteSuggestions(result, prefix)\n      },\n    }\n    return provider\n  }\n  injectPosition(text: string, editor: Object, bufferPosition: Object) {\n    const characterIndex = editor.getBuffer().characterIndexForPosition(bufferPosition)\n    return text.slice(0, characterIndex) + 'AUTO332' + text.slice(characterIndex)\n  }\n  toAutocompleteSuggestions(contents: string, prefix: string) {\n    if (contents.slice(0, 1) !== '{') {\n      // Invalid server response\n      return []\n    }\n\n    const parsed = JSON.parse(contents)\n    const hasPrefix = prefix.trim().length\n    const suggestions = parsed.result.map((suggestion) => {\n      const isFunction = suggestion.func_details !== null && suggestion.func_details !== undefined\n      let text = null\n      let snippet = null\n      let displayText = null\n      let description = null\n\n      if (isFunction) {\n        const functionParams = suggestion.func_details.params\n        displayText = `${suggestion.name}(${functionParams.map(value => value.name).join(', ')})`\n        const snippetArgs = functionParams.map((value, i) => `\\${${i + 1}:${value.name}}`).join(', ')\n        snippet = `${suggestion.name}(${snippetArgs})$${functionParams.length + 1}`\n\n        const params = functionParams.map(param => param.name + (param.type ? `: ${param.type}` : ''))\n        const match = suggestion.type.match(/\\(.*?\\) => (.*)/)\n        const returnType = match ? `=> ${match[1]}` : ''\n\n        description = `(${params.join(', ')}) ${returnType}`\n      } else {\n        text = suggestion.name\n      }\n\n      return {\n        text,\n        type: isFunction ? 'function' : 'property',\n        score: hasPrefix ? score(suggestion.name, prefix) : 1,\n        snippet,\n        leftLabel: isFunction ? 'function' : this.getType(suggestion),\n        displayText,\n        replacementPrefix: prefix,\n        description,\n      }\n    })\n    return suggestions.sort((a, b) => b.score - a.score).filter(item => item.score)\n  }\n  getType(value: { value: string, type: string }) {\n    return value.type && value.type.substr(0, 1) === '{' ? 'Object' : value.type || 'any'\n  }\n\n  provideHyperclick(): HyperclickProvider {\n    const provider = {\n      priority: this.hyperclickPriority,\n      grammarScopes: Helpers.grammarScopes,\n      getSuggestionForWord: async (textEditor: TextEditor, text: string, range: Range): Promise<?HyperclickSuggestion> => {\n        const filePath = textEditor.getPath()\n        if (filePath == null) {\n          return null\n        }\n\n        const fileDirectory = Path.dirname(filePath)\n        const configFile = await this.getConfigFile(fileDirectory)\n        if (configFile == null) {\n          return null\n        }\n\n        const pos = this.adjustPosition(range.start, textEditor)\n        const flowOptions = [\n          'get-def',\n          '--json',\n          '--path=' + filePath,\n          pos.row + 1,\n          pos.column + 1,\n        ]\n\n        let result\n        try {\n          result = await exec(await Helpers.getExecutablePath(fileDirectory), flowOptions, {\n            cwd: fileDirectory,\n            stdin: textEditor.getText(),\n            ignoreExitCode: true,\n            timeout: 60 * 1000,\n            uniqueKey: 'flow-ide-hyperclick',\n          })\n          if (result === null) {\n            return null\n          }\n        } catch (error) {\n          this.handleError(error, configFile)\n          return provider.getSuggestionForWord(textEditor, text, range)\n        }\n        const jsonResult = JSON.parse(result)\n\n        if (!jsonResult.path) {\n          return null\n        }\n\n        return {\n          range,\n          callback() {\n            atom.workspace.open(jsonResult.path, { searchAllPanes: true }).then((editor) => {\n              editor.setCursorBufferPosition([jsonResult.line - 1, jsonResult.start - 1])\n            })\n          },\n        }\n      },\n    }\n    return provider\n  }\n  adjustPosition(pos: atom$Point, editor: TextEditor) {\n    // Flow fails to determine the position if the cursor is at the end of a word\n    // e.g. \"path.dirname ()\"\n    //                   ↑ the cursor is here, between \"dirname\" and \"(\"\n    // In order to avoid this problem we have to check whether the char\n    // at the given position is considered a part of an identifier.\n    // If not step back 1 char as it might contain a valid identifier.\n    const char = editor.getTextInBufferRange([\n      pos,\n      pos.translate([0, 1]),\n    ])\n    const nonWordChars = editor.getNonWordCharacters(pos)\n    if (nonWordChars.indexOf(char) >= 0 || /\\s/.test(char)) {\n      return pos.translate([0, -1])\n    }\n    return pos\n  }\n\n  provideOutlines(): OutlineProvider {\n    const outlineOptions: OutlineOptions = {\n      showKeywords: {\n        export: false,\n        default: false,\n        const: false,\n        var: false,\n        let: false,\n        class: false,\n        function: false,\n        type: false,\n      },\n      showFunctionArgs: false,\n    }\n    this.subscriptions.add(atom.config.observe('flow-ide.outline', (outline) => {\n      outlineOptions.showKeywords.export = outline.showExport\n      outlineOptions.showFunctionArgs = outline.showFunctionArgs\n    }))\n\n    const provider = {\n      name: 'flow-ide',\n      priority: 1,\n      grammarScopes: Helpers.grammarScopes,\n      updateOnEdit: true,\n      getOutline: async (editor: TextEditor) => {\n        const filePath = editor.getPath()\n        if (filePath == null) {\n          return null\n        }\n\n        const fileDirectory = Path.dirname(filePath)\n        const configFile = await this.getConfigFile(fileDirectory)\n        if (configFile == null) {\n          return null\n        }\n\n        const flowOptions = ['ast']\n\n        let result\n        try {\n          result = await exec(await Helpers.getExecutablePath(fileDirectory), flowOptions, {\n            cwd: fileDirectory,\n            stdin: editor.getText(),\n            timeout: 60 * 1000,\n            uniqueKey: 'flow-ide-ast',\n            ignoreExitCode: true,\n          })\n          if (result === null) {\n            return { outlineTrees: [] }\n          }\n        } catch (error) {\n          this.handleError(error, configFile)\n          return provider.getOutline(editor)\n        }\n\n        return toOutline(result, outlineOptions)\n      },\n    }\n    return provider\n  }\n\n  consumeDatatip(datatipService: any) {\n    const provider = {\n      providerName: 'flow-ide',\n      priority: 1,\n      grammarScopes: Helpers.grammarScopes,\n      datatip: async (editor: TextEditor, point: Point): Promise<any> => {\n        const filePath = editor.getPath()\n        if (filePath == null) {\n          return null\n        }\n\n        const fileDirectory = Path.dirname(filePath)\n        const configFile = await this.getConfigFile(fileDirectory)\n        if (configFile == null) {\n          return null\n        }\n\n        const flowOptions = [\n          'type-at-pos',\n          '--json',\n          '--path=' + filePath,\n          point.row + 1,\n          point.column + 1,\n        ]\n\n        let result\n        try {\n          result = await exec(await Helpers.getExecutablePath(fileDirectory), flowOptions, {\n            cwd: fileDirectory,\n            stdin: editor.getText(),\n            timeout: 60 * 1000,\n            uniqueKey: 'flow-ide-type-at-pos',\n            ignoreExitCode: true,\n          })\n          if (result === null) {\n            return null\n          }\n        } catch (error) {\n          this.handleError(error, configFile)\n          return provider.datatip(editor, point)\n        }\n\n        return this.toDatatip(editor, point, result)\n      },\n    }\n    this.subscriptions.add(datatipService.addProvider(provider))\n  }\n  toDatatip(editor: TextEditor, point: Point, result: string) {\n    const parsed: TypeAtPosObject = JSON.parse(result)\n\n    const { type, loc } = parsed\n    if (type === '(unknown)') {\n      return null\n    }\n\n    return {\n      range: LinterV1.locationToRange(loc),\n      markedStrings: [{\n        type: 'snippet',\n        grammar: editor.getGrammar(),\n        value: prettyPrintTypes(type),\n      }],\n    }\n  }\n\n  consumeStatusBar(statusBar: atom$StatusBar): void {\n    this.coverageView = new CoverageView()\n    this.coverageView.initialize()\n    this.statusBar = statusBar.addLeftTile({ item: this.coverageView, priority: 10 })\n    this.subscriptions.add({\n      dispose: () => {\n        if (this.statusBar) {\n          this.statusBar.destroy()\n        }\n      },\n    })\n  }\n\n  handleError(error: { message: string, code: string }, configFile: ?string) {\n    if (error.message.indexOf(INIT_MESSAGE) !== -1 && typeof configFile === 'string') {\n      servers.set(Path.dirname(configFile), { version: null })\n    }\n    if (error.message.indexOf(INIT_MESSAGE) !== -1 || error.message.indexOf(RECHECKING_MESSAGE) !== -1) {\n      // continue...\n    } else if (error.code === 'ENOENT') {\n      throw new Error('Unable to find `flow` executable.')\n    } else {\n      throw error\n    }\n  }\n\n  toCoverageLinterMessages(coverage: CoverageObject): Message[] {\n    return coverage.expressions.uncovered_locs.map(loc => ({\n      severity: 'info',\n      location: LinterV1.toLinterLocation(loc),\n      excerpt: 'Uncovered code',\n      reference: null,\n    }))\n  }\n}\n"
  },
  {
    "path": "lib/language-client.js",
    "content": "/* @flow */\n\nimport { TextEditor } from 'atom'\nimport { AutoLanguageClient } from '@lloiser/atom-languageclient'\nimport { findCachedAsync } from 'atom-linter'\nimport { spawn } from 'child_process'\nimport * as Path from 'path'\nimport * as Helpers from './helpers'\n\nexport class FlowLanguageClient extends AutoLanguageClient {\n  getGrammarScopes() { return Helpers.grammarScopes }\n  getLanguageName() { return 'Flowtype' }\n  getServerName() { return 'flow' }\n\n  async startServerProcess(projectPath: string) {\n    return spawn(\n      await Helpers.getExecutablePath(projectPath),\n      ['lsp'],\n      { cwd: projectPath },\n    )\n  }\n\n  async determineProjectPath(textEditor: TextEditor) {\n    const path = textEditor.getPath()\n    if (path == null) {\n      return null\n    }\n\n    const configFile: ?string = await findCachedAsync(path, '.flowconfig')\n    if (configFile != null) {\n      return Path.dirname(configFile)\n    }\n    return null\n  }\n}\n"
  },
  {
    "path": "lib/linter/v1/index.js",
    "content": "/* @flow */\n\nimport { Range } from 'atom'\nimport type { Message } from 'linter'\n\nimport { mainMessageOfError, prettyPrintError } from './pretty'\nimport type { StatusMessage, StatusObject } from './types'\nimport type { Location } from '../../types'\n\nexport function locationToRange({ start, end }: Location): Range {\n  return new Range(\n    [start.line - 1, start.column - 1],\n    [end.line - 1, end.column],\n  )\n}\nexport function toLinterLocation(loc: Location) {\n  return {\n    file: loc.source,\n    position: locationToRange(loc),\n  }\n}\n\nfunction toLinterReference(messages: StatusMessage[]) {\n  for (let i = 1, length = messages.length; i < length; i++) {\n    const message = messages[i]\n    if (message.loc) {\n      return {\n        file: message.loc.source,\n        position: locationToRange(message.loc).start,\n      }\n    }\n  }\n  return null\n}\n\nexport function toLinterMessages(contents: string): Message[] {\n  const parsed: StatusObject = JSON.parse(contents)\n  if (!Array.isArray(parsed.errors) || !parsed.errors.length) {\n    return []\n  }\n\n  return parsed.errors.map((error) => {\n    const mainMsg = mainMessageOfError(error)\n    const { loc } = mainMsg\n    if (!loc) {\n      return null\n    }\n\n    let excerpt = error.message.map(msg => msg.descr).join(' ')\n    if (error.operation && mainMsg === error.operation) {\n      excerpt = error.operation.descr + ' ' + excerpt\n    }\n\n    return {\n      severity: error.level === 'error' ? 'error' : 'warning',\n      location: toLinterLocation(loc),\n      excerpt,\n      description: prettyPrintError(error),\n      reference: toLinterReference(error.message),\n    }\n  }).filter(Boolean)\n}\n"
  },
  {
    "path": "lib/linter/v1/pretty.js",
    "content": "/* @flow */\n\n// Note: the following code is based on\n// https://github.com/facebook/flow/blob/v0.47.0/tsrc/flowResult.js\n// and adjusted to output nicely formatted markdown.\n\nimport { format } from 'util'\nimport type { StatusError, StatusExtra, StatusMessage } from './types'\nimport type { Location } from '../../types'\n\nconst regexMarkdownChars = /[*#()[\\]<>_]/g\nconst escapeChars = { '<': '&lt;', '>': '&gt;' }\n\nfunction fileUrl({ source, start }: Location): string {\n  // build a link that can be opened by the linter ui.\n  // e.g. atom://linter?file=<path>&row=<number>&column=<number>\n  const params = ['file=' + encodeURIComponent(source)]\n  if (start.line > 0) {\n    params.push('row=' + (start.line - 1))\n    if (start.column > 0) {\n      params.push('column=' + (start.column - 1))\n    }\n  }\n  return 'atom://linter?' + params.join('&')\n}\nfunction linterLink(loc: Location, text: string) {\n  return '[' + text + '](' + fileUrl(loc) + ')'\n}\nfunction fileLink(loc: Location): string {\n  return linterLink(loc, atom.project.relativize(loc.source))\n}\nfunction lineLink(loc: Location): string {\n  return linterLink(loc, loc.start.line.toString())\n}\n\nexport function mainMessageOfError(error: StatusError): StatusMessage {\n  return error.operation || error.message[0]\n}\n\nexport function mainLocOfError(error: StatusError): ?Location {\n  return mainMessageOfError(error).loc\n}\n\nfunction getExtraMessages(extra: ?StatusExtra[]): StatusMessage[] {\n  if (extra) {\n    const messages = extra.reduce((acc, current) => {\n      const childrenMessages = getExtraMessages(current.children)\n      return acc.concat(current.message, childrenMessages)\n    }, [])\n    messages.forEach((message) => {\n      const msg = message\n      msg.indent = (msg.indent || 0) + 2\n    })\n    return messages\n  }\n  return []\n}\n\nfunction getTraceReasons(trace: ?StatusMessage[]): StatusMessage[] {\n  if (trace != null && trace.length > 0) {\n    return ([{ descr: 'Trace:', type: 'Blame' }].concat(trace): any)\n  }\n  return []\n}\n\nfunction mkComment(descr: string): StatusMessage {\n  return ({ descr, type: 'Comment' }: any)\n}\n\nfunction getOpReason(op: ?StatusMessage): StatusMessage[] {\n  if (op) {\n    return [\n      op,\n      mkComment('Error:'),\n    ]\n  }\n  return []\n}\n\nfunction getHeader(mainLoc: ?Location, kind: string, level: string): StatusMessage[] {\n  let line = -1\n  let filename = ''\n  if (mainLoc) {\n    const { source, start } = mainLoc\n    line = start.line\n    if (source) {\n      filename = fileLink(mainLoc)\n    }\n  }\n  if (!filename) {\n    filename = format('%s:%d', '[No file]', line)\n  }\n\n  let prefix = ''\n  if (kind === 'internal' && level === 'error') {\n    prefix = 'Internal error (see logs):\\n'\n  } else if (mainLoc && mainLoc.type === 'LibFile') {\n    if (kind === 'parse' && level === 'error') {\n      prefix = 'Library parse error:\\n'\n    } else if (kind === 'infer') {\n      prefix = 'Library type error:\\n'\n    }\n  }\n\n  return [mkComment(format('%s%s', prefix, filename))]\n}\n\nfunction prettyPrintMessage(mainFile: string, { context, descr, loc, indent }: StatusMessage): string {\n  const indentation = ' '.repeat(indent || 0)\n  if (loc) {\n    const startCol = loc.start.column - 1\n    let contextStr = indentation\n    if (context !== null && typeof context === 'string') {\n      // On Windows this might have \\r\n      let ctx = context.trimRight()\n      // Replace tabs with spaces\n      ctx = ctx.replace(/\\t/g, ' ')\n      // escape certain chars that serve a purpose in markdown\n      ctx = ctx.replace(regexMarkdownChars, m => escapeChars[m] || '\\\\' + m)\n\n      const { line } = loc.start\n      const prefix = line < 100 ? ' '.repeat(3 - line.toString().length) : ''\n\n      let padding = Array((prefix + line + ': ').length + 1).join(' ')\n      if (ctx.length > startCol) {\n        padding += ctx.substr(0, startCol).replace(/[^\\t ]/g, ' ')\n      }\n\n      const underlineSize = line === loc.end.line ?\n        Math.max(1, loc.end.column - startCol) :\n        1\n      const underline = '^'.repeat(underlineSize)\n\n      contextStr = format(\n        '%s%s%s: %s\\n%s%s%s ',\n        indentation,\n        prefix,\n        lineLink(loc),\n        ctx,\n        indentation,\n        padding,\n        underline,\n      )\n    }\n    const seeAnotherFile = loc.source === mainFile ?\n      '' :\n      format(\n        '. See%s: %s',\n        loc.type === 'LibFile' ? ' lib' : '',\n        fileLink(loc),\n      )\n    return format('%s%s%s', contextStr, descr, seeAnotherFile)\n  }\n  return indentation + descr\n}\n\nexport function mergedMessagesOfError(error: StatusError): StatusMessage[] {\n  const { level, kind, message, operation, trace, extra } = error\n  const mainLoc = mainLocOfError(error)\n  const messages = [].concat(\n    getHeader(mainLoc, kind, level),\n    getOpReason(operation),\n    message,\n    getExtraMessages(extra),\n    getTraceReasons(trace),\n  )\n  // Merge comments into blames\n  return messages.reduce((acc, msg) => {\n    const { descr, loc, type } = msg\n    if (loc || acc.length === 0 || type === 'Blame') {\n      acc.push(msg)\n    } else if (descr !== 'Error:') {\n      const prev = acc[acc.length - 1]\n      prev.descr = prev.descr === '' ? descr : format('%s. %s', prev.descr, descr)\n    }\n    return acc\n  }, [])\n}\n\nexport function prettyPrintError(error: StatusError): string {\n  const mainLoc = mainLocOfError(error)\n  const mainFile = (mainLoc && mainLoc.source) || '[No file]'\n  const messages = mergedMessagesOfError(error)\n  return '<div style=\"white-space: pre-wrap\">' + messages.map(msg => prettyPrintMessage(mainFile, msg)).join('\\n') + '</div>'\n}\n"
  },
  {
    "path": "lib/linter/v1/types.js",
    "content": "/* @flow */\n\nimport type { Location } from '../../types'\n\nexport type StatusMessage = {\n  context: ?string,\n  descr: string,\n  type: string,\n  loc?: Location,\n  path: string,\n  line: number,\n  endline: number,\n  start: number,\n  end: number,\n  indent?: number,\n}\n\nexport type StatusExtra = {\n  message: StatusMessage[],\n  children?: StatusExtra[],\n}\n\nexport type StatusError = {\n  kind: string,\n  level: string,\n  message: StatusMessage[],\n  operation?: StatusMessage,\n  extra?: StatusExtra[],\n  trace?: StatusMessage[],\n}\n\nexport type StatusObject = {\n  flowVersion: string,\n  errors: StatusError[],\n  passed: boolean,\n}\n"
  },
  {
    "path": "lib/linter/v2/index.js",
    "content": "/* @flow */\n\nimport { Range } from 'atom'\nimport type { Message } from 'linter'\n\nimport type { Location, MessageMarkup, InlineMarkup, ReferenceLocs, StatusResult } from './types'\n\nfunction locationToRange({ start, end }: Location): Range {\n  return new Range(\n    [start.line - 1, start.column - 1],\n    [end.line - 1, end.column],\n  )\n}\n\nfunction locactionToLinterLocation(loc: Location) {\n  return {\n    file: loc.source,\n    position: locationToRange(loc),\n  }\n}\n\nfunction plainText(messages: InlineMarkup[], references: ReferenceLocs): string {\n  return messages.map((message) => {\n    switch (message.kind) {\n      case 'Text':\n        return message.text\n\n      case 'Code':\n        return message.text\n\n      case 'Reference': {\n        const ref = references[message.referenceId]\n        if (!ref) {\n          return ''\n        }\n        return plainText(message.message, references)\n      }\n\n      default:\n        return ''\n    }\n  }).join('')\n}\n\nfunction fileUrl(loc: Location, path: string): string {\n  // build a link that can be opened by the linter ui.\n  // e.g. atom://linter?file=<path>&row=<number>&column=<number>\n  let { source } = loc\n  if (source === '-') {\n    source = path\n  }\n  const params = ['file=' + encodeURIComponent(source)]\n  const { start } = loc\n  if (start.line > 0) {\n    params.push('row=' + (start.line - 1))\n    if (start.column > 0) {\n      params.push('column=' + (start.column - 1))\n    }\n  }\n  return 'atom://linter?' + params.join('&')\n}\n\nfunction markup(messages: MessageMarkup, references: ReferenceLocs, path: string): string {\n  if (Array.isArray(messages)) {\n    return messages.map((message) => {\n      switch (message.kind) {\n        case 'Text':\n          return message.text\n\n        case 'Code':\n          return '`' + message.text + '`'\n\n        case 'Reference': {\n          const ref = references[message.referenceId]\n          if (!ref) {\n            return ''\n          }\n          return `[${markup(message.message, references, path)}](${fileUrl(ref, path)})`\n        }\n\n        default:\n          return ''\n      }\n    }).join('')\n  }\n\n  if (messages.kind === 'UnorderedList') {\n    // `messages.message` is already part of the excerpt\n    return messages.items.map(msg => markup(msg, references, path))\n      .map(msg => ` - ${msg}`).join('\\n')\n  }\n  return ''\n}\n\nexport function toLinterMessages(json: string, path: string): Message[] {\n  const result: StatusResult = JSON.parse(json)\n\n  if (result.passed && result.errors.length === 0) {\n    return []\n  }\n\n  return result.errors.map((err) => {\n    const location = locactionToLinterLocation(err.primaryLoc)\n    const severity = err.level\n    const { messageMarkup } = err\n    if (Array.isArray(messageMarkup)) {\n      return {\n        location,\n        excerpt: plainText(messageMarkup, err.referenceLocs),\n        severity,\n        reference: null,\n      }\n    }\n\n    return {\n      location,\n      excerpt: plainText(messageMarkup.message, err.referenceLocs),\n      severity,\n      description: markup(messageMarkup, err.referenceLocs, path),\n      reference: null,\n    }\n  })\n}\n"
  },
  {
    "path": "lib/linter/v2/types.js",
    "content": "/* @flow */\n\nexport type Position = {\n  line: number,\n  column: number,\n  offset: number\n}\n\nexport type Location = {\n  source: string,\n  type: \"SourceFile\", // TODO: others?\n  start: Position,\n  end: Position,\n  context: string\n}\n\nexport type ReferenceId = string\n\nexport type ReferenceLocs = { [id: ReferenceId]: Location }\n\n// CodeMarkup represents text that originates from the actual source code.\n// Typically should be rendered in a fixed-width font (e.g. in markdown using `...`)\nexport type CodeMarkup = {\n  kind: \"Code\",\n  text: string\n}\n// TextMarkup just represents text, most likely used in combination with other markups\nexport type TextMarkup = {\n  kind: \"Text\",\n  text: string\n}\n// ReferenceMarkup can be used to reference to source code (e.g. via links)\nexport type ReferenceMarkup = {\n  kind: \"Reference\",\n  referenceId: ReferenceId,\n  message: InlineMarkup[] // eslint-disable-line no-use-before-define\n}\n\n// UnorderedListMarkup represents a `message` and a list of bullet points (`items`)\nexport type UnorderedListMarkup = {\n  kind: 'UnorderedList',\n  message: InlineMarkup[], // eslint-disable-line no-use-before-define\n  items: MessageMarkup[] // eslint-disable-line no-use-before-define\n}\n\n// InlineMarkup represents a single line of text\nexport type InlineMarkup = CodeMarkup | TextMarkup | ReferenceMarkup\n// BlockMarkup represents a larger block of text.\n// Typically this is suitable for linter `description`\nexport type BlockMarkup = UnorderedListMarkup\n\nexport type MessageMarkup =\n  InlineMarkup[] |\n  BlockMarkup\n\nexport type Error = {\n  kind: \"lint\" | \"infer\",\n  level: \"warning\" | \"error\",\n  suppressions: [], // TODO: I probably have to turn on some suppressions to see this...\n  classic: boolean,\n  primaryLoc: Location,\n  rootLoc: ?Location,\n  messageMarkup: MessageMarkup,\n  referenceLocs: ReferenceLocs\n}\n\nexport type StatusResult = {\n  flowVersion: string, // e.g 0.66.0\n  jsonVersion: \"2\",\n  errors: Error[],\n  passed: true\n};\n"
  },
  {
    "path": "lib/main.js",
    "content": "/* @flow */\n\nconst useLSP = atom.config.get('flow-ide.useLSP')\n\n// notify to restart if the value changes\natom.config.onDidChange('flow-ide.useLSP', () => {\n  const buttons = [{\n    text: 'Restart',\n    onDidClick () { return atom.restartApplication() },\n  }]\n  atom.notifications.addInfo('Changing this value requires a restart of atom.', { dismissable: true, buttons })\n})\n\n// possible improvement: check if flow really supports lsp\n\nif (useLSP === true) {\n  // eslint-disable-next-line global-require\n  const { FlowLanguageClient } = require('./language-client')\n  module.exports = new FlowLanguageClient()\n} else {\n  // eslint-disable-next-line global-require\n  const { Flow } = require('./index')\n  module.exports = new Flow()\n}\n"
  },
  {
    "path": "lib/outline/index.js",
    "content": "/* @flow */\n\nimport type { Outline } from 'atom-ide-ui/outline'\nimport { astToOutline } from './parse'\nimport type { OutlineOptions } from './types'\n\nexport function toOutline(result: string, options: OutlineOptions): Outline {\n  const parsed = JSON.parse(result)\n  return astToOutline(options, parsed)\n}\n"
  },
  {
    "path": "lib/outline/parse.js",
    "content": "/* @flow */\n\n// NOTE: the following code is based on\n// https://github.com/flowtype/flow-language-server/blob/fbd1bc3/src/pkg/nuclide-flow-rpc/lib/astToOutline.js\n// and adjusted to toggle keywords and function arguments\n\nimport { Point } from 'atom'\nimport invariant from 'assert'\nimport type { Outline, OutlineTree, TokenizedText } from 'atom-ide-ui/outline'\nimport * as Text from './text'\nimport type { OutlineOptions, Extent } from './types'\n\nfunction exportDeclaration(\n  options: OutlineOptions,\n  item: Object,\n  extent: Extent,\n  isDefault: boolean,\n): ?OutlineTree {\n  const tree = itemToTree(options, item.declaration) // eslint-disable-line\n  if (tree == null) {\n    return null\n  }\n  // Flow always has tokenizedText\n  invariant(tree.tokenizedText != null)\n\n  const tokenizedText = []\n  if (options.showKeywords.export) {\n    tokenizedText.push(Text.keyword('export'), Text.whitespace(' '))\n  }\n  if (options.showKeywords.default && isDefault) {\n    tokenizedText.push(Text.keyword('default'), Text.whitespace(' '))\n  }\n  tokenizedText.push(...tree.tokenizedText)\n\n  return {\n    kind: tree.kind,\n    tokenizedText,\n    representativeName: tree.representativeName,\n    children: tree.children,\n    ...extent,\n  }\n}\n\nfunction declarationsTokenizedText(options: OutlineOptions, declarations: Array<Object>): TokenizedText {\n  return declarations.reduce((text, decl, i, decls) => {\n    text.push(...declarationReducer(options, decl)) // eslint-disable-line\n    if (i < decls.length - 1) {\n      text.push(Text.plain(','))\n      text.push(Text.whitespace(' '))\n    }\n    return text\n  }, [])\n}\n\nfunction declarationReducer(\n  options: OutlineOptions,\n  decl: Object,\n): TokenizedText {\n  if (!decl) {\n    // special case: array patterns can contain `null` elements\n    // which means that this value is simply ignored.\n    return []\n  }\n\n  switch (decl.type) {\n    case 'Identifier':\n      return [Text.param(decl.name)]\n    case 'ObjectPattern':\n      return [\n        Text.plain('{'),\n        ...declarationsTokenizedText(options, decl.properties),\n        Text.plain('}'),\n      ]\n    case 'ArrayPattern':\n      return [\n        Text.plain('['),\n        ...declarationsTokenizedText(options, decl.elements),\n        Text.plain(']'),\n      ]\n    case 'AssignmentPattern':\n      return declarationReducer(options, decl.left)\n    case 'RestElement':\n    case 'RestProperty':\n      return [\n        Text.plain('...'),\n        ...declarationReducer(options, decl.argument),\n      ]\n    case 'Property':\n      return declarationReducer(options, decl.value)\n    default:\n      throw new Error(`encountered unexpected argument type ${decl.type}`)\n  }\n}\n\nfunction getExtent(item: Object): Extent {\n  return {\n    startPosition: new Point(\n      // It definitely makes sense that the lines we get are 1-based and the columns are\n      // 0-based... convert to 0-based all around.\n      item.loc.start.line - 1,\n      item.loc.start.column,\n    ),\n    endPosition: new Point(item.loc.end.line - 1, item.loc.end.column),\n  }\n}\n\nfunction functionOutline(\n  options: OutlineOptions,\n  name: string,\n  params: Array<Object>,\n  extent: Extent,\n): OutlineTree {\n  const tokenizedText = []\n\n  if (options.showKeywords.function || !name) {\n    tokenizedText.push(Text.keyword('function'))\n    if (name) {\n      tokenizedText.push(Text.whitespace(' '))\n    }\n  }\n  if (name) {\n    tokenizedText.push(Text.method(name))\n  }\n  if (options.showFunctionArgs) {\n    tokenizedText.push(\n      Text.plain('('),\n      ...declarationsTokenizedText(options, params),\n      Text.plain(')'),\n    )\n  }\n\n  return {\n    kind: 'function',\n    tokenizedText,\n    representativeName: name,\n    children: [],\n    ...extent,\n  }\n}\n\nfunction typeAliasOutline(options: OutlineOptions, typeAliasExpression: Object): OutlineTree {\n  invariant(typeAliasExpression.type === 'TypeAlias' || typeAliasExpression.type === 'DeclareTypeAlias')\n  const name = typeAliasExpression.id.name\n\n  const tokenizedText = []\n  if (options.showKeywords.type) {\n    tokenizedText.push(Text.keyword('type'), Text.whitespace(' '))\n  }\n  tokenizedText.push(Text.type(name))\n\n  return {\n    kind: 'interface',\n    tokenizedText,\n    representativeName: name,\n    children: [],\n    ...getExtent(typeAliasExpression),\n  }\n}\n\nfunction isModuleExports(left: Object): boolean {\n  return (\n    left.type === 'MemberExpression' &&\n    left.object.type === 'Identifier' &&\n    left.object.name === 'module' &&\n    left.property.type === 'Identifier' &&\n    left.property.name === 'exports'\n  )\n}\n\nfunction moduleExportsPropertyOutline(options: OutlineOptions, property: Object): ?OutlineTree {\n  invariant(property.type === 'Property')\n  if (property.key.type !== 'Identifier') {\n    return null\n  }\n  const propName = property.key.name\n\n  if (property.shorthand) {\n    // This happens when the shorthand `{ foo }` is used for `{ foo: foo }`\n    return {\n      kind: 'method',\n      tokenizedText: [Text.string(propName)],\n      representativeName: propName,\n      children: [],\n      ...getExtent(property),\n    }\n  }\n\n  if (\n    property.value.type === 'FunctionExpression' ||\n    property.value.type === 'ArrowFunctionExpression'\n  ) {\n    const tokenizedText = [Text.method(propName)]\n    if (options.showFunctionArgs) {\n      tokenizedText.push(\n        Text.plain('('),\n        ...declarationsTokenizedText(options, property.value.params),\n        Text.plain(')'),\n      )\n    }\n\n    return {\n      kind: 'method',\n      tokenizedText,\n      representativeName: propName,\n      children: [],\n      ...getExtent(property),\n    }\n  }\n\n  return {\n    kind: 'field',\n    tokenizedText: [Text.string(propName), Text.plain(':')],\n    representativeName: propName,\n    children: [],\n    ...getExtent(property),\n  }\n}\n\nfunction moduleExportsOutline(options: OutlineOptions, assignmentStatement: Object): ?OutlineTree {\n  invariant(assignmentStatement.type === 'AssignmentExpression')\n\n  const left = assignmentStatement.left\n  if (!isModuleExports(left)) {\n    return null\n  }\n\n  const right = assignmentStatement.right\n  if (right.type !== 'ObjectExpression') {\n    return null\n  }\n  const properties: Array<Object> = right.properties\n  return {\n    kind: 'module',\n    tokenizedText: [Text.plain('module.exports')],\n    children: properties.map(prop => moduleExportsPropertyOutline(options, prop)).filter(Boolean),\n    ...getExtent(assignmentStatement),\n  }\n}\n\n// Return the function name as written as a string. Intended to stringify patterns like `describe`\n// and `describe.only` even though `describe.only` is a MemberExpression rather than an Identifier.\nfunction getFunctionName(callee: Object): ?string {\n  switch (callee.type) {\n    case 'Identifier':\n      return callee.name\n    case 'MemberExpression':\n      if (\n        callee.object.type !== 'Identifier' ||\n        callee.property.type !== 'Identifier'\n      ) {\n        return null\n      }\n      return `${callee.object.name}.${callee.property.name}`\n    default:\n      return null\n  }\n}\n\nfunction isDescribe(functionName: string): boolean {\n  switch (functionName) {\n    case 'describe':\n    case 'fdescribe':\n    case 'ddescribe':\n    case 'xdescribe':\n    case 'describe.only':\n    case 'describe.skip':\n    case 'test.cb':\n    case 'test.serial':\n    case 'test.todo':\n    case 'test.failing':\n    case 'test':\n    case 'test.concurrent':\n    case 'test.only':\n    case 'test.skip':\n    case 'suite':\n    case 'suite.only':\n    case 'suite.skip':\n    case 'xtest':\n    case 'xtest.concurrent':\n    case 'xtest.only':\n    case 'xtest.skip':\n      return true\n    default:\n      return false\n  }\n}\n\nfunction isIt(functionName: string): boolean {\n  switch (functionName) {\n    case 'it':\n    case 'fit':\n    case 'iit':\n    case 'pit':\n    case 'xit':\n    case 'it.only':\n    case 'it.skip':\n      return true\n    default:\n      return false\n  }\n}\n\n/** If the given AST Node is a string literal, return its literal value. Otherwise return null */\nfunction getStringLiteralValue(literal: ?Object): ?string {\n  if (literal == null) {\n    return null\n  }\n  if (literal.type !== 'Literal') {\n    return null\n  }\n  const value = literal.value\n  if (typeof value !== 'string') {\n    return null\n  }\n  return value\n}\n\nfunction getFunctionBody(fn: ?Object): ?Array<Object> {\n  if (fn == null) {\n    return null\n  }\n  if (\n    fn.type !== 'ArrowFunctionExpression' &&\n    fn.type !== 'FunctionExpression'\n  ) {\n    return null\n  }\n  return fn.body.body\n}\n\nfunction specOutline(\n  options: OutlineOptions,\n  expressionStatement: Object,\n  describeOnly: boolean = false,\n): ?OutlineTree {\n  const expression = expressionStatement.expression\n  if (expression.type !== 'CallExpression') {\n    return null\n  }\n  const functionName = getFunctionName(expression.callee)\n  if (functionName == null) {\n    return null\n  }\n  if (!isDescribe(functionName)) {\n    if (describeOnly || !isIt(functionName)) {\n      return null\n    }\n  }\n  const description = getStringLiteralValue(expression.arguments[0])\n  const specBody = getFunctionBody(expression.arguments[1])\n  if (description == null || specBody == null) {\n    return null\n  }\n  let children\n  if (isIt(functionName)) {\n    children = []\n  } else {\n    children =\n      specBody\n        .filter(item => item.type === 'ExpressionStatement')\n        .map(item => specOutline(options, item))\n        .filter(Boolean)\n  }\n  return {\n    kind: 'function',\n    tokenizedText: [Text.method(functionName), Text.whitespace(' '), Text.string(description)],\n    representativeName: description,\n    children,\n    ...getExtent(expressionStatement),\n  }\n}\n\nfunction topLevelExpressionOutline(options: OutlineOptions, expressionStatement: Object): ?OutlineTree {\n  switch (expressionStatement.expression.type) {\n    case 'CallExpression':\n      return specOutline(options, expressionStatement, /* describeOnly */ true)\n    case 'AssignmentExpression':\n      return moduleExportsOutline(options, expressionStatement.expression)\n    default:\n      return null\n  }\n}\n\nfunction variableDeclaratorOutline(\n  options: OutlineOptions,\n  declarator: Object,\n  kind: string,\n  extent: Extent,\n): ?OutlineTree {\n  if (\n    declarator.init != null &&\n    (declarator.init.type === 'FunctionExpression' ||\n      declarator.init.type === 'ArrowFunctionExpression')\n  ) {\n    return functionOutline(options, declarator.id.name, declarator.init.params, extent)\n  }\n\n  const { id } = declarator\n\n  const tokenizedText = []\n  if (options.showKeywords[kind]) {\n    tokenizedText.push(\n      Text.keyword(kind),\n      Text.whitespace(' '),\n    )\n  }\n  tokenizedText.push(...declarationsTokenizedText(options, [id]))\n\n  const representativeName = id.type === 'Identifier' ? id.name : undefined\n  return {\n    kind: kind === 'const' ? 'constant' : 'variable',\n    tokenizedText,\n    representativeName,\n    children: [],\n    ...extent,\n  }\n}\n\nfunction variableDeclarationOutline(options: OutlineOptions, declaration: Object): ?OutlineTree {\n  // If there are multiple var declarations in one line, just take the first.\n  return variableDeclaratorOutline(\n    options,\n    declaration.declarations[0],\n    declaration.kind,\n    getExtent(declaration),\n  )\n}\n\nfunction itemToTree(options: OutlineOptions, item: Object): ?OutlineTree {\n  if (item == null) {\n    return null\n  }\n  const extent = getExtent(item)\n  switch (item.type) {\n    case 'FunctionDeclaration':\n    case 'ArrowFunctionExpression':\n      return functionOutline(\n        options,\n        item.id != null ? item.id.name : '',\n        item.params,\n        extent,\n      )\n    case 'ClassDeclaration':\n    case 'ClassExpression': {\n      let representativeName\n      if (item.id != null) {\n        representativeName = item.id.name\n      }\n\n      const tokenizedText = []\n      if (options.showKeywords.class || !representativeName) {\n        tokenizedText.push(Text.keyword('class'))\n      }\n      if (representativeName) {\n        if (options.showKeywords.class) {\n          tokenizedText.push(Text.whitespace(' '))\n        }\n        tokenizedText.push(Text.className(representativeName))\n      }\n      return {\n        kind: 'class',\n        tokenizedText,\n        representativeName,\n        children: itemsToTrees(options, item.body.body), // eslint-disable-line\n        ...extent,\n      }\n    }\n    case 'ClassProperty': {\n      if (item.value && item.value.type === 'ArrowFunctionExpression') {\n        const tokenizedText = [Text.method(item.key.name)]\n        if (options.showFunctionArgs) {\n          tokenizedText.push(\n            Text.plain('('),\n            ...declarationsTokenizedText(options, item.value.params),\n            Text.plain(')'),\n          )\n        }\n        return {\n          kind: 'method',\n          tokenizedText,\n          representativeName: item.key.name,\n          children: [],\n          ...extent,\n        }\n      }\n      return {\n        kind: 'property',\n        tokenizedText: [Text.param(item.key.name)],\n        representativeName: item.key.name,\n        children: [],\n        ...extent,\n      }\n    }\n    case 'MethodDefinition': {\n      const tokenizedText = [Text.method(item.key.name)]\n      if (options.showFunctionArgs) {\n        tokenizedText.push(\n          Text.plain('('),\n          ...declarationsTokenizedText(options, item.value.params),\n          Text.plain(')'),\n        )\n      }\n      return {\n        kind: 'method',\n        tokenizedText,\n        representativeName: item.key.name,\n        children: [],\n        ...extent,\n      }\n    }\n    case 'ExportDeclaration':\n    case 'ExportNamedDeclaration':\n      return exportDeclaration(options, item, extent, Boolean(item.default))\n    case 'ExportDefaultDeclaration':\n      return exportDeclaration(options, item, extent, true)\n    case 'ExpressionStatement':\n      return topLevelExpressionOutline(options, item)\n    case 'DeclareTypeAlias':\n    case 'TypeAlias':\n      return typeAliasOutline(options, item)\n    case 'VariableDeclaration':\n      return variableDeclarationOutline(options, item)\n    default:\n      return null\n  }\n}\n\nfunction itemsToTrees(options: OutlineOptions, items: Array<Object>): Array<OutlineTree> {\n  return items.map(item => itemToTree(options, item)).filter(Boolean)\n}\n\nexport function astToOutline(options: OutlineOptions, ast: Object): Outline {\n  return {\n    outlineTrees: itemsToTrees(options, ast.body),\n  }\n}\n"
  },
  {
    "path": "lib/outline/text.js",
    "content": "/* @flow */\n\nimport type { TokenKind, TextToken } from 'atom-ide-ui/outline'\n\nfunction buildToken(kind: TokenKind, value: string): TextToken {\n  return { kind, value }\n}\n\nexport function keyword(value: string): TextToken {\n  return buildToken('keyword', value)\n}\n\nexport function className(value: string): TextToken {\n  return buildToken('class-name', value)\n}\n\nexport function constructor(value: string): TextToken {\n  return buildToken('constructor', value)\n}\n\nexport function method(value: string): TextToken {\n  return buildToken('method', value)\n}\n\nexport function param(value: string): TextToken {\n  return buildToken('param', value)\n}\n\nexport function string(value: string): TextToken {\n  return buildToken('string', value)\n}\n\nexport function whitespace(value: string): TextToken {\n  return buildToken('whitespace', value)\n}\n\nexport function plain(value: string): TextToken {\n  return buildToken('plain', value)\n}\n\nexport function type(value: string): TextToken {\n  return buildToken('type', value)\n}\n"
  },
  {
    "path": "lib/outline/types.js",
    "content": "/* @flow */\n\nimport type { Point } from 'atom'\n\nexport type OutlineOptions = {\n  showKeywords: {\n    export: boolean,\n    default: boolean,\n    const: boolean,\n    var: boolean,\n    let: boolean,\n    class: boolean,\n    function: boolean,\n    type: boolean,\n  },\n  showFunctionArgs: boolean\n};\n\nexport type Extent = {|\n  startPosition: Point,\n  endPosition: Point,\n|};\n"
  },
  {
    "path": "lib/types.js",
    "content": "/* @flow */\n\nexport type Position = {\n  line: number,\n  column: number,\n  offset: number,\n  end: number,\n}\n\nexport type Location = {\n  source: string,\n  type: string,\n  start: Position,\n  end: Position,\n}\n\nexport type CoverageObject = {\n  expressions: {\n    covered_count: number,\n    uncovered_count: number,\n    uncovered_locs: Location[],\n  }\n}\n\nexport type TypeAtPosObject = {\n  type: string,\n  reasons: Array<{\n    desc: string,\n    loc: Location,\n    path: string,\n    line: number,\n    endline: number,\n    start: number,\n    end: number,\n  }>,\n  loc: Location,\n  path: string,\n  line: number,\n  endline: number,\n  start: number,\n  end: number,\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"flow-ide\",\n  \"private\": true,\n  \"version\": \"1.13.0\",\n  \"description\": \"Flowtype support in Atom without any bloatware\",\n  \"main\": \"lib/main.js\",\n  \"scripts\": {\n    \"test\": \"apm test\",\n    \"lint\": \"eslint .\"\n  },\n  \"package-deps\": [\n    \"linter\",\n    \"hyperclick\"\n  ],\n  \"engines\": {\n    \"atom\": \">=1.4.0 <2.0.0\"\n  },\n  \"providedServices\": {\n    \"autocomplete.provider\": {\n      \"versions\": {\n        \"2.0.0\": \"provideAutocomplete\"\n      }\n    },\n    \"hyperclick.provider\": {\n      \"versions\": {\n        \"0.0.0\": \"provideHyperclick\"\n      }\n    },\n    \"linter\": {\n      \"versions\": {\n        \"2.0.0\": \"provideLinter\"\n      }\n    },\n    \"outline-view\": {\n      \"versions\": {\n        \"0.1.0\": \"provideOutlines\"\n      }\n    },\n    \"code-actions\": {\n      \"versions\": {\n        \"0.1.0\": \"provideCodeActions\"\n      }\n    },\n    \"code-format.range\": {\n      \"versions\": {\n        \"0.1.0\": \"provideCodeFormat\"\n      }\n    },\n    \"code-highlight\": {\n      \"versions\": {\n        \"0.1.0\": \"provideCodeHighlight\"\n      }\n    },\n    \"definitions\": {\n      \"versions\": {\n        \"0.1.0\": \"provideDefinitions\"\n      }\n    },\n    \"find-references\": {\n      \"versions\": {\n        \"0.1.0\": \"provideFindReferences\"\n      }\n    }\n  },\n  \"consumedServices\": {\n    \"datatip\": {\n      \"versions\": {\n        \"0.1.0\": \"consumeDatatip\"\n      }\n    },\n    \"status-bar\": {\n      \"versions\": {\n        \"^1.0.0\": \"consumeStatusBar\"\n      }\n    },\n    \"console\": {\n      \"versions\": {\n        \"0.1.0\": \"consumeConsole\"\n      }\n    },\n    \"atom-ide-busy-signal\": {\n      \"versions\": {\n        \"0.1.0\": \"consumeBusySignal\"\n      }\n    },\n    \"linter-indie\": {\n      \"versions\": {\n        \"2.0.0\": \"consumeLinterV2\"\n      }\n    },\n    \"signature-help\": {\n      \"versions\": {\n        \"0.1.0\": \"consumeSignatureHelp\"\n      }\n    }\n  },\n  \"atomTranspilers\": [\n    {\n      \"glob\": \"{lib,spec}/**/*.js\",\n      \"transpiler\": \"atom-babel6-transpiler\",\n      \"options\": {\n        \"cacheKeyFiles\": [\n          \"package.json\",\n          \".babelrc\"\n        ]\n      }\n    }\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/steelbrain/flow-ide.git\"\n  },\n  \"keywords\": [\n    \"flow\",\n    \"flowtype\",\n    \"ide\",\n    \"javascript\"\n  ],\n  \"author\": \"steelbrain\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/steelbrain/flow-ide/issues\"\n  },\n  \"homepage\": \"https://github.com/steelbrain/flow-ide#readme\",\n  \"dependencies\": {\n    \"@lloiser/atom-languageclient\": \"^0.10.1\",\n    \"atom-autocomplete\": \"^1.0.0\",\n    \"atom-babel6-transpiler\": \"^1.2.0\",\n    \"atom-linter\": \"^10.0.0\",\n    \"atom-package-deps\": \"^4.4.1\",\n    \"babel-plugin-transform-class-properties\": \"^6.24.1\",\n    \"babel-plugin-transform-flow-strip-types\": \"^6.22.0\",\n    \"babel-plugin-transform-object-rest-spread\": \"^6.26.0\",\n    \"babel-preset-env\": \"^1.7.0\",\n    \"flow-language-server\": \"^0.2.3\",\n    \"sb-string_score\": \"^0.1.20\",\n    \"semver\": \"^5.5.0\"\n  },\n  \"devDependencies\": {\n    \"eslint-config-steelbrain\": \"^3.0.1\",\n    \"eslint-plugin-flowtype\": \"^2.33.0\",\n    \"flow-bin\": \"^0.91.0\"\n  },\n  \"configSchema\": {\n    \"useLSP\": {\n      \"title\": \"Use the Language Server Protocol to talk to flow, otherwise call flow\",\n      \"description\": \"Changing this value requires a restart of atom.\",\n      \"type\": \"boolean\",\n      \"default\": false,\n      \"order\": 1\n    },\n    \"executablePath\": {\n      \"description\": \"Path to `flow` executable\",\n      \"type\": \"string\",\n      \"default\": \"\",\n      \"order\": 2\n    },\n    \"onlyIfAppropriate\": {\n      \"title\": \"Only activate when .flowconfig exists\",\n      \"type\": \"boolean\",\n      \"default\": true,\n      \"order\": 3\n    },\n    \"stopServer\": {\n      \"title\": \"Stop flow server when disabling this plugin or closing atom\",\n      \"type\": \"boolean\",\n      \"default\": true,\n      \"order\": 4\n    },\n    \"showUncovered\": {\n      \"title\": \"Show uncovered code in the editor\",\n      \"type\": \"boolean\",\n      \"default\": false,\n      \"order\": 5\n    },\n    \"hyperclickPriority\": {\n      \"description\": \"Priority to use for hyperclick provider (requires restart)\",\n      \"type\": \"integer\",\n      \"default\": 0,\n      \"order\": 6\n    },\n    \"outline\": {\n      \"title\": \"Outline\",\n      \"type\": \"object\",\n      \"order\": 7,\n      \"properties\": {\n        \"showExport\": {\n          \"title\": \"Show 'export' keyword\",\n          \"description\": \"Shows a leading 'export' keyword if the variable, function or type is exported\",\n          \"type\": \"boolean\",\n          \"default\": true\n        },\n        \"showFunctionArgs\": {\n          \"title\": \"Show function arguments\",\n          \"type\": \"boolean\",\n          \"default\": true\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "spec/linter/v2/index-spec.js",
    "content": "/* @flow */\n/* eslint-env jasmine */\n\nimport { findCached, exec } from 'atom-linter'\nimport * as LinterV2 from '../../../lib/linter/v2'\n\nfunction fileUrl(file, row, column) {\n  return `atom://linter?file=${encodeURIComponent(file)}&row=${row}&column=${column}`\n}\n\ndescribe('linter/v2', function() {\n  const flowBin = findCached(__dirname, 'node_modules/.bin/flow')\n\n  describe('toLinterMessages', function() {\n    it('only excerpt', function() {\n      const code = `// @flow\n\n      type Human = { name: string }\n\n      function getAge({ age }): number {\n        return age\n      }\n\n      const p1: Human = { name: 'John Doe' }\n      getAge(p1)`\n\n      /* flow status\n        Cannot call getAge with p1 bound to the first parameter because property age is missing in Human [1].\n\n              7| }\n              8|\n         [1]  9| const p1: Human = { name: 'John Doe' }\n             10| getAge(p1)\n             11|\n      */\n\n      let result = null\n      waitsForPromise(async () => {\n        result = await exec(flowBin, ['check-contents', '--json', '--json-version=2'], { stdin: code })\n\n        const messages = LinterV2.toLinterMessages(result, __filename)\n        expect(messages.length).toEqual(1)\n        expect(messages[0].excerpt).toEqual('Cannot call getAge with p1 bound to the first parameter because property age is missing in Human.')\n      })\n    })\n\n    it('with description', function() {\n      const code = `// @flow\n\n      type Human = { name: string }\n      type Man = Human & { gender: 'male' }\n\n      function getAge({ age }): number {\n        return age\n      }\n\n      const p1: Man = { name: 'John Doe', gender: 'male' }\n      getAge(p1)`\n\n      /* flow status\n        Cannot call getAge with p1 bound to the first parameter because:\n         - Either property age is missing in Human [1].\n         - Or property age is missing in object type [2].\n\n         [1][2]  4| type Man = Human & { gender: 'male' }\n                 5|\n                 6| function getAge({ age }): number {\n                 7|   return age\n                 8| }\n                 9|\n                10| const p1: Man = { name: 'John Doe', gender: 'male' }\n                11| getAge(p1)\n                12|\n      */\n\n      let result = null\n      waitsForPromise(async () => {\n        result = await exec(flowBin, ['check-contents', '--json', '--json-version=2'], { stdin: code })\n\n        const messages = LinterV2.toLinterMessages(result, __filename)\n        expect(messages.length).toEqual(1)\n        expect(messages[0].excerpt).toEqual('Cannot call getAge with p1 bound to the first parameter because:')\n        expect(messages[0].description).toEqual(\n          ` - Either property \\`age\\` is missing in [\\`Human\\`](${fileUrl(__filename, 3, 17)}).\\n` +\n          ` - Or property \\`age\\` is missing in [object type](${fileUrl(__filename, 3, 25)}).`,\n        )\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "spec/outline/parse-sample-ast.js",
    "content": "/* @flow */\n\nconst lc = (line, column) => ({ line, column })\nconst loc = (start, end, source = null) => ({ start, end, source })\n\n/*\ndeclare type LocalType = {\n  foo: string,\n  bar: string\n}\n*/\nexport const typeDecl = {\n  type: 'Program',\n  loc: loc(lc(3, 0), lc(6, 1)),\n  range: [13, 70],\n  body: [{\n    type: 'DeclareTypeAlias',\n    loc: loc(lc(3, 0), lc(6, 1)),\n    range: [13, 70],\n    id: {\n      type: 'Identifier',\n      loc: loc(lc(3, 13), lc(3, 22)),\n      range: [26, 35],\n      name: 'LocalType',\n      optional: false,\n    },\n    right: {\n      type: 'ObjectTypeAnnotation',\n      loc: loc(lc(3, 25), lc(6, 1)),\n      range: [38, 70],\n      exact: false,\n      properties: [{\n        type: 'ObjectTypeProperty',\n        loc: loc(lc(4, 2), lc(4, 13)),\n        range: [42, 53],\n        key: {\n          type: 'Identifier',\n          loc: loc(lc(4, 2), lc(4, 5)),\n          range: [42, 45],\n          name: 'foo',\n          optional: false,\n        },\n        value: {\n          type: 'StringTypeAnnotation',\n          loc: loc(lc(4, 7), lc(4, 13)),\n          range: [47, 53],\n        },\n        optional: false,\n        static: false,\n        kind: 'init',\n      }, {\n        type: 'ObjectTypeProperty',\n        loc: loc(lc(5, 2), lc(5, 13)),\n        range: [57, 68],\n        key: {\n          type: 'Identifier',\n          loc: loc(lc(5, 2), lc(5, 5)),\n          range: [57, 60],\n          name: 'bar',\n          optional: false,\n        },\n        value: {\n          type: 'StringTypeAnnotation',\n          loc: loc(lc(5, 7), lc(5, 13)),\n          range: [62, 68],\n        },\n        optional: false,\n        static: false,\n        kind: 'init',\n      }],\n    },\n  }],\n}\n\n/*\nexport type ExportedType = {\n  foo: string\n}\n*/\nexport const exportedTypeDecl = {\n  type: 'Program',\n  loc: loc(lc(3, 0), lc(5, 1)),\n  range: [13, 48],\n  body: [{\n    type: 'ExportNamedDeclaration',\n    loc: loc(lc(3, 0), lc(5, 1)),\n    range: [13, 48],\n    declaration: {\n      type: 'TypeAlias',\n      loc: loc(lc(3, 7), lc(5, 1)),\n      range: [20, 48],\n      id: {\n        type: 'Identifier',\n        loc: loc(lc(3, 12), lc(3, 15)),\n        range: [25, 28],\n        name: 'ExportedType',\n        optional: false,\n      },\n      right: {\n        type: 'ObjectTypeAnnotation',\n        loc: loc(lc(3, 18), lc(5, 1)),\n        range: [31, 48],\n        exact: false,\n        properties: [{\n          type: 'ObjectTypeProperty',\n          loc: loc(lc(4, 2), lc(4, 13)),\n          range: [35, 46],\n          key: {\n            type: 'Identifier',\n            loc: loc(lc(4, 2), lc(4, 5)),\n            range: [35, 38],\n            name: 'foo',\n            optional: false,\n          },\n          value: {\n            type: 'StringTypeAnnotation',\n            loc: loc(lc(4, 7), lc(4, 13)),\n            range: [40, 46],\n          },\n          optional: false,\n          static: false,\n          kind: 'init',\n        }],\n        indexers: [],\n        callProperties: [],\n      },\n    },\n    specifiers: [],\n    exportKind: 'type',\n  }],\n}\n\n/*\nfunction func(foo: string, bar: string) {\n}\n*/\nexport const func = {\n  type: 'Program',\n  loc: loc(lc(3, 0), lc(4, 1)),\n  range: [13, 59],\n  body: [{\n    type: 'FunctionDeclaration',\n    loc: loc(lc(3, 0), lc(4, 1)),\n    range: [13, 59],\n    id: {\n      type: 'Identifier',\n      loc: loc(lc(3, 9), lc(3, 16)),\n      range: [22, 29],\n      name: 'func',\n      optional: false,\n    },\n    params: [{\n      type: 'Identifier',\n      loc: loc(lc(3, 17), lc(3, 28)),\n      range: [30, 41],\n      name: 'foo',\n      typeAnnotation: {\n        type: 'TypeAnnotation',\n        loc: loc(lc(3, 20), lc(3, 28)),\n        range: [33, 41],\n        typeAnnotation: {\n          type: 'StringTypeAnnotation',\n          loc: loc(lc(3, 22), lc(3, 28)),\n          range: [35, 41],\n        },\n      },\n      optional: false,\n    }, {\n      type: 'Identifier',\n      loc: loc(lc(3, 30), lc(3, 41)),\n      range: [43, 54],\n      name: 'bar',\n      typeAnnotation: {\n        type: 'TypeAnnotation',\n        loc: loc(lc(3, 33), lc(3, 41)),\n        range: [46, 54],\n        typeAnnotation: {\n          type: 'StringTypeAnnotation',\n          loc: loc(lc(3, 35), lc(3, 41)),\n          range: [48, 54],\n        },\n      },\n      optional: false,\n    }],\n    body: {\n      type: 'BlockStatement',\n      loc: loc(lc(3, 43), lc(4, 1)),\n      range: [56, 59],\n      body: [],\n    },\n    async: false,\n    generator: false,\n    expression: false,\n  }],\n}\n\n/*\nexport function exportedFunc(fooBar: FooBar) {\n}\n*/\nexport const exportedFunc = {\n  type: 'Program',\n  loc: loc(lc(3, 0), lc(4, 1)),\n  range: [13, 62],\n  body: [{\n    type: 'ExportNamedDeclaration',\n    loc: loc(lc(3, 0), lc(4, 1)),\n    range: [13, 62],\n    declaration: {\n      type: 'FunctionDeclaration',\n      loc: loc(lc(3, 7), lc(4, 1)),\n      range: [20, 62],\n      id: {\n        type: 'Identifier',\n        loc: loc(lc(3, 16), lc(3, 29)),\n        range: [29, 42],\n        name: 'exportedFunc',\n        optional: false,\n      },\n      params: [{\n        type: 'Identifier',\n        loc: loc(lc(3, 30), lc(3, 44)),\n        range: [43, 57],\n        name: 'fooBar',\n        typeAnnotation: {\n          type: 'TypeAnnotation',\n          loc: loc(lc(3, 36), lc(3, 44)),\n          range: [49, 57],\n          typeAnnotation: {\n            type: 'GenericTypeAnnotation',\n            loc: loc(lc(3, 38), lc(3, 44)),\n            range: [51, 57],\n            id: {\n              type: 'Identifier',\n              loc: loc(lc(3, 38), lc(3, 44)),\n              range: [51, 57],\n              name: 'FooBar',\n              optional: false,\n            },\n          },\n        },\n        optional: false,\n      }],\n      body: {\n        type: 'BlockStatement',\n        loc: loc(lc(3, 46), lc(4, 1)),\n        range: [59, 62],\n        body: [],\n      },\n      async: false,\n      generator: false,\n      expression: false,\n    },\n    specifiers: [],\n    exportKind: 'value',\n  }],\n}\n\n/*\nconst constantValue = {}\nlet letValue = 1\nvar varValue = ''\n*/\nexport const variables = {\n  type: 'Program',\n  loc: loc(lc(3, 0), lc(5, 17)),\n  range: [13, 72],\n  body: [{\n    type: 'VariableDeclaration',\n    loc: loc(lc(3, 0), lc(3, 24)),\n    range: [13, 37],\n    declarations: [{\n      type: 'VariableDeclarator',\n      loc: loc(lc(3, 6), lc(3, 24)),\n      range: [19, 37],\n      id: {\n        type: 'Identifier',\n        loc: loc(lc(3, 6), lc(3, 19)),\n        range: [19, 32],\n        name: 'constantValue',\n        optional: false,\n      },\n      init: {\n        type: 'ObjectExpression',\n        loc: loc(lc(3, 22), lc(3, 24)),\n        range: [35, 37],\n        properties: [],\n      },\n    }],\n    kind: 'const',\n  }, {\n    type: 'VariableDeclaration',\n    loc: loc(lc(4, 0), lc(4, 16)),\n    range: [38, 54],\n    declarations: [{\n      type: 'VariableDeclarator',\n      loc: loc(lc(4, 4), lc(4, 16)),\n      range: [42, 54],\n      id: {\n        type: 'Identifier',\n        loc: loc(lc(4, 4), lc(4, 12)),\n        range: [42, 50],\n        name: 'letValue',\n        optional: false,\n      },\n      init: {\n        type: 'Literal',\n        loc: loc(lc(4, 15), lc(4, 16)),\n        range: [53, 54],\n        value: 1,\n        raw: '1',\n      },\n    }],\n    kind: 'let',\n  }, {\n    type: 'VariableDeclaration',\n    loc: loc(lc(5, 0), lc(5, 17)),\n    range: [55, 72],\n    declarations: [{\n      type: 'VariableDeclarator',\n      loc: loc(lc(5, 4), lc(5, 17)),\n      range: [59, 72],\n      id: {\n        type: 'Identifier',\n        loc: loc(lc(5, 4), lc(5, 12)),\n        range: [59, 67],\n        name: 'varValue',\n        optional: false,\n      },\n      init: {\n        type: 'Literal',\n        loc: loc(lc(5, 15), lc(5, 17)),\n        range: [70, 72],\n        value: '',\n        raw: \"''\",\n      },\n    }],\n    kind: 'var',\n  }],\n}\n\n/*\nexport const exportedConstantValue = {}\nexport let exportedLetValue = 1\nexport var exportedVarValue = ''\n*/\nexport const exportedVariables = {\n  errors: [],\n  tokens: [],\n  type: 'Program',\n  loc: loc(lc(3, 0), lc(5, 30)),\n  range: [13, 111],\n  body: [{\n    type: 'ExportNamedDeclaration',\n    loc: loc(lc(3, 0), lc(3, 37)),\n    range: [13, 50],\n    declaration: {\n      type: 'VariableDeclaration',\n      loc: loc(lc(3, 7), lc(3, 37)),\n      range: [20, 50],\n      declarations: [{\n        type: 'VariableDeclarator',\n        loc: loc(lc(3, 13), lc(3, 37)),\n        range: [26, 50],\n        id: {\n          type: 'Identifier',\n          loc: loc(lc(3, 13), lc(3, 32)),\n          range: [26, 45],\n          name: 'exportedConstantValue',\n          optional: false,\n        },\n        init: {\n          type: 'ObjectExpression',\n          loc: loc(lc(3, 35), lc(3, 37)),\n          range: [48, 50],\n          properties: [],\n        },\n      }],\n      kind: 'const',\n    },\n    specifiers: [],\n    exportKind: 'value',\n  }, {\n    type: 'ExportNamedDeclaration',\n    loc: loc(lc(4, 0), lc(4, 29)),\n    range: [51, 80],\n    declaration: {\n      type: 'VariableDeclaration',\n      loc: loc(lc(4, 7), lc(4, 29)),\n      range: [58, 80],\n      declarations: [{\n        type: 'VariableDeclarator',\n        loc: loc(lc(4, 11), lc(4, 29)),\n        range: [62, 80],\n        id: {\n          type: 'Identifier',\n          loc: loc(lc(4, 11), lc(4, 25)),\n          range: [62, 76],\n          name: 'exportedLetValue',\n          optional: false,\n        },\n        init: {\n          type: 'Literal',\n          loc: loc(lc(4, 28), lc(4, 29)),\n          range: [79, 80],\n          value: 1,\n          raw: '1',\n        },\n      }],\n      kind: 'let',\n    },\n    specifiers: [],\n    exportKind: 'value',\n  }, {\n    type: 'ExportNamedDeclaration',\n    loc: loc(lc(5, 0), lc(5, 30)),\n    range: [81, 111],\n    declaration: {\n      type: 'VariableDeclaration',\n      loc: loc(lc(5, 7), lc(5, 30)),\n      range: [88, 111],\n      declarations: [{\n        type: 'VariableDeclarator',\n        loc: loc(lc(5, 11), lc(5, 30)),\n        range: [92, 111],\n        id: {\n          type: 'Identifier',\n          loc: loc(lc(5, 11), lc(5, 25)),\n          range: [92, 106],\n          name: 'exportedVarValue',\n          optional: false,\n        },\n        init: {\n          type: 'Literal',\n          loc: loc(lc(5, 28), lc(5, 30)),\n          range: [109, 111],\n          value: '',\n          raw: \"''\",\n        },\n      }],\n      kind: 'var',\n    },\n    specifiers: [],\n    exportKind: 'value',\n  }],\n}\n\n/*\nexport class Component extends React.Component {\n  static propTypes = {\n  }\n\n  prop = 1\n\n  constructor(props: any) {\n  }\n\n  handleChangeEvent = (ev: Event) => {\n  }\n}\n*/\nexport const classDecl = {\n  errors: [],\n  tokens: [],\n  type: 'Program',\n  loc: loc(lc(3, 0), lc(14, 1)),\n  range: [13, 172],\n  body: [{\n    type: 'ClassDeclaration',\n    loc: loc(lc(3, 0), lc(14, 1)),\n    range: [13, 172],\n    id: {\n      type: 'Identifier',\n      loc: loc(lc(3, 6), lc(3, 15)),\n      range: [19, 28],\n      name: 'Component',\n      optional: false,\n    },\n    body: {\n      type: 'ClassBody',\n      loc: loc(lc(3, 40), lc(14, 1)),\n      range: [53, 172],\n      body: [{\n        type: 'ClassProperty',\n        loc: loc(lc(4, 2), lc(5, 3)),\n        range: [57, 81],\n        key: {\n          type: 'Identifier',\n          loc: loc(lc(4, 9), lc(4, 18)),\n          range: [64, 73],\n          name: 'propTypes',\n          optional: false,\n        },\n        value: {\n          type: 'ObjectExpression',\n          loc: loc(lc(4, 21), lc(5, 3)),\n          range: [76, 81],\n          properties: [],\n        },\n        computed: false,\n        static: true,\n      }, {\n        type: 'ClassProperty',\n        loc: loc(lc(7, 2), lc(7, 10)),\n        range: [85, 93],\n        key: {\n          type: 'Identifier',\n          loc: loc(lc(7, 2), lc(7, 6)),\n          range: [85, 89],\n          name: 'prop',\n          optional: false,\n        },\n        value: {\n          type: 'Literal',\n          loc: loc(lc(7, 9), lc(7, 10)),\n          range: [92, 93],\n          value: 1,\n          raw: '1',\n        },\n        computed: false,\n        static: false,\n      }, {\n        type: 'MethodDefinition',\n        loc: loc(lc(9, 2), lc(10, 3)),\n        range: [97, 126],\n        key: {\n          type: 'Identifier',\n          loc: loc(lc(9, 2), lc(9, 13)),\n          range: [97, 108],\n          name: 'constructor',\n          optional: false,\n        },\n        value: {\n          type: 'FunctionExpression',\n          loc: loc(lc(9, 13), lc(10, 3)),\n          range: [108, 126],\n          params: [{\n            type: 'Identifier',\n            loc: loc(lc(9, 14), lc(9, 24)),\n            range: [109, 119],\n            name: 'props',\n            typeAnnotation: {\n              type: 'TypeAnnotation',\n              loc: loc(lc(9, 19), lc(9, 24)),\n              range: [114, 119],\n              typeAnnotation: {\n                type: 'AnyTypeAnnotation',\n                loc: loc(lc(9, 21), lc(9, 24)),\n                range: [116, 119],\n              },\n            },\n            optional: false,\n          }],\n          body: {\n            type: 'BlockStatement',\n            loc: loc(lc(9, 26), lc(10, 3)),\n            range: [121, 126],\n            body: [],\n          },\n          async: false,\n          generator: false,\n          expression: false,\n        },\n        kind: 'constructor',\n        static: false,\n        computed: false,\n        decorators: [],\n      }, {\n        type: 'ClassProperty',\n        loc: loc(lc(12, 2), lc(13, 3)),\n        range: [130, 170],\n        key: {\n          type: 'Identifier',\n          loc: loc(lc(12, 2), lc(12, 19)),\n          range: [130, 147],\n          name: 'handleChangeEvent',\n          optional: false,\n        },\n        value: {\n          type: 'ArrowFunctionExpression',\n          loc: loc(lc(12, 22), lc(13, 3)),\n          range: [150, 170],\n          params: [{\n            type: 'Identifier',\n            loc: loc(lc(12, 23), lc(12, 32)),\n            range: [151, 160],\n            name: 'ev',\n            typeAnnotation: {\n              type: 'TypeAnnotation',\n              loc: loc(lc(12, 25), lc(12, 32)),\n              range: [153, 160],\n              typeAnnotation: {\n                type: 'GenericTypeAnnotation',\n                loc: loc(lc(12, 27), lc(12, 32)),\n                range: [155, 160],\n                id: {\n                  type: 'Identifier',\n                  loc: loc(lc(12, 27), lc(12, 32)),\n                  range: [155, 160],\n                  name: 'Event',\n                  optional: false,\n                },\n              },\n            },\n            optional: false,\n          }],\n          body: {\n            type: 'BlockStatement',\n            loc: loc(lc(12, 37), lc(13, 3)),\n            range: [165, 170],\n            body: [],\n          },\n          async: false,\n          generator: false,\n          expression: false,\n        },\n        computed: false,\n        static: false,\n      }],\n    },\n    superClass: {\n      type: 'MemberExpression',\n      loc: loc(lc(3, 24), lc(3, 39)),\n      range: [37, 52],\n      object: {\n        type: 'Identifier',\n        loc: loc(lc(3, 24), lc(3, 29)),\n        range: [37, 42],\n        name: 'React',\n        optional: false,\n      },\n      property: {\n        type: 'Identifier',\n        loc: loc(lc(3, 30), lc(3, 39)),\n        range: [43, 52],\n        name: 'Component',\n        optional: false,\n      },\n      computed: false,\n    },\n    implements: [],\n    decorators: [],\n  }],\n}\n\n/*\nexport class ExportedComponent extends React.Component {\n  static propTypes = {\n  }\n\n  prop = 1\n\n  constructor(props: any) {\n  }\n\n  handleChangeEvent = (ev: Event) => {\n  }\n}\n*/\nexport const exportedClassDecl = {\n  type: 'Program',\n  loc: loc(lc(3, 0), lc(14, 1)),\n  range: [13, 179],\n  body: [{\n    type: 'ExportNamedDeclaration',\n    loc: loc(lc(3, 0), lc(14, 1)),\n    range: [13, 179],\n    declaration: {\n      type: 'ClassDeclaration',\n      loc: loc(lc(3, 7), lc(14, 1)),\n      range: [20, 179],\n      id: {\n        type: 'Identifier',\n        loc: loc(lc(3, 13), lc(3, 22)),\n        range: [26, 35],\n        name: 'ExportedComponent',\n        optional: false,\n      },\n      body: {\n        type: 'ClassBody',\n        loc: loc(lc(3, 47), lc(14, 1)),\n        range: [60, 179],\n        body: [{\n          type: 'ClassProperty',\n          loc: loc(lc(4, 2), lc(5, 3)),\n          range: [64, 88],\n          key: {\n            type: 'Identifier',\n            loc: loc(lc(4, 9), lc(4, 18)),\n            range: [71, 80],\n            name: 'propTypes',\n            optional: false,\n          },\n          value: {\n            type: 'ObjectExpression',\n            loc: loc(lc(4, 21), lc(5, 3)),\n            range: [83, 88],\n            properties: [],\n          },\n          computed: false,\n          static: true,\n        }, {\n          type: 'ClassProperty',\n          loc: loc(lc(7, 2), lc(7, 10)),\n          range: [92, 100],\n          key: {\n            type: 'Identifier',\n            loc: loc(lc(7, 2), lc(7, 6)),\n            range: [92, 96],\n            name: 'prop',\n            optional: false,\n          },\n          value: {\n            type: 'Literal',\n            loc: loc(lc(7, 9), lc(7, 10)),\n            range: [99, 100],\n            value: 1,\n            raw: '1',\n          },\n          computed: false,\n          static: false,\n        }, {\n          type: 'MethodDefinition',\n          loc: loc(lc(9, 2), lc(10, 3)),\n          range: [104, 133],\n          key: {\n            type: 'Identifier',\n            loc: loc(lc(9, 2), lc(9, 13)),\n            range: [104, 115],\n            name: 'constructor',\n            optional: false,\n          },\n          value: {\n            type: 'FunctionExpression',\n            loc: loc(lc(9, 13), lc(10, 3)),\n            range: [115, 133],\n            params: [{\n              type: 'Identifier',\n              loc: loc(lc(9, 14), lc(9, 24)),\n              range: [116, 126],\n              name: 'props',\n              typeAnnotation: {\n                type: 'TypeAnnotation',\n                loc: loc(lc(9, 19), lc(9, 24)),\n                range: [121, 126],\n                typeAnnotation: {\n                  type: 'AnyTypeAnnotation',\n                  loc: loc(lc(9, 21), lc(9, 24)),\n                  range: [123, 126],\n                },\n              },\n              optional: false,\n            }],\n            body: {\n              type: 'BlockStatement',\n              loc: loc(lc(9, 26), lc(10, 3)),\n              range: [128, 133],\n              body: [],\n            },\n            async: false,\n            generator: false,\n            expression: false,\n          },\n          kind: 'constructor',\n          static: false,\n          computed: false,\n          decorators: [],\n        }, {\n          type: 'ClassProperty',\n          loc: loc(lc(12, 2), lc(13, 3)),\n          range: [137, 177],\n          key: {\n            type: 'Identifier',\n            loc: loc(lc(12, 2), lc(12, 19)),\n            range: [137, 154],\n            name: 'handleChangeEvent',\n            optional: false,\n          },\n          value: {\n            type: 'ArrowFunctionExpression',\n            loc: loc(lc(12, 22), lc(13, 3)),\n            range: [157, 177],\n            params: [{\n              type: 'Identifier',\n              loc: loc(lc(12, 23), lc(12, 32)),\n              range: [158, 167],\n              name: 'ev',\n              typeAnnotation: {\n                type: 'TypeAnnotation',\n                loc: loc(lc(12, 25), lc(12, 32)),\n                range: [160, 167],\n                typeAnnotation: {\n                  type: 'GenericTypeAnnotation',\n                  loc: loc(lc(12, 27), lc(12, 32)),\n                  range: [162, 167],\n                  id: {\n                    type: 'Identifier',\n                    loc: loc(lc(12, 27), lc(12, 32)),\n                    range: [162, 167],\n                    name: 'Event',\n                    optional: false,\n                  },\n                },\n              },\n              optional: false,\n            }],\n            body: {\n              type: 'BlockStatement',\n              loc: loc(lc(12, 37), lc(13, 3)),\n              range: [172, 177],\n              body: [],\n            },\n            async: false,\n            generator: false,\n            expression: false,\n          },\n          computed: false,\n          static: false,\n        }],\n      },\n      superClass: {\n        type: 'MemberExpression',\n        loc: loc(lc(3, 31), lc(3, 46)),\n        range: [44, 59],\n        object: {\n          type: 'Identifier',\n          loc: loc(lc(3, 31), lc(3, 36)),\n          range: [44, 49],\n          name: 'React',\n          optional: false,\n        },\n        property: {\n          type: 'Identifier',\n          loc: loc(lc(3, 37), lc(3, 46)),\n          range: [50, 59],\n          name: 'Component',\n          optional: false,\n        },\n        computed: false,\n      },\n      implements: [],\n      decorators: [],\n    },\n    specifiers: [],\n    exportKind: 'value',\n  }],\n}\n\n/*\nexport const restSpread = ({ ...rest }) => rest\n */\nexport const exportedFuncWithObjectRest = {\n  errors: [],\n  tokens: [],\n  type: 'Program',\n  loc: loc(lc(1, 0), lc(1, 52)),\n  range: [0, 52],\n  body: [\n    {\n      type: 'ExportNamedDeclaration',\n      loc: loc(lc(1, 0), lc(1, 52)),\n      range: [0, 52],\n      declaration: {\n        type: 'VariableDeclaration',\n        loc: loc(lc(1, 7), lc(1, 52)),\n        range: [7, 52],\n        declarations: [\n          {\n            type: 'VariableDeclarator',\n            loc: loc(lc(1, 13), lc(1, 52)),\n            range: [13, 52],\n            id: {\n              type: 'Identifier',\n              loc: loc(lc(1, 13), lc(1, 23)),\n              range: [13, 23],\n              name: 'restSpread',\n              optional: false,\n            },\n            init: {\n              type: 'ArrowFunctionExpression',\n              loc: loc(lc(1, 26), lc(1, 52)),\n              range: [26, 52],\n              params: [\n                {\n                  type: 'AssignmentPattern',\n                  loc: loc(lc(1, 27), lc(1, 43)),\n                  range: [27, 43],\n                  left: {\n                    type: 'ObjectPattern',\n                    loc: loc(lc(1, 27), lc(1, 38)),\n                    range: [27, 38],\n                    properties: [\n                      {\n                        type: 'RestProperty',\n                        loc: loc(lc(1, 29), lc(1, 36)),\n                        range: [29, 36],\n                        argument: {\n                          type: 'Identifier',\n                          loc: loc(lc(1, 32), lc(1, 36)),\n                          range: [32, 36],\n                          name: 'rest',\n                          optional: false,\n                        },\n                      },\n                    ],\n                  },\n                  right: {\n                    type: 'ObjectExpression',\n                    loc: loc(lc(1, 41), lc(1, 43)),\n                    range: [41, 43],\n                    properties: [],\n                  },\n                },\n              ],\n              body: {\n                type: 'Identifier',\n                loc: loc(lc(1, 48), lc(1, 52)),\n                range: [48, 52],\n                name: 'rest',\n                optional: false,\n              },\n              async: false,\n              generator: false,\n              expression: true,\n            },\n          },\n        ],\n        kind: 'const',\n      },\n      specifiers: [],\n      exportKind: 'value',\n    },\n  ],\n  comments: [],\n}\n\n/*\nconst { first, second: renamed, ...rest } = {}\n */\nexport const objectDestructuring = {\n  errors: [],\n  tokens: [],\n  type: 'Program',\n  loc: loc(lc(1, 0), lc(1, 46)),\n  range: [0, 46],\n  body: [\n    {\n      type: 'VariableDeclaration',\n      loc: loc(lc(1, 0), lc(1, 46)),\n      range: [0, 46],\n      declarations: [\n        {\n          type: 'VariableDeclarator',\n          loc: loc(lc(1, 6), lc(1, 46)),\n          range: [6, 46],\n          id: {\n            type: 'ObjectPattern',\n            loc: loc(lc(1, 6), lc(1, 41)),\n            range: [6, 41],\n            properties: [\n              {\n                type: 'Property',\n                loc: loc(lc(1, 8), lc(1, 13)),\n                range: [8, 13],\n                key: {\n                  type: 'Identifier',\n                  loc: loc(lc(1, 8), lc(1, 13)),\n                  range: [8, 13],\n                  name: 'first',\n                  optional: false,\n                },\n                value: {\n                  type: 'Identifier',\n                  loc: loc(lc(1, 8), lc(1, 13)),\n                  range: [8, 13],\n                  name: 'first',\n                  optional: false,\n                },\n                kind: 'init',\n                method: false,\n                shorthand: true,\n                computed: false,\n              },\n              {\n                type: 'Property',\n                loc: loc(lc(1, 15), lc(1, 30)),\n                range: [15, 30],\n                key: {\n                  type: 'Identifier',\n                  loc: loc(lc(1, 15), lc(1, 21)),\n                  range: [15, 21],\n                  name: 'second',\n                  optional: false,\n                },\n                value: {\n                  type: 'Identifier',\n                  loc: loc(lc(1, 23), lc(1, 30)),\n                  range: [23, 30],\n                  name: 'renamed',\n                  optional: false,\n                },\n                kind: 'init',\n                method: false,\n                shorthand: false,\n                computed: false,\n              },\n              {\n                type: 'RestProperty',\n                loc: loc(lc(1, 32), lc(1, 39)),\n                range: [32, 39],\n                argument: {\n                  type: 'Identifier',\n                  loc: loc(lc(1, 35), lc(1, 39)),\n                  range: [35, 39],\n                  name: 'rest',\n                  optional: false,\n                },\n              },\n            ],\n          },\n          init: {\n            type: 'ObjectExpression',\n            loc: loc(lc(1, 44), lc(1, 46)),\n            range: [44, 46],\n            properties: [],\n          },\n        },\n      ],\n      kind: 'const',\n    },\n  ],\n  comments: [],\n}\n\n/*\nconst [first, , ...rest] = []\n */\nexport const arrayDestructuring = {\n  errors: [],\n  tokens: [],\n  type: 'Program',\n  loc: loc(lc(1, 0), lc(1, 29)),\n  range: [0, 29],\n  body: [\n    {\n      type: 'VariableDeclaration',\n      loc: loc(lc(1, 0), lc(1, 29)),\n      range: [0, 29],\n      declarations: [\n        {\n          type: 'VariableDeclarator',\n          loc: loc(lc(1, 6), lc(1, 29)),\n          range: [6, 29],\n          id: {\n            type: 'ArrayPattern',\n            loc: loc(lc(1, 6), lc(1, 24)),\n            range: [6, 24],\n            elements: [\n              {\n                type: 'Identifier',\n                loc: loc(lc(1, 7), lc(1, 12)),\n                range: [7, 12],\n                name: 'first',\n                typeAnnotation: null,\n                optional: false,\n              },\n              null,\n              {\n                type: 'RestElement',\n                loc: loc(lc(1, 16), lc(1, 23)),\n                range: [16, 23],\n                argument: {\n                  type: 'Identifier',\n                  loc: loc(lc(1, 19), lc(1, 23)),\n                  range: [19, 23],\n                  name: 'rest',\n                  typeAnnotation: null,\n                  optional: false,\n                },\n              },\n            ],\n            typeAnnotation: null,\n          },\n          init: {\n            type: 'ArrayExpression',\n            loc: loc(lc(1, 27), lc(1, 29)),\n            range: [27, 29],\n            elements: [],\n          },\n        },\n      ],\n      kind: 'const',\n    },\n  ],\n  comments: [],\n}\n"
  },
  {
    "path": "spec/outline/parse-spec.js",
    "content": "/* @flow */\n/* eslint-env jasmine */\n\nimport {\n  typeDecl, exportedTypeDecl,\n  func, exportedFunc,\n  variables, exportedVariables,\n  classDecl, exportedClassDecl,\n  objectDestructuring, arrayDestructuring,\n  exportedFuncWithObjectRest,\n} from './parse-sample-ast'\nimport * as Parse from '../../lib/outline/parse'\n\nfunction buildOptions(exported, args) {\n  return {\n    showKeywords: {\n      export: exported,\n      default: false,\n      const: false,\n      var: false,\n      let: false,\n      class: false,\n      function: false,\n      type: false,\n    },\n    showFunctionArgs: args,\n  }\n}\n\nfunction toOutlineText(item, prefix) {\n  const output = []\n  const { tokenizedText } = item\n  if (!tokenizedText) {\n    return []\n  }\n  const text = tokenizedText.map(tt => tt.value).join('')\n  output.push(prefix + text)\n\n  return output.concat(\n    toOutlineTexts(item.children, prefix + '  '), // eslint-disable-line\n  )\n}\n\nfunction toOutlineTexts(tree, prefix = '') {\n  return tree.reduce(\n    (output, item) => output.concat(toOutlineText(item, prefix)),\n    [],\n  )\n}\n\ndescribe('outline/parse', function() {\n  describe('types', function() {\n    it('local', function() {\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, false), typeDecl).outlineTrees,\n      )).toEqual(\n        ['LocalType'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, false), typeDecl).outlineTrees,\n      )).toEqual(\n        ['LocalType'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, true), typeDecl).outlineTrees,\n      )).toEqual(\n        ['LocalType'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, true), typeDecl).outlineTrees,\n      )).toEqual(\n        ['LocalType'],\n      )\n    })\n\n    it('exported', function() {\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, false), exportedTypeDecl).outlineTrees,\n      )).toEqual(\n        ['ExportedType'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, false), exportedTypeDecl).outlineTrees,\n      )).toEqual(\n        ['export ExportedType'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, true), exportedTypeDecl).outlineTrees,\n      )).toEqual(\n        ['ExportedType'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, true), exportedTypeDecl).outlineTrees,\n      )).toEqual(\n        ['export ExportedType'],\n      )\n    })\n  })\n\n  describe('functions', function() {\n    it('local', function() {\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, false), func).outlineTrees,\n      )).toEqual(\n        ['func'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, false), func).outlineTrees,\n      )).toEqual(\n        ['func'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, true), func).outlineTrees,\n      )).toEqual(\n        ['func(foo, bar)'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, true), func).outlineTrees,\n      )).toEqual(\n        ['func(foo, bar)'],\n      )\n    })\n\n    it('exported', function() {\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, false), exportedFunc).outlineTrees,\n      )).toEqual(\n        ['exportedFunc'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, false), exportedFunc).outlineTrees,\n      )).toEqual(\n        ['export exportedFunc'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, true), exportedFunc).outlineTrees,\n      )).toEqual(\n        ['exportedFunc(fooBar)'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, true), exportedFunc).outlineTrees,\n      )).toEqual(\n        ['export exportedFunc(fooBar)'],\n      )\n    })\n  })\n\n  describe('variables', function() {\n    it('local', function() {\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, false), variables).outlineTrees,\n      )).toEqual(\n        ['constantValue', 'letValue', 'varValue'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, false), variables).outlineTrees,\n      )).toEqual(\n        ['constantValue', 'letValue', 'varValue'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, true), variables).outlineTrees,\n      )).toEqual(\n        ['constantValue', 'letValue', 'varValue'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, true), variables).outlineTrees,\n      )).toEqual(\n        ['constantValue', 'letValue', 'varValue'],\n      )\n    })\n\n    it('exported', function() {\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, false), exportedVariables).outlineTrees,\n      )).toEqual(\n        ['exportedConstantValue', 'exportedLetValue', 'exportedVarValue'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, false), exportedVariables).outlineTrees,\n      )).toEqual(\n        ['export exportedConstantValue', 'export exportedLetValue', 'export exportedVarValue'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, true), exportedVariables).outlineTrees,\n      )).toEqual(\n        ['exportedConstantValue', 'exportedLetValue', 'exportedVarValue'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, true), exportedVariables).outlineTrees,\n      )).toEqual(\n        ['export exportedConstantValue', 'export exportedLetValue', 'export exportedVarValue'],\n      )\n    })\n\n    it('object destructuring', function() {\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, false), objectDestructuring).outlineTrees,\n      )).toEqual(\n        ['{first, renamed, ...rest}'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, false), objectDestructuring).outlineTrees,\n      )).toEqual(\n        ['{first, renamed, ...rest}'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, true), objectDestructuring).outlineTrees,\n      )).toEqual(\n        ['{first, renamed, ...rest}'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, true), objectDestructuring).outlineTrees,\n      )).toEqual(\n        ['{first, renamed, ...rest}'],\n      )\n    })\n\n    it('array destructuring', function() {\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, false), arrayDestructuring).outlineTrees,\n      )).toEqual(\n        ['[first, , ...rest]'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, false), arrayDestructuring).outlineTrees,\n      )).toEqual(\n        ['[first, , ...rest]'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, true), arrayDestructuring).outlineTrees,\n      )).toEqual(\n        ['[first, , ...rest]'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, true), arrayDestructuring).outlineTrees,\n      )).toEqual(\n        ['[first, , ...rest]'],\n      )\n    })\n\n    it('exported func with object rest', function() {\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, false), exportedFuncWithObjectRest).outlineTrees,\n      )).toEqual(\n        ['restSpread'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, false), exportedFuncWithObjectRest).outlineTrees,\n      )).toEqual(\n        ['export restSpread'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, true), exportedFuncWithObjectRest).outlineTrees,\n      )).toEqual(\n        ['restSpread({...rest})'],\n      )\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, true), exportedFuncWithObjectRest).outlineTrees,\n      )).toEqual(\n        ['export restSpread({...rest})'],\n      )\n    })\n  })\n\n  describe('class', function() {\n    it('local', function() {\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, false), classDecl).outlineTrees,\n      )).toEqual([\n        'Component',\n        '  propTypes',\n        '  prop',\n        '  constructor',\n        '  handleChangeEvent',\n      ])\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, false), classDecl).outlineTrees,\n      )).toEqual([\n        'Component',\n        '  propTypes',\n        '  prop',\n        '  constructor',\n        '  handleChangeEvent',\n      ])\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, true), classDecl).outlineTrees,\n      )).toEqual([\n        'Component',\n        '  propTypes',\n        '  prop',\n        '  constructor(props)',\n        '  handleChangeEvent(ev)',\n      ])\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, true), classDecl).outlineTrees,\n      )).toEqual([\n        'Component',\n        '  propTypes',\n        '  prop',\n        '  constructor(props)',\n        '  handleChangeEvent(ev)',\n      ])\n    })\n\n    it('exported', function() {\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, false), exportedClassDecl).outlineTrees,\n      )).toEqual([\n        'ExportedComponent',\n        '  propTypes',\n        '  prop',\n        '  constructor',\n        '  handleChangeEvent',\n      ])\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, false), exportedClassDecl).outlineTrees,\n      )).toEqual([\n        'export ExportedComponent',\n        '  propTypes',\n        '  prop',\n        '  constructor',\n        '  handleChangeEvent',\n      ])\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(false, true), exportedClassDecl).outlineTrees,\n      )).toEqual([\n        'ExportedComponent',\n        '  propTypes',\n        '  prop',\n        '  constructor(props)',\n        '  handleChangeEvent(ev)',\n      ])\n      expect(toOutlineTexts(\n        Parse.astToOutline(buildOptions(true, true), exportedClassDecl).outlineTrees,\n      )).toEqual([\n        'export ExportedComponent',\n        '  propTypes',\n        '  prop',\n        '  constructor(props)',\n        '  handleChangeEvent(ev)',\n      ])\n    })\n  })\n})\n"
  },
  {
    "path": "styles/flow-ide.less",
    "content": ".flow-ide-hide {\n  display: none;\n}\n"
  },
  {
    "path": "vendor/.flowconfig",
    "content": "[ignore]\n\n[include]\n\n[libs]\n\n[options]\n"
  }
]