diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index e3b05003..00000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -!.eslintrc.js -**/node_modules/** -**/flow-typed/** diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 12651145..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,521 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ -/* eslint-disable max-len */ - -module.exports = { - root: true, - - parser: 'babel-eslint', - - parserOptions: { - ecmaVersion: 7, - sourceType: 'module', - ecmaFeatures: { - globalReturn: true, - jsx: true, - experimentalObjectRestSpread: true, - }, - }, - - // https://github.com/sindresorhus/globals/blob/master/globals.json - env: { - atomtest: true, - es6: true, - jasmine: true, - node: true, - }, - - extends: [ - 'plugin:jsx-a11y/recommended', - ], - - globals: { - atom: false, - document: false, - window: false, - }, - - rules: { - // Possible Errors (http://eslint.org/docs/rules/#possible-errors) - 'no-await-in-loop': 1, - 'no-cond-assign': 1, - 'no-console': 1, - 'no-constant-condition': [1, {checkLoops: false}], - 'no-control-regex': 1, - 'no-debugger': 1, - 'no-dupe-args': 1, - 'no-dupe-keys': 1, - 'no-duplicate-case': 1, - 'no-empty-character-class': 1, - 'no-empty': [1, {allowEmptyCatch: true}], - 'no-ex-assign': 1, - 'no-extra-boolean-cast': 0, // Flow actually requires us to cast to avoid sketchy null checks. - 'no-extra-parens': 0, - 'no-extra-semi': 1, - 'no-func-assign': 1, - 'no-inner-declarations': 1, - 'no-invalid-regexp': 1, - 'no-irregular-whitespace': 1, - 'no-obj-calls': 1, - 'no-prototype-builtins': 0, - 'no-regex-spaces': 1, - 'no-sparse-arrays': 1, - 'no-template-curly-in-string': 0, - 'no-unexpected-multiline': 1, - 'no-unreachable': 1, - 'no-unsafe-finally': 1, - 'no-unsafe-negation': 1, - 'use-isnan': 1, - 'valid-jsdoc': 0, - 'valid-typeof': 1, - - // Best Practices (http://eslint.org/docs/rules/#best-practices) - 'accessor-pairs': 1, - 'array-callback-return': 0, - 'block-scoped-var': 0, - 'class-methods-use-this': 0, - 'complexity': 0, - 'consistent-return': 0, - 'curly': 1, - 'default-case': 0, - 'dot-location': [1, 'property'], - 'dot-notation': 1, - 'eqeqeq': [1, 'allow-null'], - 'guard-for-in': 0, - 'no-alert': 0, - 'no-caller': 1, - 'no-case-declarations': 0, - 'no-div-regex': 1, - 'no-else-return': 0, - 'no-empty-function': 0, - 'no-empty-pattern': 1, - 'no-eq-null': 0, - 'no-eval': 1, - 'no-extend-native': 1, - 'no-extra-bind': 1, - 'no-extra-label': 1, - 'no-fallthrough': 1, - 'no-floating-decimal': 1, - 'no-global-assign': 1, - 'no-implicit-coercion': 1, - 'no-implicit-globals': 0, - 'no-implied-eval': 1, - 'no-invalid-this': 0, - 'no-iterator': 1, - 'no-labels': 1, - 'no-lone-blocks': 1, - 'no-loop-func': 0, - 'no-magic-numbers': 0, - 'no-multi-spaces': 1, - 'no-multi-str': 0, - 'no-new-func': 1, - 'no-new-wrappers': 1, - 'no-new': 1, - 'no-octal-escape': 1, - 'no-octal': 1, - 'no-param-reassign': 1, - 'no-proto': 1, - 'no-redeclare': [1, {builtinGlobals: true}], - 'no-restricted-properties': 0, - 'no-return-assign': 1, - 'no-return-await': 1, - 'no-script-url': 1, - 'no-self-assign': 1, - 'no-self-compare': 1, - 'no-sequences': 1, - 'no-throw-literal': 1, - 'no-unmodified-loop-condition': 0, - 'no-unused-expressions': 0, - 'no-unused-labels': 1, - 'no-useless-call': 1, - 'no-useless-concat': 1, - 'no-useless-escape': 1, - 'no-useless-return': 0, - 'no-void': 1, - 'no-warning-comments': 0, - 'no-with': 1, - 'prefer-promise-reject-errors': 1, - 'radix': 1, - 'require-await': 0, - // 'require-await': 1, - 'vars-on-top': 0, - 'wrap-iife': [1, 'inside'], - 'yoda': 1, - - // Strict Mode (http://eslint.org/docs/rules/#strict-mode) - 'strict': 0, - - // Variables (http://eslint.org/docs/rules/#variables) - 'init-declarations': 0, - 'no-catch-shadow': 1, - 'no-delete-var': 1, - 'no-label-var': 1, - 'no-restricted-globals': 0, - 'no-shadow-restricted-names': 1, - 'no-shadow': 1, - 'no-undef-init': 0, - 'no-undef': 1, - 'no-undefined': 0, - 'no-unused-vars': [1, {args: 'none', ignoreRestSiblings: true}], - 'no-use-before-define': 0, - - // Node.js and CommonJS (http://eslint.org/docs/rules/#nodejs-and-commonjs) - 'callback-return': 0, - 'global-require': 0, - 'handle-callback-err': 1, - 'no-mixed-requires': 1, - 'no-new-require': 1, - 'no-path-concat': 1, - 'no-process-env': 0, - 'no-process-exit': 0, - 'no-restricted-modules': 0, - 'no-sync': 0, - - // Stylistic Issues (http://eslint.org/docs/rules/#stylistic-issues) - 'array-bracket-spacing': 1, - 'block-spacing': 1, - 'brace-style': [1, '1tbs', {allowSingleLine: true}], - 'camelcase': 0, - 'capitalized-comments': 0, - 'comma-dangle': [1, {arrays: 'always-multiline', objects: 'always-multiline', imports: 'always-multiline', exports: 'always-multiline', functions: 'always-multiline'}], - 'comma-spacing': 1, - 'comma-style': 1, - 'computed-property-spacing': 1, - 'consistent-this': 0, - 'eol-last': 1, - 'func-call-spacing': 1, - 'func-name-matching': 0, - 'func-names': 0, - 'func-style': 0, - 'id-blacklist': 0, - 'id-length': 0, - 'id-match': 0, - // 'indent': [1, 2, {SwitchCase: 1}], - 'jsx-quotes': [1, 'prefer-double'], - 'key-spacing': [1, {beforeColon: false, afterColon: true}], - 'keyword-spacing': 1, - 'line-comment-position': 0, - 'linebreak-style': 1, - 'lines-around-comment': 0, - 'lines-around-directive': 0, - 'max-depth': 0, - // 'max-len': [1, 100, {tabWidth: 2, ignoreUrls: true}], - 'max-lines': 0, - 'max-nested-callbacks': 0, - 'max-params': 0, - 'max-statements-per-line': 0, - 'max-statements': 0, - 'multiline-ternary': 0, - 'new-cap': 0, - 'new-parens': 1, - 'newline-after-var': 0, - 'newline-before-return': 0, - 'newline-per-chained-call': 0, - 'no-array-constructor': 1, - 'no-bitwise': 1, - 'no-continue': 0, - 'no-inline-comments': 0, - 'no-lonely-if': 0, - 'no-mixed-operators': 0, - 'no-mixed-spaces-and-tabs': 1, - 'no-multi-assign': 0, - 'no-multiple-empty-lines': [1, {max: 2, maxBOF: 0, maxEOF: 1}], - 'no-negated-condition': 0, - 'no-nested-ternary': 0, - 'no-new-object': 1, - 'no-plusplus': 0, - 'no-restricted-syntax': 0, - 'no-tabs': 1, - 'no-ternary': 0, - 'no-trailing-spaces': 1, - 'no-underscore-dangle': 0, - 'no-unneeded-ternary': 0, - 'no-whitespace-before-property': 1, - 'object-curly-newline': 0, - // 'object-curly-spacing': 1, - 'object-property-newline': 0, - 'one-var-declaration-per-line': 0, - 'one-var': [1, 'never'], - 'operator-assignment': 1, - 'operator-linebreak': 0, - 'padded-blocks': [1, {blocks: 'never', classes: 'never', switches: 'never'}], - // 'quote-props': [1, 'as-needed'], - 'quotes': [1, 'single', 'avoid-escape'], - 'require-jsdoc': 0, - // 'semi-spacing': 1, - 'semi': 1, - 'sort-keys': 0, - 'sort-vars': 0, - 'space-before-blocks': 1, - 'space-before-function-paren': [1, {anonymous: 'never', named: 'never', asyncArrow: 'always'}], - 'space-in-parens': [1, 'never'], - 'space-infix-ops': 1, - 'space-unary-ops': 1, - 'spaced-comment': [1, 'always', {line: {exceptions: ['-']}, block: {balanced: true}}], - 'template-tag-spacing': 1, - 'unicode-bom': [1, 'never'], - 'wrap-regex': 0, - - // ECMAScript 6 (http://eslint.org/docs/rules/#ecmascript-6) - 'arrow-body-style': 0, - 'arrow-parens': [1, 'as-needed'], - 'arrow-spacing': 1, - 'constructor-super': 1, - // 'generator-star-spacing': 1, - 'no-class-assign': 1, - 'no-confusing-arrow': 0, - 'no-const-assign': 1, - 'no-dupe-class-members': 1, - 'no-duplicate-imports': 0, - 'no-new-symbol': 1, - 'no-restricted-imports': 0, - 'no-this-before-super': 1, - 'no-useless-computed-key': 1, - 'no-useless-constructor': 0, - 'no-useless-rename': 1, - 'no-var': 1, - 'object-shorthand': 1, - 'prefer-arrow-callback': [1, {allowNamedFunctions: true}], - 'prefer-const': 1, - 'prefer-destructuring': 0, - 'prefer-numeric-literals': 0, - 'prefer-rest-params': 0, - 'prefer-spread': 1, - 'prefer-template': 0, - 'require-yield': 0, - 'rest-spread-spacing': 1, - 'sort-imports': 0, - 'symbol-description': 1, - 'template-curly-spacing': 1, - 'yield-star-spacing': 1, - - // dependencies (https://github.com/zertosh/eslint-plugin-dependencies) - 'dependencies/case-sensitive': 1, - 'dependencies/no-cycles': [0, {skip: ['/spec/', '/sample-[^/]+/']}], - 'dependencies/no-unresolved': 0, - 'dependencies/require-json-ext': 1, - - // flowtype (https://github.com/gajus/eslint-plugin-flowtype) - 'flowtype/boolean-style': 1, - 'flowtype/define-flow-type': 1, - 'flowtype/delimiter-dangle': [1, 'always-multiline'], - // 'flowtype/generic-spacing': 1, - 'flowtype/no-dupe-keys': 0, - 'flowtype/no-primitive-constructor-types': 1, - 'flowtype/no-weak-types': 0, - 'flowtype/object-type-delimiter': 1, - 'flowtype/require-parameter-type': 0, - 'flowtype/require-return-type': 0, - 'flowtype/require-valid-file-annotation': 0, - 'flowtype/require-variable-type': 0, - 'flowtype/semi': 1, - 'flowtype/sort-keys': 0, - 'flowtype/space-after-type-colon': [1, 'always', {allowLineBreak: true}], - 'flowtype/space-before-generic-bracket': 1, - 'flowtype/space-before-type-colon': 1, - 'flowtype/type-id-match': 0, - 'flowtype/union-intersection-spacing': 1, - 'flowtype/use-flow-type': 1, - 'flowtype/valid-syntax': 0, - - // Jasmine (https://github.com/tlvince/eslint-plugin-jasmine) - 'jasmine/missing-expect': 0, - 'jasmine/named-spy': 0, - 'jasmine/no-assign-spyon': 0, - 'jasmine/no-disabled-tests': 1, - 'jasmine/no-expect-in-setup-teardown': 0, - 'jasmine/no-focused-tests': 0, - 'jasmine/no-global-setup': 0, - 'jasmine/no-spec-dupes': [1, 'branch'], - 'jasmine/no-suite-callback-args': 0, - 'jasmine/no-suite-dupes': [1, 'branch'], - 'jasmine/no-unsafe-spy': 0, - 'jasmine/valid-expect': 0, - - // nuclide-internal (https://github.com/facebook/nuclide/tree/master/resources/eslint-plugin-nuclide-internal) - 'rulesdir/atom-apis': 1, - 'rulesdir/consistent-import-name': 1, - 'rulesdir/dom-apis': 1, - 'rulesdir/flow-fb-oss': 1, - 'rulesdir/import-type-style': 1, - 'rulesdir/license-header': [1, {useBSDLicense: true}], - 'rulesdir/modules-dependencies': 1, - 'rulesdir/no-cross-atom-imports': [1, {whitelist: ['nuclide-ui']}], - 'rulesdir/no-shell-quote': 1, - 'rulesdir/no-unnecessary-disposable-wrapping': 1, - 'rulesdir/no-unresolved': 1, - 'rulesdir/prefer-nuclide-uri': 1, - 'rulesdir/use-nuclide-ui-components': 1, - 'rulesdir/no-commonjs': 1, - - // prefer-object-spread (https://github.com/bryanrsmith/eslint-plugin-prefer-object-spread) - 'prefer-object-spread/prefer-object-spread': 1, - - // prettier (https://github.com/prettier/eslint-plugin-prettier) - 'prettier/prettier': [1, 'fb', '@format'], - - // React (https://github.com/yannickcr/eslint-plugin-react) - 'react/display-name': 0, - 'react/forbid-component-props:': 0, - 'react/forbid-prop-types': 1, - 'react/no-array-index-key': 0, - 'react/no-children-prop': 0, - 'react/no-danger': 0, - 'react/no-danger-with-children': 0, - 'react/no-deprecated': 1, - 'react/no-did-mount-set-state': 0, - 'react/no-did-update-set-state': 0, - 'react/no-direct-mutation-state': 1, - 'react/no-find-dom-node': 0, - 'react/no-is-mounted': 0, - 'react/no-multi-comp': 0, - 'react/no-render-return-value': 0, - 'react/no-set-state': 0, - 'react/no-string-refs': 0, - 'react/no-unescaped-entities': 0, - 'react/no-unknown-property': 1, - 'react/no-unused-prop-types': 0, - 'react/prefer-es6-class': 0, - 'react/prefer-stateless-function': 0, - // 'react/prefer-stateless-function': 1, - // 'react/prop-types': 1, - 'react/react-in-jsx-scope': 1, - 'react/require-default-props': 0, - 'react/require-optimization': 0, - 'react/require-render-return': 0, - 'react/self-closing-comp': 1, - 'react/sort-comp': 0, - 'react/sort-prop-types': 0, - 'react/style-prop-object': 0, - 'react/jsx-boolean-value': 0, - 'react/jsx-closing-bracket-location': [1, {selfClosing: 'tag-aligned', nonEmpty: 'after-props'}], - // 'react/jsx-curly-spacing': [1, 'never'], - 'react/jsx-equals-spacing': 0, - 'react/jsx-filename-extension': 0, - 'react/jsx-first-prop-new-line': 0, - 'react/jsx-handler-names': 0, - 'react/jsx-indent': 0, - 'react/jsx-indent-props': 0, - 'react/jsx-key': 1, - 'react/jsx-max-props-per-line': 0, - 'react/jsx-no-bind': 0, - // 'react/jsx-no-bind': 1, - 'react/jsx-no-comment-textnodes': 1, - 'react/jsx-no-duplicate-props': 1, - 'react/jsx-no-literals': 0, - 'react/jsx-no-target-blank': 0, - 'react/jsx-no-undef': 1, - 'react/jsx-pascal-case': 0, - 'react/jsx-sort-props': 0, - 'react/jsx-space-before-closing': 1, - 'react/jsx-tag-spacing': 1, - 'react/jsx-uses-react': 1, - 'react/jsx-uses-vars': 1, - 'react/jxs-wrap-multilines': 0, - - // JSX Accessibility checks - // some currently disabled to adopt incrementally, annotated 'incremental' - 'jsx-a11y/accessible-emoji': 0, - 'jsx-a11y/alt-text': 0, // incremental: error - 'jsx-a11y/anchor-has-content': 0, - 'jsx-a11y/aria-activedescendant-has-tabindex': 0, - 'jsx-a11y/aria-props': 1, - 'jsx-a11y/aria-proptypes': 0, - 'jsx-a11y/aria-role': 0, - 'jsx-a11y/aria-unsupported-elements': 0, - 'jsx-a11y/click-events-have-key-events': 0, - 'jsx-a11y/heading-has-content': 0, - 'jsx-a11y/href-no-hash': 0, - 'jsx-a11y/html-has-lang': 0, - 'jsx-a11y/iframe-has-title': 0, - 'jsx-a11y/img-has-alt': 0, - 'jsx-a11y/img-redundant-alt': 0, - 'jsx-a11y/interactive-supports-focus': [ - 1, - { - tabbable: [ - 'button', - 'checkbox', - 'link', - 'searchbox', - 'spinbutton', - 'switch', - 'textbox', - ], - }, - ], - 'jsx-a11y/label-has-for': 0, - 'jsx-a11y/lang': 0, - 'jsx-a11y/mouse-events-have-key-events': 0, - 'jsx-a11y/no-access-key': 0, - 'jsx-a11y/no-autofocus': 0, - 'jsx-a11y/no-distracting-elements': 0, - 'jsx-a11y/no-interactive-element-to-noninteractive-role': [ - 1, - { - tr: ['none', 'presentation'], - }, - ], - 'jsx-a11y/no-noninteractive-element-interactions': [ - 0, // incremental: warning - { - handlers: ['onClick'], - }, - ], - 'jsx-a11y/no-noninteractive-element-to-interactive-role': [ - 1, - { - ul: ['listbox', 'menu', 'menubar', - 'radiogroup', 'tablist', 'tree', 'treegrid'], - ol: ['listbox', 'menu', 'menubar', - 'radiogroup', 'tablist', 'tree', 'treegrid'], - li: ['menuitem', 'option', 'row', 'tab', 'treeitem'], - table: ['grid'], - td: ['gridcell'], - }, - ], - 'jsx-a11y/no-noninteractive-tabindex': 0, // incremental: error - 'jsx-a11y/no-onchange': 0, - 'jsx-a11y/no-redundant-roles': 0, - 'jsx-a11y/no-static-element-interactions': [ - 0, // incremental: warning - { - handlers: ['onClick'], - }, - ], - 'jsx-a11y/role-has-required-aria-props': 0, - 'jsx-a11y/role-supports-aria-props': 0, - 'jsx-a11y/scope': 0, - 'jsx-a11y/tabindex-no-positive': 0, - }, - - plugins: [ - 'dependencies', - 'flowtype', - 'jasmine', - 'jsx-a11y', - 'prefer-object-spread', - 'prettier', - 'react', - 'rulesdir', - ], -}; - -// TODO(#21523621): Remove rulesdir when Yarn workspaces is enforced. -const rulesDirPlugin = require('eslint-plugin-rulesdir'); -rulesDirPlugin.RULES_DIR = 'modules/eslint-plugin-nuclide-internal'; diff --git a/.flowconfig b/.flowconfig deleted file mode 100644 index 9a645fd7..00000000 --- a/.flowconfig +++ /dev/null @@ -1,44 +0,0 @@ -[include] - -[ignore] -; ignore module source to prefer declaration -/node_modules/classnames/.* -/node_modules/lru-cache/.* -/node_modules/react/.* -/node_modules/rxjs/.* -/node_modules/semver/.* -/node_modules/jest-validate/.* -; annotated with `@flow` but have errors -/node_modules/fbjs/lib/.* -/modules/nuclide-node-transpiler/spec/fixtures/.* -; large dirs that are not imported -/docs/.* -/pkg/nuclide-debugger/VendorLib/devtools/.* - -[libs] -flow-libs/ - -[options] -emoji=true -experimental.const_params=true -experimental.strict_type_args=true -module.use_strict=true -module.system.node.resolve_dirname=node_modules -; 'modules' is added to the NODE_PATH via nuclide-node-transpiler. -module.system.node.resolve_dirname=modules -unsafe.enable_getters_and_setters=true - -suppress_comment=.*\\$FlowFixMe.* -suppress_comment=.*\\$FlowIssue.* -suppress_comment=.*\\$FlowIgnore.* -; uncommenting the next line will silence flow errors about missing 'fb' modules -; suppress_comment=.*\\$FlowFB.* - -[lints] -untyped-type-import=error - -sketchy-null=error -sketchy-null-bool=off - -[version] -0.53.1 diff --git a/.gitignore b/.gitignore index ade14b91..d4feb5b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,23 @@ .DS_Store npm-debug.log node_modules +# APM uses the .gitignore for installation purposes. +# This is merged into the regular .gitignore by the release script. + +/.flowconfig +/.gitignore.release +/CONTRIBUTING.md +/DEVELOPMENT +/circle.yml +/docs +/flow-libs +/flow-typed +/modules/eslint-plugin-nuclide-internal +/modules/nuclide-jasmine +/modules/scripts + +.eslintignore +.eslintrc.js +.eslintrc +scripts +spec diff --git a/.gitignore.release b/.gitignore.release deleted file mode 100644 index ffbe2d49..00000000 --- a/.gitignore.release +++ /dev/null @@ -1,20 +0,0 @@ -# APM uses the .gitignore for installation purposes. -# This is merged into the regular .gitignore by the release script. - -/.flowconfig -/.gitignore.release -/CONTRIBUTING.md -/DEVELOPMENT -/circle.yml -/docs -/flow-libs -/flow-typed -/modules/eslint-plugin-nuclide-internal -/modules/nuclide-jasmine -/modules/scripts - -.eslintignore -.eslintrc.js -.eslintrc -scripts -spec diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 160658f4..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,72 +0,0 @@ -# Contributing to `atom-ide-ui` - -Run the following commands to run `atom-ide-ui` from source: - -``` -# Clone the source -$ git clone https://github.com/facebook-atom/atom-ide-ui -# Install dependencies (`npm install` also works, but we recommend Yarn) -$ yarn -# Link the package to Atom's package directory -$ apm link - -# Make sure tests pass! -$ npm test - -# Run only Flow -$ npm run flow -# Run only lint -$ npm run lint-all -# Run only unit tests -$ ./scripts/test.js -``` - -## Repository Structure - -Code in `modules/` is periodically synced with the Nuclide repository: https://github.com/facebook/nuclide/tree/master/modules - -The main [index.js file](./modules/atom-ide-ui/index.js) is a [unified package]( -https://nuclide.io/blog/2016/01/13/Nuclide-v0.111.0-The-Unified-Package/) that -loads all of the feature packages (e.g. `atom-ide-diagnostics`, `hyperclick`, etc). -This allows us to share dependencies between all of Atom IDE UI's subpackages. - -- All feature packages are under [`modules/atom-ide-ui/pkg`](./modules/atom-ide-ui/pkg) - - Each package contains code in `lib/` and tests in `spec/`. -- The other `modules/` directories are helper libraries used in both Atom IDE UI and Nuclide. - - Node-only helpers are found in [`modules/nuclide-commons`](./modules/nuclide-commons) - - Atom-only helpers are found in [`modules/nuclide-commons-atom`](./modules/nuclide-commons-atom) - - Common React components are found in [`modules/nuclide-commons-ui`](./modules/nuclide-commons-ui) - - [`modules/nuclide-node-transpiler`](./modules/nuclide-node-transpiler) adds a require hook for runtime transpilation. - - [`modules/nuclide-jasmine`](./modules/nuclide-jasmine) is our custom Node test runner. - - [`modules/eslint-plugin-nuclide-internal`](./modules/eslint-plugin-nuclide-internal) contains various lint rules that we've developed for Atom/Nuclide packages. - -## Development Tips - -- Install [`ide-flowtype`](https://atom.io/packages/ide-flowtype) for Flow integration. -- Install [`linter-eslint`](https://atom.io/packages/linter-eslint) for ESLint integration. - - Skip the `linter` dependency to use atom-ide-ui's Diagnostics. -- Coding style is enforced by `eslint-plugin-prettier`. - -## Pull Requests - -1. Fork the repo and create your branch from `master`. -2. If you've added code that should be tested, add tests in the `spec` folders. -3. If you've changed APIs, update the documentation. -4. Ensure that tests pass and Flow/ESLint are clean (see above). -7. If you haven't already, complete the Contributor License Agreement ("CLA"). - -## Contributor License Agreement ("CLA") -In order to accept your pull request, we need you to submit a CLA. You only need -to do this once to work on any of Facebook's open source projects. - -Complete your CLA here: - -## Issues - -We use GitHub issues to track public bugs. Please ensure your description is -clear and has sufficient instructions to be able to reproduce the issue. - -## License - -By contributing to atom-ide-ui, you agree that your contributions will be licensed -under the LICENSE file in the root directory of this source tree. diff --git a/DEVELOPMENT b/DEVELOPMENT deleted file mode 100644 index e69de29b..00000000 diff --git a/circle.yml b/circle.yml deleted file mode 100644 index 7ac96a16..00000000 --- a/circle.yml +++ /dev/null @@ -1,24 +0,0 @@ -machine: - environment: - PATH: "${PATH}:${HOME}/${CIRCLE_PROJECT_REPONAME}/node_modules/.bin" - node: - version: 7.4.0 - -dependencies: - override: - # Copied from https://github.com/atom/ci/blob/master/circle.yml - - > - curl -s -L "https://atom.io/download/deb?channel=${ATOM_CHANNEL}" \ - -H 'Accept: application/octet-stream' \ - -o "atom-amd64.deb" - - sudo dpkg --install atom-amd64.deb || true - - sudo apt-get update - - sudo apt-get --fix-broken --assume-yes --quiet install - - yarn - cache_directories: - - ~/.cache/yarn - -notify: - branches: - only: - - master diff --git a/docs/busy-signal.md b/docs/busy-signal.md deleted file mode 100644 index ee1fba0d..00000000 --- a/docs/busy-signal.md +++ /dev/null @@ -1,34 +0,0 @@ -# Busy Signal - -A small status bar icon to indicate that something's happening. - -![Busy Signal](./images/busy-signal.png) - -[Code Formatting](./code-format.md) and [Find References](./find-references.md) -automatically activate the busy signal while they're waiting for providers, -but any package can consume the busy signal service. - -## Service API - -Consume the busy signal [Atom service](http://flight-manual.atom.io/behind-atom/sections/interacting-with-other-packages-via-services/) by adding this to your `package.json`: - -``` -"consumedServices": { - "atom-ide-busy-signal": { - "versions": { - "0.1.0": "consumeBusySignal" - } - } -} -``` - -Then, in your package entry point, add: - -``` -export function consumeBusySignal(busySignalService) { - ... -} -``` - -`busySignalService` will be a `BusySignalService` object -as described in [`atom-ide-busy-signal/lib/types.js`](../modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/types.js). diff --git a/docs/code-actions.md b/docs/code-actions.md deleted file mode 100644 index eb9056db..00000000 --- a/docs/code-actions.md +++ /dev/null @@ -1,50 +0,0 @@ -# Code Actions - -Code Actions allow you to perform additional actions for [diagnostics]( -./diagnostics.md). - -Code Actions can currently be triggered in two ways. - -Either by mousing over a diagnostic with code actions: - -![Datatip](./images/code-actions-datatip.png) - -Or by using the `diagnostics:show-actions-at-position` command / keyboard shortcut -while the cursor is on top of a diagnostic with code actions. - -![Context menu](./images/code-actions-context-menu.png) - -## Service API - -Provide the code actions [Atom service](http://flight-manual.atom.io/behind-atom/sections/interacting-with-other-packages-via-services/) by adding this to your `package.json`: - -``` -"providedServices": { - "code-actions": { - "versions": { - "0.1.0": "provideCodeActions" - } - } -} -``` - -Then, in your package entry point, add: - -``` -export function provideCodeActions(): CodeActionProvider { - return ... -} -``` - -You must return a `CodeActionProvider` object -as described in [`atom-ide-code-actions/lib/types.js`](../modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/types.js). - -- `grammarScopes` should be a list of [scope names]( -https://github.com/execjosh/atom-file-types#scope-names) of grammars -that the provider should apply to. -- `priority` will be used to determine the ordering of code actions in the case -of multiple providers. -- `getCodeActions` will be called in the situations described above, with a list -of intersecting diagnostics. See screenshots above to see how actions are displayed in the UI. - -Once the user clicks an action, your `apply()` function will be called. diff --git a/docs/code-format.md b/docs/code-format.md deleted file mode 100644 index 1eba1a41..00000000 --- a/docs/code-format.md +++ /dev/null @@ -1,58 +0,0 @@ -# Code Format - -Format a selection of code using the `code-format:format-code` command. -(Also accessible via context menu, or "Edit > Text > Format Code"). - -When no selection is provided, the entire file is formatted. - -![Code Format](./images/code-format.gif) - -Code Format also provides APIs to: - -- format code as you type -- format code on save (after you press save but before writing to disk). - -You can enable format-on-save using plain range/file providers from the -"atom-ide-code-format" section in the `atom-ide-ui` package settings. - -## Service API - -Provide code format [Atom services](http://flight-manual.atom.io/behind-atom/sections/interacting-with-other-packages-via-services/) by adding one or more of these to your `package.json`: -(Only the ones that you want to use; you don't need all of them!) - -``` -"providedServices": { - "code-format.range": { - "versions": { - "0.1.0": "provideRangeCodeFormat" - } - }, - "code-format.file": { - "versions": { - "0.1.0": "provideFileCodeFormat" - } - }, - "code-format.onType": { - "versions": { - "0.1.0": "provideOnTypeCodeFormat" - } - }, - "code-format.onSave": { - "versions": { - "0.1.0": "provideOnSaveCodeFormat" - } - } -} -``` - -Then, in your package entry point: - -``` -export function provideRangeCodeFormat(): RangeCodeFormatProvider {} -export function provideFileCodeFormat(): FileCodeFormatProvider {} -export function provideOnTypeCodeFormat(): OnTypeCodeFormatProvider {} -export function provideOnSaveCodeFormat(): OnSaveCodeFormatProvider {} -``` - -The various provider types are described in -[`atom-ide-code-format/lib/types.js`](../modules/atom-ide-ui/pkg/atom-ide-code-format/lib/types.js). diff --git a/docs/code-highlight.md b/docs/code-highlight.md deleted file mode 100644 index ba5ba32e..00000000 --- a/docs/code-highlight.md +++ /dev/null @@ -1,35 +0,0 @@ -# Code Highlight - -Put your cursor on a symbol to see relevant ranges highlighted. - -![Code Highlight](./images/code-highlight.gif) - -## Service API - -Provide the code highlight [Atom service](http://flight-manual.atom.io/behind-atom/sections/interacting-with-other-packages-via-services/) by adding this to your `package.json`: - -``` -"providedServices": { - "code-highlight": { - "versions": { - "0.1.0": "provideCodeHighlight" - } - } -} -``` - -Then, in your package entry point, add: - -``` -export function provideCodeHighlight(): CodeHighlightProvider {} -``` - -You must return a `CodeHighlightProvider` object -as described in [`atom-ide-code-highlight/lib/types.js`](../modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/types.js). - -- `grammarScopes` should be a list of [scope names]( -https://github.com/execjosh/atom-file-types#scope-names) of grammars -that the provider should apply to. -- `priority` will be used to determine the provider to use in the case of multiple providers. -- `highlight` will be called every time the cursor position changes or the buffer changes with the current position. -The returned array of ranges will be highlighted. diff --git a/docs/datatips.md b/docs/datatips.md deleted file mode 100644 index d69ead8d..00000000 --- a/docs/datatips.md +++ /dev/null @@ -1,54 +0,0 @@ -# Datatips - -Hover over sections of code to see relevant information in a tooltip. - -![Datatips](./images/datatips.gif) - -Datatips can display one or more blocks of Markdown-formatted text or -highlighted snippets of code. - -Datatips can be pinned to be persistent using the small 'pin' button. - -You can customize the delay for showing and hiding datatips from the -"atom-ide-datatip" section in the `atom-ide-ui` package settings. - -## Service API - -Consume the datatip [Atom service](http://flight-manual.atom.io/behind-atom/sections/interacting-with-other-packages-via-services/) by adding this to your `package.json`: - -``` -"consumedServices": { - "datatip": { - "versions": { - "0.1.0": "consumeDatatipService" - } - } -} -``` - -Then, in your package entry point, add: - -``` -export function consumeDatatipService(datatipService) {} -``` - -`datatipService` will be a `DatatipService` object -as described in [`atom-ide-datatip/lib/types.js`](../modules/atom-ide-ui/pkg/atom-ide-datatip/lib/types.js). - -Use the `DatatipService` to register providers with `addProvider`. -`addModifierProvider` may be used to register -datatips that require trigger keys: one example -is definition previews, which appear when using -the [Hyperclick](./definitions.md) modifier key. - -For each provider: - -- `grammarScopes` should be a list of [scope names]( -https://github.com/execjosh/atom-file-types#scope-names) of grammars -that the provider should apply to. -- `priority` will be used to disambiguate between multiple providers. The highest priority provider that returns a non-null result will be displayed. -- Return a valid `Datatip` object from the `datatip` function. -Using the `MarkedString` form is preferred to avoid having to create a custom React component. - -Finally, `createPinnedDataTip` may be used to dynamically create -pinned datatips at any time. diff --git a/docs/definitions.md b/docs/definitions.md deleted file mode 100644 index d0d5905f..00000000 --- a/docs/definitions.md +++ /dev/null @@ -1,83 +0,0 @@ -# Definitions - -## Hyperclick - -Cmd-click (Ctrl-click on Windows/Linux) on an editor position to go to its -definition, or trigger the `hyperclick:confirm-cursor` command. - -![Jump to symbol definitions](./images/hyperclick.gif) - -The default keybinding was chosen to be compatible with most other IDEs -[(see blog post here)](https://nuclide.io/blog/2017/02/27/Command-Click-You-Have-One-Job/), -but you can always customize it from the "hyperclick" section in the `atom-ide-ui` -package settings. - -## Definition Preview - -Cmd-hover (Ctrl-hover on Windows/Linux) on an editor position to preview the -source code following the definition. - -![Preview a symbol definition](./images/definition-preview.png) - -## Service API - -Atom IDE UI consumes an abstract "definitions" API to fetch definitions at -arbitrary editor positions. If you use this API, Hyperclick and Definition Preview are automatically -provided for you. - -You can provide the definitions [Atom service](http://flight-manual.atom.io/behind-atom/sections/interacting-with-other-packages-via-services/) by adding the following to your `package.json`: - -``` -"providedServices": { - "definitions": { - "versions": { - "0.1.0": "provideDefinitions" - } - } -} -``` - -Then, in your package entry point, add: - -``` -export function provideDefinitions(): DefinitionsProvider { - return ... -} -``` - -The return value must be a `DefinitionProvider` object -as defined in -[`atom-ide-definitions/lib/types.js`](../modules/atom-ide-ui/pkg/atom-ide-definitions/lib/types.js). - -- `grammarScopes` should be a list of [scope names]( -https://github.com/execjosh/atom-file-types#scope-names) of grammars -that the provider should apply to. -- `priority` will be used to disambiguate between multiple providers. The highest priority provider that returns a non-null result will be used. - -## Hyperclick Service API - -In some cases, it may make sense to provide Hyperclick results directly. -In general, Hyperclick results can perform arbitrary actions upon selection (unlike definitions, which can only take you to a file location). - -To provide Hyperclick results, add the following to your `package.json`: - -``` -"providedServices": { - "hyperclick": { - "versions": { - "0.1.0": "provideHyperclick" - } - } -} -``` - -Then, in your package entry point, add: - -``` -export function provideHyperclick(): HyperclickProvider { - return ... -} -``` - -The return value must be a `HyperclickProvider` object as defined in -[`hyperclick/lib/types.js`](../modules/atom-ide-ui/pkg/hyperclick/lib/types.js). diff --git a/docs/diagnostics.md b/docs/diagnostics.md deleted file mode 100644 index f47773ce..00000000 --- a/docs/diagnostics.md +++ /dev/null @@ -1,22 +0,0 @@ -# Diagnostics - -## Overview - -Atom IDE UI displays diagnostics in three main ways: - -- An expandable dock shows a table of diagnostics -- Diagnostics are underlined inside the text editor (with [datatips](./datatips.md)) -- Color-coded gutter markers indicate the presence of diagnostics on a line - -![Highlight and fix problems with your code with Diagnostics](./images/diagnostics.png) - -## Service APIs - -Atom IDE UI is compatible with the [Linter APIs](http://steelbrain.me/linter/), -with a few unimplemented features: - -- markdown rendering of `description` -- the `url` and `icon` fields -- multiple `solutions` (only the first one is used) -- callback-based `solutions` -- callback-based `description` diff --git a/docs/find-references.md b/docs/find-references.md deleted file mode 100644 index f0e98415..00000000 --- a/docs/find-references.md +++ /dev/null @@ -1,38 +0,0 @@ -# Find References - -Use the `find-references:activate` command to find references at the current -editor location. - -![Find all usages of a symbol with Find References](./images/find-references.gif) - -A scrollable list of all references, with context, will be displayed in a new -pane alongside the active editor. - -You can configure the default location of the Find References pane via the -"atom-ide-find-references" section in the `atom-ide-ui` package settings. - -## Service API - -You can provide the Find References [Atom service](http://flight-manual.atom.io/behind-atom/sections/interacting-with-other-packages-via-services/) by adding the following to your `package.json`: - -``` -"providedServices": { - "find-references": { - "versions": { - "0.1.0": "provideReferences" - } - } -} -``` - -Then, in your package entry point, add: - -``` -export function provideReferences(): FindReferencesProvider { - return ... -} -``` - -The return value must be a `FindReferencesProvider` object -as defined in -[`atom-ide-find-references/lib/types.js`](../modules/atom-ide-ui/pkg/atom-ide-find-references/lib/types.js). diff --git a/docs/images/busy-signal.png b/docs/images/busy-signal.png deleted file mode 100644 index 94a1849e..00000000 Binary files a/docs/images/busy-signal.png and /dev/null differ diff --git a/docs/images/code-actions-context-menu.png b/docs/images/code-actions-context-menu.png deleted file mode 100644 index e9ae568c..00000000 Binary files a/docs/images/code-actions-context-menu.png and /dev/null differ diff --git a/docs/images/code-actions-datatip.png b/docs/images/code-actions-datatip.png deleted file mode 100644 index ddbabca5..00000000 Binary files a/docs/images/code-actions-datatip.png and /dev/null differ diff --git a/docs/images/code-format.gif b/docs/images/code-format.gif deleted file mode 100644 index eb624491..00000000 Binary files a/docs/images/code-format.gif and /dev/null differ diff --git a/docs/images/code-highlight.gif b/docs/images/code-highlight.gif deleted file mode 100644 index c348a9c6..00000000 Binary files a/docs/images/code-highlight.gif and /dev/null differ diff --git a/docs/images/datatips.gif b/docs/images/datatips.gif deleted file mode 100644 index 4d3c6bdc..00000000 Binary files a/docs/images/datatips.gif and /dev/null differ diff --git a/docs/images/datatips.png b/docs/images/datatips.png deleted file mode 100644 index c6f9d558..00000000 Binary files a/docs/images/datatips.png and /dev/null differ diff --git a/docs/images/definition-preview.png b/docs/images/definition-preview.png deleted file mode 100644 index 402c38db..00000000 Binary files a/docs/images/definition-preview.png and /dev/null differ diff --git a/docs/images/diagnostics.png b/docs/images/diagnostics.png deleted file mode 100644 index ba50f6f2..00000000 Binary files a/docs/images/diagnostics.png and /dev/null differ diff --git a/docs/images/find-references.gif b/docs/images/find-references.gif deleted file mode 100644 index 3ce93615..00000000 Binary files a/docs/images/find-references.gif and /dev/null differ diff --git a/docs/images/hyperclick.gif b/docs/images/hyperclick.gif deleted file mode 100644 index 1f1eb286..00000000 Binary files a/docs/images/hyperclick.gif and /dev/null differ diff --git a/docs/images/outline-view.png b/docs/images/outline-view.png deleted file mode 100644 index e2e67441..00000000 Binary files a/docs/images/outline-view.png and /dev/null differ diff --git a/docs/images/screenshot.png b/docs/images/screenshot.png deleted file mode 100644 index ee4c7423..00000000 Binary files a/docs/images/screenshot.png and /dev/null differ diff --git a/docs/keybindings.md b/docs/keybindings.md deleted file mode 100644 index 9bcbda51..00000000 --- a/docs/keybindings.md +++ /dev/null @@ -1,20 +0,0 @@ -# Default Keybindings - -Remember, you can always search through all the commands via the Command Palette (cmd-shift-P). - -As with all Atom commands, feel free to customize these to whichever keybindings you prefer in your `keymap.cson`. - -| Feature | Command | MacOS | Windows/Linux | -| ------------------- | --------------------------- | --------------- | ------------- | -| Format Code | `code-format:format-code` | cmd-shift-c | ctrl-shift-c | -| Toggle Datatip | `datatip:toggle` | opt / cmd-opt | alt / ctrl-alt | -| Toggle Diagnostics | `diagnostics:toggle-table` | opt-shift-d | alt-shift-d | -| Go to First Diagnostic | `diagnostics:go-to-first-diagnostic` | opt-ctrl-< | alt-ctrl-< | -| Go to Last Diagnostic | `diagnostics:go-to-last-diagnostic` | opt-ctrl-> | alt-ctrl-> | -| Go to Previous Diagnostic | `diagnostics:go-to-previous-diagnostic` | opt-< | alt-< | -| Go to Next Diagnostic | `diagnostics:go-to-next-diagnostic` | opt-> | alt-> | -| Show Code Actions | `diagnostics:show-actions-at-position` | opt-a | alt-a | -| Apply Diagnostic Fixes | `diagnostics:fix-all-in-current-file` | opt-shift-a | alt-shift-a | -| Find References | `find-references:activate` | cmd-opt-shift-f | ctrl-alt-shift-f | -| Toggle Outline View | `outline-view:toggle` | opt-o | alt-o | -| Hyperclick | `hyperclick:confirm-cursor` | cmd-opt-enter | ctrl-alt-enter | diff --git a/docs/outline-view.md b/docs/outline-view.md deleted file mode 100644 index ba46f29b..00000000 --- a/docs/outline-view.md +++ /dev/null @@ -1,40 +0,0 @@ -# Outline View - -Use the `outline-view:toggle` command to open the Outline View dock. - -Outline View - -The Outline View displays a tree view of all symbols in the active editor, -along with the ability to filter on a search keyword and jump to selected symbols. - -You can also select the editor range corresponding to an outline view entry by -simply double-clicking it. - -## Service API - -You can provide the Outline View [Atom service](http://flight-manual.atom.io/behind-atom/sections/interacting-with-other-packages-via-services/) by adding the following to your `package.json`: - -``` -"providedServices": { - "outline-view": { - "versions": { - "0.1.0": "provideOutlines" - } - } -} -``` - -Then, in your package entry point, add: - -``` -export function provideOutlines(): OutlineProvider { - return ... -} -``` - -The return value must be a `OutlineProvider` object -as defined in -[`atom-ide-outline-view/lib/types.js`](../modules/atom-ide-ui/pkg/atom-ide-outline-view/lib/types.js). - -Outlines are normally re-fetched after every edit, but -you can provide an `updateOnEdit` field of `false` to only re-fetch on save. diff --git a/flow-libs/atom-jasmine.js.flow b/flow-libs/atom-jasmine.js.flow deleted file mode 100644 index b4cd47ba..00000000 --- a/flow-libs/atom-jasmine.js.flow +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the license found in the LICENSE file in - * the root directory of this source tree. - * - * @flow - */ - -// Type declarations for Atom's extensions to Jasmine v1.3 -// https://github.com/atom/atom/blob/master/spec/spec-helper.coffee - -/** Note that waitsForPromise has an optional first argument. */ -declare function waitsForPromise( - optionsOrFunc: {timeout?: number, shouldReject?: boolean, label?: string} | () => Promise, - func?: () => Promise -): void; - -/** - * deltaInMilliseconds defaults to 1. - */ -declare function advanceClock(deltaInMilliseconds?: number): void; diff --git a/flow-libs/atom.js.flow b/flow-libs/atom.js.flow deleted file mode 100644 index b990b5e4..00000000 --- a/flow-libs/atom.js.flow +++ /dev/null @@ -1,1962 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the license found in the LICENSE file in - * the root directory of this source tree. - * - * @flow - */ - -/** - * Private Classes - */ - -// Octicons v4.4.0. List extracted from the atom-styleguide package. -type atom$Octicon = 'alert' | 'alignment-align' | 'alignment-aligned-to' | 'alignment-unalign' | - 'arrow-down' | 'arrow-left' | 'arrow-right' | 'arrow-small-down' | 'arrow-small-left' | - 'arrow-small-right' | 'arrow-small-up' | 'arrow-up' | 'beaker' | 'beer' | 'bell' | 'bold' | - 'book' | 'bookmark' | 'briefcase' | 'broadcast' | 'browser' | 'bug' | 'calendar' | 'check' | - 'checklist' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'circle-slash' | - 'circuit-board' | 'clippy' | 'clock' | 'cloud-download' | 'cloud-upload' | 'code' | 'color-mode' | - 'comment' | 'comment-add' | 'comment-discussion' | 'credit-card' | 'dash' | 'dashboard' | - 'database' | 'desktop-download' | 'device-camera' | 'device-camera-video' | 'device-desktop' | - 'device-mobile' | 'diff' | 'diff-added' | 'diff-ignored' | 'diff-modified' | 'diff-removed' | - 'diff-renamed' | 'ellipses' | 'ellipsis' | 'eye' | 'eye-unwatch' | 'eye-watch' | 'file' | - 'file-add' | 'file-binary' | 'file-code' | 'file-directory' | 'file-directory-create' | - 'file-media' | 'file-pdf' | 'file-submodule' | 'file-symlink-directory' | 'file-symlink-file' | - 'file-text' | 'file-zip' | 'flame' | 'fold' | 'gear' | 'gift' | 'gist' | 'gist-fork' | - 'gist-new' | 'gist-private' | 'gist-secret' | 'git-branch' | 'git-branch-create' | - 'git-branch-delete' | 'git-commit' | 'git-compare' | 'git-fork-private' | 'git-merge' | - 'git-pull-request' | 'git-pull-request-abandoned' | 'globe' | 'grabber' | 'graph' | 'heart' | - 'history' | 'home' | 'horizontal-rule' | 'hourglass' | 'hubot' | 'inbox' | 'info' | - 'issue-closed' | 'issue-opened' | 'issue-reopened' | 'italic' | 'jersey' | 'jump-down' | - 'jump-left' | 'jump-right' | 'jump-up' | 'key' | 'keyboard' | 'law' | 'light-bulb' | 'link' | - 'link-external' | 'list-ordered' | 'list-unordered' | 'location' | 'lock' | 'log-in' | 'log-out' | - 'logo-gist' | 'logo-github' | 'mail' | 'mail-read' | 'mail-reply' | 'mark-github' | 'markdown' | - 'megaphone' | 'mention' | 'microscope' | 'milestone' | 'mirror' | 'mirror-private' | - 'mirror-public' | 'mortar-board' | 'move-down' | 'move-left' | 'move-right' | 'move-up' | 'mute' | - 'no-newline' | 'octoface' | 'organization' | 'package' | 'paintcan' | 'pencil' | 'person' | - 'person-add' | 'person-follow' | 'pin' | 'playback-fast-forward' | 'playback-pause' | - 'playback-play' | 'playback-rewind' | 'plug' | 'plus-small' | 'plus' | 'podium' | - 'primitive-dot' | 'primitive-square' | 'pulse' | 'puzzle' | 'question' | 'quote' | 'radio-tower' | - 'remove-close' | 'reply' | 'repo' | 'repo-clone' | 'repo-create' | 'repo-delete' | - 'repo-force-push' | 'repo-forked' | 'repo-pull' | 'repo-push' | 'repo-sync' | 'rocket' | 'rss' | - 'ruby' | 'screen-full' | 'screen-normal' | 'search' | 'search-save' | 'server' | 'settings' | - 'shield' | 'sign-in' | 'sign-out' | 'smiley' | 'split' | 'squirrel' | 'star' | 'star-add' | - 'star-delete' | 'steps' | 'stop' | 'sync' | 'tag' | 'tag-add' | 'tag-remove' | 'tasklist' | - 'telescope' | 'terminal' | 'text-size' | 'three-bars' | 'thumbsdown' | 'thumbsup' | 'tools' | - 'trashcan' | 'triangle-down' | 'triangle-left' | 'triangle-right' | 'triangle-up' | 'unfold' | - 'unmute' | 'unverified' | 'verified' | 'versions' | 'watch' | 'x' | 'zap'; - -type atom$PaneLocation = 'left' | 'right' | 'bottom' | 'center'; - -declare class atom$Model { - destroy(): void, - isDestroyed(): boolean, -} - -declare class atom$Package { - path: string, - activateTime: number, - mainModule: any, - metadata: Object, - name: string, - loadTime: number, - getType(): 'atom' | 'textmate' | 'theme', - hasActivationCommands(): boolean, - hasActivationHooks(): boolean, - getActivationHooks(): Array, - onDidDeactivate(cb: () => mixed): IDisposable, - activateNow(): void, - // Undocumented - getCanDeferMainModuleRequireStorageKey(): string, -} - -/** - * Essential Classes - */ - -declare class atom$CustomEvent extends Event { - constructor(type: string, eventInitDict?: CustomEvent$Init): void; - detail: any; - originalEvent: ?Event; -} - -type atom$CommandCallback = (event: atom$CustomEvent) => mixed; - -declare class atom$CommandRegistry { - // Methods - add( - target: string | HTMLElement, - commandNameOrCommands: string | {[commandName: string]: atom$CommandCallback}, - callback?: atom$CommandCallback - ): IDisposable, - dispatch(target: HTMLElement, commandName: string, detail?: Object): void, - onDidDispatch(callback: (event: Event) => mixed): IDisposable, - onWillDispatch(callback: (event: Event) => mixed): IDisposable, -} - -declare class atom$CompositeDisposable { - constructor(...disposables: Array): void, - dispose(): void, - - add(...disposables: Array): void, - remove(disposable: IDisposable): void, - clear(): void, -} - -type atom$ConfigType = - 'boolean' | 'string' | 'integer' | 'number' | - 'array' | 'object' | 'color' | 'any'; - -type atom$ConfigSchema = { - default?: mixed, - description?: string, - enum?: Array, - maximum?: number, - minimum?: number, - properties?: Object, - title?: string, - type: Array | atom$ConfigType, -}; - -declare class atom$Config { - // Config Subscription - observe( - keyPath: string, - optionsOrCallback?: Object | (value: any) => void, - callback?: (value: any) => void - ): IDisposable, - - onDidChange( - keyPathOrCallback: string | (event: Object) => void, - optionsOrCallback?: Object | (event: Object) => void, - callback?: (event: Object) => void - ): IDisposable, - - // Managing Settings - get( - keyPath?: string, - options?: { - excludeSources?: Array, - sources?: Array, - scope?: Object, - } - ): mixed, - - set( - keyPath: string, - value: ?mixed, - options?: { - scopeSelector?: string, - source?: string, - }, - ): boolean, - - unset( - keyPath: string, - options?: { - scopeSelector?: string, - source?: string, - } - ): void, - - getUserConfigPath(): string, - - // Undocumented Methods - getRawValue(keyPath: ?string, options: {excludeSources?: string, sources?: string}): mixed, - getSchema(keyPath: string): atom$ConfigSchema, - save(): void, - setRawValue(keyPath: string, value: mixed): void, - setSchema( - keyPath: string, - schema: atom$ConfigSchema, - ): void, -} - -declare class atom$Cursor { - // Event Subscription - onDidChangePosition( - callback: (event: { - oldBufferPosition: atom$Point, - oldScreenPosition: atom$Point, - newBufferPosition: atom$Point, - newScreenPosition: atom$Point, - textChanged: boolean, - Cursor: atom$Cursor, - }) => mixed, - ): IDisposable, - - // Managing Cursor Position - getBufferRow(): number, - getBufferColumn(): number, - getBufferPosition(): atom$Point, - - // Cursor Position Details - // Moving the Cursor - - // Local Positions and Ranges - getCurrentWordBufferRange(options?: {wordRegex: RegExp}): atom$Range, - getCurrentWordPrefix(): string, - - // Visibility - // Comparing to another cursor - // Utilities - wordRegExp(options?: {includeNonWordCharacters: boolean}): RegExp, -} - -declare class atom$Decoration { - destroy(): void, - onDidChangeProperties( - callback: (event: {oldProperties: Object, newProperties: Object}) => mixed - ): IDisposable, - onDidDestroy(callback: () => mixed): IDisposable, - getMarker(): atom$Marker, - getProperties(): Object, - setProperties(properties: mixed): void, -} - -declare class atom$DisplayMarkerLayer { - destroy(): void, - clear(): void, - isDestroyed(): boolean, - markBufferRange(range: atom$Range | atom$RangeLike, options: MarkerOptions): atom$Marker, - getMarkers(): Array, -} - -declare class atom$Disposable { - constructor(disposalAction?: (...args: Array) => any): void, - dispose(): void, -} - -declare class atom$Emitter { - dispose(): void, - on(name: string, callback: (v: any) => mixed): IDisposable, - preempt(name: string, callback: (v: any) => void): IDisposable, - // This is a flow hack to prevent emitting more than one value. - // `EventEmitter` allows emitting any number of values - making this a land - // mine, since we tend to think of `emit` as interchangeable. - // This hack only works if the extra value is not `undefined`, so this isn't - // full-proof, but it works for most cases. - emit(name: string, value: any, ...no_extra_args_allowed: Array): void, -} - -declare class atom$Gutter { - name: string, - destroy(): void, - decorateMarker( - marker: atom$Marker, - options?: {'class'?: string, item?: Object | HTMLElement}, - ): atom$Decoration, - show(): void, - hide(): void, - onDidDestroy(callback: () => void): IDisposable, -} - -declare class atom$Marker { - destroy(): void, - getBufferRange(): atom$Range, - getStartBufferPosition(): atom$Point, - onDidChange(callback: (event: { - oldHeadScreenPosition: atom$Point, - newHeadScreenPosition: atom$Point, - oldTailScreenPosition: atom$Point, - newTailScreenPosition: atom$Point, - - oldHeadBufferPosition: atom$Point, - newHeadBufferPosition: atom$Point, - oldTailBufferPosition: atom$Point, - newTailBufferPosition: atom$Point, - - isValid: boolean, - textChanged: boolean, - }) => void): IDisposable, - isValid(): boolean, - isDestroyed(): boolean, - onDidDestroy(callback: () => mixed): IDisposable, - setBufferRange( - range: atom$RangeLike, - properties?: {reversed: boolean}, - ): void, - id: number, -} - -declare class atom$ServiceHub { - provide(keyPath: string, version: string, service: T): IDisposable, - consume( - keyPath: string, - versionRange: string, - callback: (provider: T) => mixed - ): IDisposable, -} - -type atom$PackageMetadata = { - name: string, - version: string, -}; - -declare class atom$PackageManager { - // Event Subscription - onDidLoadInitialPackages(callback: () => void): IDisposable, - onDidActivateInitialPackages(callback: () => void): IDisposable, - onDidActivatePackage(callback: (pkg: atom$Package) => mixed): IDisposable, - onDidDeactivatePackage(callback: (pkg: atom$Package) => mixed): IDisposable, - onDidLoadPackage(callback: (pkg: atom$Package) => mixed): IDisposable, - onDidTriggerActivationHook(activationHook: string, callback: () => mixed): IDisposable, - - // Package system data - getApmPath(): string, - getPackageDirPaths(): Array, - - // General package data - resolvePackagePath(name: string): ?string, - isBundledPackage(name: string): boolean, - - // Enabling and disabling packages - enablePackage(name: string): ?atom$Package, - disablePackage(name: string): ?atom$Package, - isPackageDisabled(name: string): boolean, - - // Accessing active packages - getActivePackage(name: string): ?atom$Package, - getActivePackages(): Array, - isPackageActive(name: string): boolean, - - // Activating and deactivating packages - activatePackage(name: string): Promise, - - // Accessing loaded packages - getLoadedPackage(name: string): ?atom$Package, - getLoadedPackages(): Array, - isPackageLoaded(name: string): boolean, - - // Accessing available packages - getAvailablePackageNames(): Array, - getAvailablePackageMetadata(): Array, - - // (Undocumented.) - activate(): Promise, - deactivatePackages(): void, - deactivatePackage(name: string, suppressSerialization?: boolean): void, - emitter: atom$Emitter, - loadPackage(name: string): void, - loadPackages(): void, - serializePackage(pkg: atom$Package): void, - serviceHub: atom$ServiceHub, - packageDirPaths: Array, - triggerActivationHook(hook: string): void, - triggerDeferredActivationHooks(): void, - unloadPackage(name: string): void, - unloadPackages(): void, -} - -declare class atom$StyleManager { - // Event Subscription - - // Reading Style Elements - getStyleElements(): Array, - - // Paths - getUserStyleSheetPath(): string, - - // (Undocumented.) - addStyleSheet( - source: string, - params: { - sourcePath?: string, - context?: boolean, - priority?: number, - skipDeprecatedSelectorsTransformation?: boolean - } - ): IDisposable, -} - -type atom$PaneSplitParams = { - copyActiveItem?: boolean, - items?: Array, -}; - -type atom$PaneSplitOrientation = 'horizontal' | 'vertical'; -type atom$PaneSplitSide = 'before' | 'after'; - -// Undocumented class -declare class atom$applicationDelegate { - focusWindow(): Promise, -} - -type atom$PaneParams = { - activeItem?: Object, - applicationDelegate: atom$applicationDelegate, - focused?: boolean, - container: Object, - config: atom$Config, - notificationManager: atom$NotificationManager, - deserializerManager: atom$DeserializerManager, - items?: Array, - itemStackIndices?: Array, - flexScale?: number, -}; - -declare class atom$Pane { - // Items - addItem(item: Object, options?: {index?: number, pending?: boolean}): Object, - getItems(): Array, - getActiveItem(): ?Object, - itemAtIndex(index: number): ?Object, - getActiveItemIndex(): number, - activateItem(item: Object): ?Object, - activateItemAtIndex(index: number): void, - moveItemToPane(item: Object, pane: atom$Pane, index: number): void, - destroyItem(item: Object, force?: boolean): boolean | Promise, - itemForURI(uri: string): Object, - - // Event subscriptions. - onDidAddItem(cb: (event: {item: Object, index: number}) => void): IDisposable, - onDidRemoveItem(cb: (event: {item: Object, index: number}) => void): IDisposable, - onWillRemoveItem(cb: (event: {item: Object, index: number}) => void): IDisposable, - onDidDestroy(cb: () => void): IDisposable, - onDidChangeFlexScale(cb: (newFlexScale: number) => void): IDisposable, - onWillDestroy(cb: () => void): IDisposable, - observeActiveItem(cb: (item: ?Object) => void): IDisposable, - - // Lifecycle - isActive(): boolean, - activate(): void, - destroy(): void, - - // Splitting - splitLeft(params?: atom$PaneSplitParams): atom$Pane, - splitRight(params?: atom$PaneSplitParams): atom$Pane, - splitUp(params?: atom$PaneSplitParams): atom$Pane, - splitDown(params?: atom$PaneSplitParams): atom$Pane, - split( - orientation: atom$PaneSplitOrientation, - side: atom$PaneSplitSide, - params?: atom$PaneSplitParams, - ): atom$Pane, - - // Undocumented Methods - constructor(params: atom$PaneParams): atom$Pane, - clearPendingItem(): void, - getFlexScale(): number, - getParent(): Object, - removeItem(item: Object, moved: ?boolean): void, - setActiveItem(item: Object): Object, - setFlexScale(flexScale: number): number, - getContainer(): atom$PaneContainer, - - element: HTMLElement, -} - -declare type atom$PaneItem = { - // These are all covariant, meaning that these props are read-only. Therefore we can assign an - // object with more strict requirements to an variable of this type. - +getTitle: () => string, - +getLongTitle?: () => string, - +getIconName?: () => string, - +getURI?: () => string, - +onDidChangeIcon?: (cb: (icon: string) => void) => IDisposable, - +onDidChangeTitle?: (cb: (title: string) => void) => IDisposable, - +serialize?: () => Object, -} - -// Undocumented class -declare class atom$PaneAxis { - getFlexScale(): number, - setFlexScale(flexScale: number): number, - getItems(): Array, -} - -// Undocumented class -declare class atom$PaneContainer { - constructor({ - config: atom$Config, - applicationDelegate: atom$applicationDelegate, - notificationManager: atom$NotificationManager, - deserializerManager: atom$DeserializerManager, - }): atom$PaneContainer, - destroy(): void, - getActivePane(): atom$Pane, - getActivePaneItem(): ?Object, - getLocation(): atom$PaneLocation, - getPanes(): Array, - getPaneItems(): Array, - observePanes(cb: (pane: atom$Pane) => void): IDisposable, - onDidAddPane(cb: (event: {pane: atom$Pane}) => void): IDisposable, - onDidDestroyPane(cb: (event: {pane: atom$Pane}) => void): IDisposable, - onWillDestroyPane(cb: (event: {pane: atom$Pane}) => void): IDisposable, - onDidAddPaneItem(cb: (item: atom$PaneItem) => void): IDisposable, - onDidDestroyPaneItem(cb: (item: atom$Pane) => void): IDisposable, - paneForItem(item: Object): ?atom$Pane, - serialize(): Object, -} - -declare class atom$Panel { - // Construction and Destruction - destroy(): void, - - // Event Subscription - onDidChangeVisible(callback: (visible: boolean) => any): IDisposable, - onDidDestroy(callback: (panel: atom$Panel) => any): IDisposable, - - // Panel Details - getElement(): HTMLElement, - getItem(): any, - getPriority(): number, - isVisible(): boolean, - hide(): void, - show(): void, -} - -type atom$PointObject = {row: number, column: number}; - -type atom$PointLike = atom$Point -| [number, number] -| atom$PointObject; - -declare class atom$Point { - static fromObject(object: atom$PointLike, copy: ? boolean): atom$Point, - constructor(row: number, column: number): void, - row: number, - column: number, - copy(): atom$Point, - negate(): atom$Point, - - // Comparison - min(point1: atom$PointLike, point2: atom$PointLike): atom$Point, - compare(other: atom$PointLike): -1 | 0 | 1, - isEqual(otherRange: atom$PointLike): boolean, - isLessThan(other: atom$PointLike): boolean, - isLessThanOrEqual(other: atom$PointLike): boolean, - isGreaterThan(other: atom$PointLike): boolean, - isGreaterThanOrEqual(other: atom$PointLike): boolean, - - // Operations - translate(other: atom$PointLike): atom$Point, - - // Conversion - serialize(): Array, - toArray(): Array, -} - -type atom$RangeObject = { - start: atom$PointObject, - end: atom$PointObject, -}; - -type atom$RangeLike = atom$Range - | atom$RangeObject // TODO: Flow doesn't really handle the real signature below... - | [atom$PointLike, atom$PointLike] - | { - start: atom$PointLike, - end: atom$PointLike, - }; - -declare class atom$Range { - static fromObject( - object: atom$RangeLike, - copy?: boolean, - ): atom$Range, - constructor(pointA: atom$PointLike, pointB: atom$PointLike): void, - compare(other: atom$Range): number, - start: atom$Point, - end: atom$Point, - isEmpty(): boolean, - isEqual(otherRange: atom$RangeLike): boolean, - intersectsWith(otherRange: atom$RangeLike, exclusive?: boolean): boolean, - containsPoint(point: atom$PointLike, exclusive?: boolean): boolean, - containsRange(other: atom$Range, exclusive?: boolean): boolean, - union(other: atom$Range): atom$Range, - serialize(): Array>, - translate(startDelta: atom$PointLike, endDelta?: atom$PointLike): atom$Range, - getRowCount(): number, -} - -type RawStatusBarTile = { - item: HTMLElement, - priority: number, -}; - -type atom$StatusBarTile = { - getPriority(): number, - getItem(): HTMLElement, - destroy(): void, -}; - -declare class atom$ScopeDescriptor { - constructor(object: {scopes: Array}): void, - getScopesArray(): Array, -} - -/** - * This API is defined at https://github.com/atom/status-bar. - */ -declare class atom$StatusBar { - addLeftTile(tile: RawStatusBarTile): atom$StatusBarTile, - addRightTile(tile: RawStatusBarTile): atom$StatusBarTile, - getLeftTiles(): Array, - getRightTiles(): Array, -} - -// https://github.com/atom/atom/blob/v1.9.0/src/text-editor-registry.coffee -declare class atom$TextEditorRegistry { - add(editor: atom$TextEditor): IDisposable, - remove(editor: atom$TextEditor): boolean, - observe(callback: (editor: atom$TextEditor) => void): IDisposable, - - // Added in 1.11.0 (These are typed optional until older Atoms are dropped) - build?: (params: atom$TextEditorParams) => atom$TextEditor, - - // Private - editors: Set, -} - -declare class atom$ThemeManager { - // Event Subscription - /** - * As recent as Atom 1.0.10, the implementation of this method was: - * - * ``` - * onDidChangeActiveThemes: (callback) -> - * @emitter.on 'did-change-active-themes', callback - * @emitter.on 'did-reload-all', callback # TODO: Remove once deprecated pre-1.0 APIs are gone - * ``` - * - * Due to the nature of CoffeeScript, onDidChangeActiveThemes returns a Disposable even though it - * is not documented as doing so. However, the Disposable that it does return removes the - * subscription on the 'did-reload-all' event (which is supposed to be deprecated) rather than the - * 'did-change-active-themes' one. - */ - onDidChangeActiveThemes(callback: () => mixed): IDisposable, - - // Accessing Loaded Themes - getLoadedThemeNames(): Array, - getLoadedThemes(): Array, // TODO: Define undocumented ThemePackage class. - - // Accessing Active Themes - getActiveThemeNames(): Array, - getActiveThemes(): Array, // TODO: Define undocumented ThemePackage class. - - // Managing Enabled Themes - getEnabledThemeNames(): Array, - - // Private - activateThemes(): Promise, - requireStylesheet(stylesheetPath: string): IDisposable, -} - -type atom$TooltipsPlacementOption = 'top' | 'bottom' | 'left' | 'right' | 'auto'; - -type atom$TooltipsAddOptions = { - title?: string, - item?: HTMLElement, - keyBindingCommand?: string, - keyBindingTarget?: HTMLElement, - animation?: boolean, - container?: string | false, - delay?: number | {show: number, hide: number}, - placement?: atom$TooltipsPlacementOption | () => atom$TooltipsPlacementOption, - trigger?: string, -}; - -type atom$Tooltip = { - hide(): void; - getTooltipElement(): HTMLElement, -}; - -declare class atom$TooltipManager { - tooltips: Map>; - add( - target: HTMLElement, - options: atom$TooltipsAddOptions, - ): IDisposable, -} - -type InsertTextOptions = { - select: boolean, - autoIndent: boolean, - autoIndentNewline: boolean, - autoDecreaseIndent: boolean, - normalizeLineEndings: ?boolean, - undo: string, -}; - -type DecorateMarkerParams = { - type: 'line', - class: string, - onlyHead?: boolean, - onlyEmpty?: boolean, - onlyNonEmpty?: boolean, -} | { - type: 'gutter', - item?: HTMLElement, - class?: string, - onlyHead?: boolean, - onlyEmpty?: boolean, - onlyNonEmpty?: boolean, - gutterName?: string, -} | { - type: 'highlight', - class?: string, - gutterName?: string, -} | { - type: 'overlay', - item: Object, - position?: 'head' | 'tail', // Defaults to 'head' when unspecified. -} | { - type: 'block', - item: HTMLElement, - position?: 'before' | 'after', // Defaults to 'before' when unspecified. -}; - -type ChangeCursorPositionEvent = { - oldBufferPosition: atom$Point, - oldScreenPosition: atom$Point, - newBufferPosition: atom$Point, - newScreenPosition: atom$Point, - textChanged: boolean, - cursor: atom$Cursor, -}; - -type MarkerOptions = {| - reversed?: boolean, - tailed?: boolean, - invalidate?: 'never' | 'surround' | 'overlap' | 'inside' | 'touch', - exclusive?: boolean, -|}; - -declare class atom$TextEditor extends atom$Model { - id: number, - - // Event Subscription - onDidChange(callback: () => void): IDisposable, - onDidChangePath(callback: (newPath: string) => mixed): IDisposable, - onDidStopChanging(callback: () => void): IDisposable, - onDidChangeCursorPosition(callback: (event: ChangeCursorPositionEvent) => mixed): - IDisposable, - onDidDestroy(callback: () => mixed): IDisposable, - onDidSave(callback: (event: {path: string}) => mixed): IDisposable, - getBuffer(): atom$TextBuffer, - observeGrammar(callback: (grammar: atom$Grammar) => mixed): IDisposable, - onWillInsertText(callback: (event: {cancel: () => void, text: string}) => void): - IDisposable, - // Note that the range property of the event is undocumented. - onDidInsertText(callback: (event: {text: string, range: atom$Range}) => mixed): IDisposable, - onDidChangeSoftWrapped(callback: (softWrapped: boolean) => mixed): IDisposable, - - // File Details - getTitle: () => string, - getLongTitle(): string, - /** - * If you open Atom via Spotlight such that it opens with a tab named - * "untitled" that does not correspond to a file on disk, this will return - * null. - */ - getPath(): ?string, - getURI: () => ?string, - insertNewline(): void, - isModified: () => boolean, - isEmpty(): boolean, - getEncoding(): buffer$Encoding, - setEncoding(encoding: string): void, - getTabLength() : number, - getSoftTabs(): boolean, - - // File Operations - save(): void, - // DO NOT USE: Doesn't work with remote text buffers! - // saveAs(filePath: string): void, - - // Reading Text - getText(): string, - getTextInBufferRange(range: atom$RangeLike): string, - getLineCount(): number, - - // Mutating Text - setText(text: string, options?: InsertTextOptions): void, - setTextInBufferRange( - range: atom$Range | Array, - text: string, - options?: { - normalizeLineEndings?: boolean, - undo?: string, - }, - ): atom$Range, - insertText(text: string): Array | false, - delete: () => void, - backspace: () => void, - duplicateLines: () => void, - - // History - createCheckpoint(): atom$TextBufferCheckpoint, - revertToCheckpoint(checkpoint: atom$TextBufferCheckpoint): boolean, - transact(fn: () => mixed, _: void): void, - transact(groupingInterval: number, fn: () => mixed): void, - - // TextEditor Coordinates - screenPositionForBufferPosition( - bufferPosition: atom$PointLike, - options?: { - wrapBeyondNewlines?: boolean, - wrapAtSoftNewlines?: boolean, - screenLine?: boolean, - }, - ): atom$Point, - bufferPositionForScreenPosition( - screenPosition: atom$PointLike, - options?: { - wrapBeyondNewlines?: boolean, - wrapAtSoftNewlines?: boolean, - screenLine?: boolean, - }, - ): atom$Point, - getVisibleRowRange(): ?[number, number], - - // Decorations - decorateMarker(marker: atom$Marker, decorationParams: DecorateMarkerParams): atom$Decoration, - decorationsForScreenRowRange( - startScreenRow: number, - endScreenRow: number, - ): {[markerId: string]: Array}, - getDecorations(options?: {class?: string, type?: string}): Array, - - // Markers - getDefaultMarkerLayer(): atom$DisplayMarkerLayer, - markBufferPosition(position: atom$PointLike, options?: MarkerOptions): atom$Marker, - markBufferRange(range: atom$RangeLike, options?: MarkerOptions): atom$Marker, - markScreenRange(range: atom$RangeLike, options?: MarkerOptions): atom$Marker, - markScreenPosition(position: atom$PointLike, options?: MarkerOptions): atom$Marker, - - // Cursors - getCursors(): Array, - setCursorBufferPosition( - position: atom$PointLike, - options?: { - autoscroll?: boolean, - wrapBeyondNewlines?: boolean, - wrapAtSoftNewlines?: boolean, - screenLine?: boolean, - }): void, - getCursorBufferPosition(): atom$Point, - getCursorBufferPositions(): Array, - getCursorScreenPosition(): atom$Point, - getCursorScreenPositions(): Array, - getLastCursor(): atom$Cursor, - addCursorAtBufferPosition(point: atom$PointLike): atom$Cursor, - moveToBeginningOfLine(): void, - moveToEndOfLine(): void, - moveToBottom(): void, - - // Selections - getSelectedText(): string, - selectAll(): void, - getSelectedBufferRange(): atom$Range, - getSelectedBufferRanges(): Array, - getSelections(): Array, - selectToBufferPosition(point: atom$Point): void, - setSelectedBufferRange( - bufferRange: atom$Range, - options?: { - reversed?: boolean, - preserveFolds?: boolean, - }, - ): void, - setSelectedBufferRanges( - bufferRanges: Array, - options?: { - reversed?: boolean, - preserveFolds?: boolean, - }, - ): void, - - // Folds - unfoldAll(): void, - - // Searching and Replacing - scanInBufferRange( - regex: RegExp, - range: atom$Range, - iterator: (foundMatch: { - match: mixed, - matchText: string, - range: atom$Range, - stop: () => mixed, - replace: (replaceWith: string) => mixed, - }) => mixed - ): void, - - scan( - regex: RegExp, - iterator: (foundMatch: { - match: mixed, - matchText: string, - range: atom$Range, - stop: () => mixed, - replace: (replaceWith: string) => mixed, - }) => mixed - ): void, - - // Tab Behavior - // Soft Wrap Behavior - // Indentation - indentationForBufferRow(bufferRow: number): number, - setTabLength(tabLength: number): void, - setSoftTabs(softTabs: boolean): void, - - lineTextForBufferRow(bufferRow: number): string, - - // Grammars - getGrammar(): atom$Grammar, - setGrammar(grammar: ?atom$Grammar): void, - - // Clipboard Operations - pasteText: (options?: Object) => void, - - // Managing Syntax Scopes - scopeDescriptorForBufferPosition( - bufferPosition: atom$PointLike, - ): atom$ScopeDescriptor, - - // Gutter - addGutter(options: { - name: string, - priority?: number, - visible?: boolean, - }): atom$Gutter, - observeGutters(callback: (gutter: atom$Gutter) => void): IDisposable, - getGutters(): Array, - gutterWithName(name: string): ?atom$Gutter, - - // Scrolling the TextEditor - scrollToBufferPosition( - position: atom$Point | [?number, ?number], - options?: {center?: boolean} - ): void, - scrollToScreenPosition( - position: atom$Point | [?number, ?number], - options?: {center?: boolean} - ): void, - scrollToBottom(): void, - scrollToTop(): void, - - // TextEditor Rendering - getPlaceholderText(): string, - setPlaceholderText(placeholderText: string): void, - - // This is undocumented, but Nuclide uses it in the AtomTextEditor wrapper. - setLineNumberGutterVisible(lineNumberGutterVisible: boolean): void, - - // Editor Options - setSoftWrapped(softWrapped: boolean): void, - - isFoldedAtBufferRow(row: number): boolean, - getLastBufferRow(): number, - - // Undocumented Methods - getElement(): HTMLElement, - getDefaultCharWidth(): number, - getLineHeightInPixels(): number, - moveToTop(): void, - tokenForBufferPosition(position: atom$Point | [?number, ?number]): atom$Token, - onDidConflict(callback: () => void): IDisposable, - serialize: () => mixed, - foldBufferRowRange(startRow: number, endRow: number): void, - getNonWordCharacters(scope?: atom$ScopeDescriptor): string, -} - -/** - * This is not part of the official Atom 1.0 API. Nevertheless, we need to reach into this object - * via `atom$TextEditorElement` to do some things that we have no other way to do. - */ -declare class atom$TextEditorComponent { - domNode: HTMLElement, - scrollViewNode: HTMLElement, - presenter: atom$TextEditorPresenter, - refs: atom$TextEditorComponentRefs, - linesComponent: atom$LinesComponent, - // NOTE: This is typed as a property to allow overwriting. - startCursorBlinking: () => void, - stopCursorBlinking(): void, - pixelPositionForScreenPosition( - screenPosition: atom$Point, - clip?: boolean, - ): {top: number, left: number}, - screenPositionForMouseEvent(event: MouseEvent): atom$Point, - pixelPositionForMouseEvent( - event: MouseEvent, - linesClientRect?: {top: number, left: number, bottom: number, right: number}, - ): {top: number, left: number, bottom: number, right: number}, - invalidateBlockDecorationDimensions(decoration: atom$Decoration): void, -} - -/** - * This is not part of the official Atom 1.0 API. Nevertheless, we need to reach into this object - * via `atom$TextEditorComponent` to do some things that we have no other way to do. - */ -declare class atom$TextEditorPresenter { - startBlinkingCursors: () => void, - stopBlinkingCursors(visible: boolean): void, - updateLineNumberGutterState(): void, -} - -/** - * This is not part of the official Atom 1.0 API. Nevertheless, we need it to access - * the deepest dom element receiving DOM events. - */ -declare class atom$LinesComponent { - domNode: HTMLElement, - getDomNode(): HTMLElement, -} - -/** - * This is not part of the official Atom 1.0 API. Nevertheless, we need it to access - * the deepest dom element receiving DOM events. - */ -declare class atom$TextEditorComponentRefs { - lineTiles: HTMLElement, -} - -/** - * This is not part of the official Atom 1.0 API, but it really should be. This is the element that - * is returned when you run `atom.views.getView()`. - */ -declare class atom$TextEditorElement extends HTMLElement { - component: ?atom$TextEditorComponent, - getModel(): atom$TextEditor, - setModel(model: atom$TextEditor): void, - pixelPositionForBufferPosition( - bufferPosition: atom$PointLike, - ): {top: number, left: number}, - pixelPositionForScreenPosition(screenPosition: atom$Point): { - left: number, - top: number, - }, - - setScrollTop(scrollTop: number): void, - getScrollTop(): number, - - setScrollLeft(scrollLeft: number): void, - getScrollLeft(): number, - - getScrollHeight(): number, - getHeight(): number, - - onDidChangeScrollTop(callback: (scrollTop: number) => mixed): IDisposable, - onDidChangeScrollLeft(callback: (scrollLeft: number) => mixed): IDisposable, - - // Called when the editor is attached to the DOM. - onDidAttach(callback: () => mixed): IDisposable, - // Called when the editor is detached from the DOM. - onDidDetach(callback: () => mixed): IDisposable, - - // Undocumented Methods - - // `undefined` means no explicit width. `null` sets a zero width (which is almost certainly a - // mistake) so we don't allow it. - setWidth(width: number | void): void, -} - -declare class atom$ViewProvider { - modelConstructor: Function, -} - -declare class atom$ViewRegistry { - // Methods - addViewProvider( - modelConstructor: any, - createView?: (...args: Array) => ?HTMLElement - ): IDisposable, - getView(textEditor: atom$TextEditor): atom$TextEditorElement, - getView(notification: atom$Notification): HTMLElement, - getView(gutter: atom$Gutter): HTMLElement, - getView(panel: atom$Panel): HTMLElement, - getView(workspace: atom$Workspace): HTMLElement, - getView(object: Object): HTMLElement, - providers: Array, -} - -type atom$WorkspaceAddPanelOptions = { - item: Object, - visible?: boolean, - priority?: number, - className?: string, -}; - -type atom$TextEditorParams = { - buffer?: atom$TextBuffer, - lineNumberGutterVisible?: boolean, -}; - -type DestroyPaneItemEvent = { - item: atom$PaneItem, - pane: atom$Pane, - index: number, -}; - -type AddPaneItemEvent = { - item: atom$PaneItem, - pane: atom$Pane, - index: number, -}; - -type OnDidOpenEvent = { - uri: string, - item: mixed, - pane: atom$Pane, - index: number, -}; - -type AddTextEditorEvent = { - textEditor: atom$TextEditor, - pane: atom$Pane, - index: number, -}; - -declare class atom$Workspace { - // Event Subscription - observePanes(cb: (pane: atom$Pane) => void): IDisposable, - observeTextEditors(callback: (editor: atom$TextEditor) => mixed): IDisposable, - onDidAddTextEditor(callback: (event: AddTextEditorEvent) => mixed): IDisposable, - onDidChangeActivePaneItem(callback: (item: mixed) => mixed): IDisposable, - onDidDestroyPaneItem(callback: (event: DestroyPaneItemEvent) => mixed): IDisposable, - onDidAddPaneItem(callback: (event: AddPaneItemEvent) => mixed): IDisposable, - observeActivePaneItem(callback: (item: ?mixed) => mixed): IDisposable, - onDidStopChangingActivePaneItem(callback: (item: ?mixed) => mixed): IDisposable, - observePaneItems(callback: (item: mixed) => mixed): IDisposable, - onWillDestroyPaneItem( - callback: (event: {item: mixed, pane: mixed, index: number}) => mixed - ): IDisposable, - onDidOpen(callback: (event: OnDidOpenEvent) => mixed): IDisposable, - - getElement(): HTMLElement, - - // Opening - open( - uri?: string, - options?: { - activePane?: boolean, - initialLine?: number, - initialColumn?: number, - pending?: boolean, - split?: string, - searchAllPanes?: boolean, - } - ): Promise, - openURIInPane( - uri?: string, - pane: atom$Pane, - options?: { - initialLine?: number, - initialColumn?: number, - activePane?: boolean, - searchAllPanes?: boolean, - } - ): Promise, - isTextEditor(item: ?mixed): boolean, - /* Optional method because this was added post-1.0. */ - buildTextEditor: ((params: atom$TextEditorParams) => atom$TextEditor), - /* Optional method because this was added in 1.9.0 */ - handleGrammarUsed?: (grammar: atom$Grammar) => void, - reopenItem(): Promise, - addOpener(callback: (uri: string) => any): IDisposable, - hide(uriOrItem: string | Object): void, - toggle(uriOrItem: string | Object): void, - - // Pane Containers - getPaneContainers(): Array, - paneContainerForItem(item: ?mixed): ?atom$PaneContainer, - - // Pane Items - getPaneItems(): Array, - getActivePaneItem(): ?Object, - getTextEditors(): Array, - getActiveTextEditor(): ?atom$TextEditor, - - // Panes - getPanes(): Array, - getActivePane(): atom$Pane, - activateNextPane(): boolean, - activatePreviousPane(): boolean, - paneForURI(uri: string): atom$Pane, - paneForItem(item: mixed): ?atom$Pane, - - // Panels - panelContainers: {[location: string]: atom$PanelContainer}, - getBottomPanels(): Array, - addBottomPanel(options: atom$WorkspaceAddPanelOptions): atom$Panel, - getLeftPanels(): Array, - addLeftPanel(options: atom$WorkspaceAddPanelOptions): atom$Panel, - getRightPanels(): Array, - addRightPanel(options: atom$WorkspaceAddPanelOptions): atom$Panel, - getTopPanels(): Array, - addTopPanel(options: atom$WorkspaceAddPanelOptions): atom$Panel, - getModalPanels(): Array, - addModalPanel(options: atom$WorkspaceAddPanelOptions): atom$Panel, - - getLeftDock(): atom$Dock, - getRightDock(): atom$Dock, - getBottomDock(): atom$Dock, - getCenter(): atom$WorkspaceCenter, - - // Searching and Replacing - scan( - regex: RegExp, - options: { - paths?: Array, - onPathsSearched?: (numSearched: number) => mixed, - leadingContextLineCount?: number, - trailingContextLineCount?: number, - }, - iterator: ( - ?{ - filePath: string, - matches: Array<{ - leadingContextLines: Array, - lineText: string, - lineTextOffset: number, - range: atom$RangeLike, - matchText: string, - trailingContextLines: Array, - }>, - }, - Error, - ) => mixed, - ): Promise, - - destroyActivePaneItemOrEmptyPane(): void, - destroyActivePaneItem(): void, -} - -declare class atom$AbstractPaneContainer { - isVisible(): boolean, - show(): void, - hide(): void, - getActivePane(): atom$Pane, - getPanes(): Array, - onDidAddPaneItem((item: {item: Object}) => void): IDisposable, - state: { - size: number, - } -} - -declare class atom$Dock extends atom$AbstractPaneContainer { - // This is a woefully incomplete list, items can be added as needed from - // https://github.com/atom/atom/blob/master/src/dock.js - toggle(): void, -} - -declare class atom$WorkspaceCenter extends atom$AbstractPaneContainer { - activate(): void; - - // Pane Items - getPaneItems(): Array, - getActivePaneItem(): ?atom$PaneItem, - getTextEditors(): Array, - getActiveTextEditor(): ?atom$TextEditor, - - observeActivePaneItem(callback: atom$PaneItem => mixed): IDisposable; - onDidChangeActivePaneItem(callback: (item: mixed) => mixed): IDisposable; - // This should be removed soon anyway, it's currently deprecated. - paneContainer: Object; -} - -/** - * Extended Classes - */ - -declare class atom$BufferedNodeProcess { } - -declare class atom$BufferedProcess { - // Event Subscription - onWillThrowError( - callback: (errorObject: {error: Object, handle: mixed}) => mixed - ): IDisposable, - // Helper Methods - kill(): void, -} - -declare class atom$Clipboard { - // Methods - write(text: string, metadata?: mixed): void, - read(): string, - readWithMetadata(): { - metadata: ?mixed, - text: string, - }, -} - -declare class atom$ContextMenuManager { - add(itemsBySelector: {[cssSelector: string]: Array}): IDisposable, - itemSets: Array, - - // Undocumented methods - showForEvent(event: Event): void, - templateForEvent(event: Event): Array, -} - -declare class atom$ContextMenuItemSet { - items: Array, - selector: string, -} - -type atom$ContextMenuItem = { - command?: string, - created?: (event: MouseEvent) => void, - enabled?: boolean, - label?: string, - shouldDisplay?: (event: MouseEvent) => boolean, - submenu?: Array, - type?: string, - visible?: boolean, -}; - -type atom$Deserializer = { - name: string, - deserialize: (state: Object) => mixed, -}; - -declare class atom$DeserializerManager { - add(...deserializers: Array): IDisposable, - deserialize(state: Object, params?: Object): mixed, -} - -// Apparently it can sometimes include a `code` property. -declare class atom$GetEntriesError extends Error { - code?: string, -} - -declare class atom$Directory { - constructor(dirname?: string): atom$Directory, - - symlink: boolean, - - // Construction - create(mode?: number): Promise, - - // Event Subscription - onDidChange(callback: () => mixed): IDisposable, - - // Directory Metadata - isFile(): boolean, - isDirectory(): boolean, - exists():Promise, - - // Managing Paths - getPath(): string, - getBaseName(): string, - relativize(fullPath: string): string, - - // Event Subscription - onDidRename(callback: () => void): IDisposable, - onDidDelete(callback: () => void): IDisposable, - - // Traversing - getParent(): atom$Directory, - getFile(filename: string): atom$File, - getSubdirectory(dirname: string): atom$Directory, - getEntries( - callback: ( - error: ?atom$GetEntriesError, - entries: ?Array, - ) => mixed): void, - contains(path: string): boolean, -} - -declare class atom$File { - constructor(filePath?: string, symlink?: boolean): atom$File, - - symlink: boolean, - - // Construction - create(): Promise, - - // File Metadata - isFile(): boolean, - isDirectory(): boolean, - exists(): Promise, - setEncoding(encoding: string): void, - getEncoding(): string, - - // Event Subscription - onDidRename(callback: () => void): IDisposable, - onDidDelete(callback: () => void): IDisposable, - onDidChange(callback: () => void): IDisposable, - - // Managing Paths - getPath(): string, - getBaseName(): string, - - // Traversing - getParent(): atom$Directory, - - // Reading and Writing - read(flushCache?: boolean): Promise, - write(text: string): Promise, - writeSync(text: string): void, -} - -declare class atom$GitRepository extends atom$Repository { - // Unofficial API. - statuses: {[filePath: string]: number}, - // Return the `git-utils` async repo. - getRepo(): atom$GitRepositoryInternal, -} - -declare class atom$Grammar { - name: string, - scopeName: string, - tokenizeLines(text: string): Array>, -} - -type atom$GrammarToken = { - value: string, - scopes: Array, -}; - -declare class atom$GrammarRegistry { - // Event Subscription - onDidAddGrammar(callback: (grammar: atom$Grammar) => void): IDisposable, - - // Managing Grammars - grammarForScopeName(scopeName: string): ?atom$Grammar, - removeGrammarForScopeName(scopeName: string): ?atom$Grammar, - loadGrammarSync(grammarPath: string): atom$Grammar, - selectGrammar(filePath: string, fileContents: string): atom$Grammar, - - // Private API - clear(): IDisposable, -} - -declare class atom$HistoryManager { - removeProject(paths: Array): void, - getProjects(): Array, -} - -declare class atom$HistoryProject { - get paths(): Array; - get lastOpened(): Date; -} - -type atom$KeyBinding = Object; - -declare class atom$KeymapManager { - - // Event Subscription - onDidMatchBinding(callback: (event: { - keystrokes: string, - binding: atom$KeyBinding, - keyboardEventTarget: HTMLElement, - }) => mixed): IDisposable, - - onDidPartiallyMatchBinding(callback: (event: { - keystrokes: string, - partiallyMatchedBindings: atom$KeyBinding, - keyboardEventTarget: HTMLElement, - }) => mixed): IDisposable, - - onDidFailToMatchBinding(callback: (event: { - keystrokes: string, - partiallyMatchedBindings: atom$KeyBinding, - keyboardEventTarget: HTMLElement, - }) => mixed): IDisposable, - - onDidFailToReadFile(callback: (error: { - message: string, - stack: string, - }) => mixed): IDisposable, - - // Adding and Removing Bindings - add(source: string, bindings: Object): void, - - // Accessing Bindings - getKeyBindings(): Array, - findKeyBindings(params: { - keystrokes?: string, - command?: string, - target?: HTMLElement, - }): Array, - - // Managing Keymap Files - loadKeymap(path: string, options?: {watch: boolean}): void, - watchKeymap(path: string): void, - - // Managing Keyboard Events - handleKeyboardEvent(event: Event): void, - keystrokeForKeyboardEvent(event: Event): string, - getPartialMatchTimeout(): number, - - static buildKeydownEvent( - key: string, - options: { - target: HTMLElement, - alt?: boolean, - cmd?: boolean, - ctrl?: boolean, - shift?: boolean, - }, - ): Event, -} - -declare class atom$MenuManager { - add(items: Array): IDisposable, - update(): void, - - // Private API - template: Array, -} - -declare class atom$Project { - // Event Subscription - onDidChangePaths(callback: (projectPaths: Array) => mixed): IDisposable, - onDidAddBuffer(callback: (buffer: atom$TextBuffer) => mixed): IDisposable, - observeBuffers(callback: (buffer: atom$TextBuffer) => mixed): IDisposable, - - // Accessing the git repository - getRepositories(): Array, - repositoryForDirectory(directory: atom$Directory): Promise, - - // Managing Paths - getPaths(): Array, - addPath(projectPath: string): void, - setPaths(paths: Array): void, - removePath(projectPath: string): void, - getDirectories(): Array, - relativizePath(relativizePath?: string): Array, // [projectPath: ?string, relativePath: string] - relativize(filePath: string): string, - contains(path: string): boolean, - - // Private API - findBufferForPath(path: string): ?atom$TextBuffer, - addBuffer(buffer: atom$TextBuffer): void, - removeBuffer(buffer: atom$TextBuffer): void, - getBuffers(): Array, -} - -type TextBufferScanIterator = (arg: { - match: Array, - matchText: string, - range: atom$Range, - stop(): void, - replace(replacement: string): void, -}) => void; - -// This happens to be a number but it would be better if the type could be entirely opaque. All you -// need to know is that if something needs a checkpoint you should only pass it values received from -// TextBuffer::createCheckpoint -type atom$TextBufferCheckpoint = number; - -// TextBuffer did-change/will-change -type atom$TextEditEvent = { - oldRange: atom$Range, - newRange: atom$Range, - oldText: string, - newText: string, -}; - -type atom$AggregatedTextEditEvent = { - changes: Array, -}; - -declare class atom$TextBuffer { - constructor(text?: string): atom$TextBuffer, - constructor(params?: { - filePath?: string, - text?: string, - }): atom$TextBuffer, - - file: ?atom$File, - - // Mixin - static deserialize: (state: Object, params: Object) => mixed, - - // Events - onWillChange(callback: (event: atom$TextEditEvent) => mixed): IDisposable, - onDidChange(callback: (event: atom$TextEditEvent) => mixed): IDisposable, - onDidChangeText(callback: (event: atom$AggregatedTextEditEvent) => mixed): IDisposable, - onDidStopChanging(callback: () => mixed): IDisposable, - onDidConflict(callback: () => mixed): IDisposable, - onDidChangeModified(callback: () => mixed): IDisposable, - onDidUpdateMarkers(callback: () => mixed): IDisposable, - onDidCreateMarker(callback: () => mixed): IDisposable, - onDidChangePath(callback: () => mixed): IDisposable, - onDidChangeEncoding(callback: () => mixed): IDisposable, - onWillSave(callback: () => mixed): IDisposable, - onDidSave(callback: (event: {path: string}) => mixed): IDisposable, - onDidDelete(callback: () => mixed): IDisposable, - onWillReload(callback: () => mixed): IDisposable, - onDidReload(callback: () => mixed): IDisposable, - onDidDestroy(callback: () => mixed): IDisposable, - onWillThrowWatchError(callback: () => mixed): IDisposable, - - // File Details - // DO NOT USE (T21363106): Doesn't work with remote text buffers! - // setPath(filePath: string): void, - getPath(): ?string, - setEncoding(encoding: string): void, - getEncoding(): string, - getUri(): string, - getId(): string, - - // Reading Text - isEmpty(): boolean, - getText(): string, - getTextInRange(range: atom$RangeLike): string, - getLineCount(): number, - getLines(): Array, - getLastLine(): string, - lineForRow(row: number): string, - lineEndingForRow(row: number): string, - lineLengthForRow(row: number): number, - isRowBlank(row: number): boolean, - previousNonBlankRow(startRow: number): ?number, - nextNonBlankRow(startRow: number): ?number, - - // Mutating Text - setText: (text: string) => atom$Range, - setTextInRange(range: atom$RangeLike, text: string, options?: Object): atom$Range, - setTextViaDiff(text: string): void, - insert( - position: atom$Point, - text: string, - options?: { - normalizeLineEndings?: boolean, - undo?: string, - }, - ): atom$Range, - append(text: string, options: ?{ - normalizeLineEndings?: boolean, - undo?: string, - }): atom$Range, - delete(range: atom$Range): atom$Range, - deleteRows(startRow: number, endRow: number): atom$Range, - - // History - undo(): void, - redo(): void, - transact(fn: () => mixed, _: void): void, - transact(groupingInterval: number, fn: () => mixed): void, - clearUndoStack(): void, - createCheckpoint(): atom$TextBufferCheckpoint, - revertToCheckpoint(checkpoint: atom$TextBufferCheckpoint): boolean, - groupChangesSinceCheckpoint(checkpoint: atom$TextBufferCheckpoint): boolean, - // TODO describe the return type more precisely. - getChangesSinceCheckpoint(checkpoint: atom$TextBufferCheckpoint): Array, - - // Search And Replace - scan(regex: RegExp, iterator: TextBufferScanIterator): void, - scanInRange(regex: RegExp, range: atom$Range, iterator: TextBufferScanIterator): void, - backwardsScanInRange(regex: RegExp, range: atom$Range, iterator: TextBufferScanIterator): void, - - // Buffer Range Details - getLastRow(): number, - getRange(): atom$Range, - rangeForRow(row: number, includeNewLine?: boolean): atom$Range, - - // Position/Index mapping - characterIndexForPosition(position: atom$PointLike): number, - positionForCharacterIndex(index: number): atom$Point, - - // Buffer Operations - reload(): void, - load(): Promise, - save(): void, - - isInConflict(): boolean, - isModified(): boolean, - - // Private APIs - cachedDiskContents: ?string, - emitter: atom$Emitter, - refcount: number, - loaded: boolean, - wasModifiedBeforeRemove: boolean, - finishLoading(): atom$TextBuffer, - updateCachedDiskContents(flushCache?: boolean, callback?: () => mixed): Promise, - emitModifiedStatusChanged(changed: boolean): void, - destroy(): void, - isDestroyed(): boolean, - applyChange: () => void, - shouldDestroyOnFileDelete?: () => boolean, -} - -declare class atom$Notification { - // Event Subscription - onDidDismiss(callback: () => mixed): IDisposable, - onDidDisplay(callback: () => mixed): IDisposable, - - // Methods - getType(): string, - getMessage(): string, - getOptions(): Object, - dismiss(): void, -} - -type atom$NotificationButton = { - text: string, - className?: string, - onDidClick?: () => mixed, -}; - -type atom$NotificationOptions = { - detail?: string, - dismissable?: boolean, - description?: string, - icon?: string, - buttons?: Array, -}; - -declare class atom$NotificationManager { - // Events - onDidAddNotification(callback: (notification: atom$Notification) => void): IDisposable, - - // Adding Notifications - add(type: string, message: string, options?: atom$NotificationOptions): atom$Notification, - addSuccess(message: string, options?: atom$NotificationOptions): atom$Notification, - addInfo(message: string, options?: atom$NotificationOptions): atom$Notification, - addWarning(message: string, options?: atom$NotificationOptions): atom$Notification, - addError(message: string, options?: atom$NotificationOptions): atom$Notification, - addFatalError(message: string, options?: atom$NotificationOptions): atom$Notification, - - // Getting Notifications - getNotifications(): Array, -} - -// The items in this declaration are available off of `require('atom')`. -// This list is not complete. -declare module 'atom' { - declare var BufferedNodeProcess: typeof atom$BufferedNodeProcess; - declare var BufferedProcess: typeof atom$BufferedProcess; - declare var CompositeDisposable: typeof atom$CompositeDisposable; - declare var Directory: typeof atom$Directory; - declare var Disposable: typeof atom$Disposable; - declare var Emitter: typeof atom$Emitter; - declare var File: typeof atom$File; - declare var GitRepository: typeof atom$GitRepository; - declare var Notification: typeof atom$Notification; - declare var Point: typeof atom$Point; - declare var Range: typeof atom$Range; - declare var TextBuffer: typeof atom$TextBuffer; - declare var TextEditor: typeof atom$TextEditor; -} - -// Make sure that common types can be referenced without the `atom$` prefix -// in type declarations. -declare var Cursor: typeof atom$Cursor; -declare var Panel: typeof atom$Panel; -declare var TextEditor: typeof atom$TextEditor; - -type atom$UnhandledErrorEvent = { - originalError: Object, - message: string, - url: string, - line: number, - column: number, -}; - -// The properties of this type match the properties of the `atom` global. -// This list is not complete. -type AtomGlobal = { - // Properties - appVersion: string, - atomScriptMode: ?boolean, // Added by nuclide-atom-script. - clipboard: atom$Clipboard, - commands: atom$CommandRegistry, - config: atom$Config, - contextMenu: atom$ContextMenuManager, - applicationDelegate: atom$applicationDelegate, - deserializers: atom$DeserializerManager, - grammars: atom$GrammarRegistry, - history: atom$HistoryManager, - keymaps: atom$KeymapManager, - menu: atom$MenuManager, - notifications: atom$NotificationManager, - packages: atom$PackageManager, - styles: atom$StyleManager, - themes: atom$ThemeManager, - textEditors: atom$TextEditorRegistry, - tooltips: atom$TooltipManager, - views: atom$ViewRegistry, - workspace: atom$Workspace, - project: atom$Project, - devMode: boolean, - - // Event Subscription - onWillThrowError(callback: (event: atom$UnhandledErrorEvent) => mixed): IDisposable, - onDidThrowError(callback: (event: atom$UnhandledErrorEvent) => mixed): IDisposable, - whenShellEnvironmentLoaded(callback: () => mixed): IDisposable, - - // Atom Details - inDevMode(): boolean, - inSafeMode(): boolean, - inSpecMode(): boolean, - getVersion(): string, - isReleasedVersion(): boolean, - getWindowLoadTime(): number, - - // This is an undocumented way to reach the Electron BrowserWindow. - // Use `electron.remote.getCurrentWindow` instead. - getCurrentWindow: void, - - // Messaging the User - confirm(options: { - buttons?: Array | {[buttonName: string]: () => mixed}, - detailedMessage?: string, - message: string, - }): ?number, - - open(params: { - pathsToOpen?: Array, - newWindow?: boolean, - devMode?: boolean, - safeMode?: boolean, - }): void, - reload(): void, - - // Undocumented Methods - getConfigDirPath(): string, - showSaveDialogSync(options: Object): string, - loadState(): Promise, - getLoadSettings(): Object, -}; - -declare var atom: AtomGlobal; - -type RepositoryDidChangeStatusCallback = (event: {path: string, pathStatus: number}) => mixed; -type RepositoryLineDiff = { - oldStart: number, - newStart: number, - oldLines: number, - newLines: number, -}; - -// Taken from the interface of [`GitRepository`][1], which is also implemented by -// `HgRepositoryClient`. -// -// [1]: https://github.com/atom/atom/blob/v1.7.3/src/git-repository.coffee -declare class atom$Repository { - constructor(path: string, options?: {refreshOnWindowFocus?: boolean}): void, - - // Event Subscription - onDidChangeStatus: (callback: RepositoryDidChangeStatusCallback) => IDisposable, - onDidChangeStatuses: (callback: () => mixed) => IDisposable, - - // Repository Details - getType: () => string, - getPath: () => string, - getWorkingDirectory: () => string, - isProjectAtRoot: () => boolean, - relativize: (aPath: string) => string, - getOriginURL: (aPath: ?string) => ?string, - - // Reading Status - isPathModified: (aPath: string) => boolean, - isPathNew: (aPath: string) => boolean, - isPathIgnored: (aPath: string) => boolean, - getDirectoryStatus: (aPath: string) => number, - getPathStatus: (aPath: string) => number, - getCachedPathStatus: (aPath: string) => ?number, - isStatusModified: (status: number) => boolean, - isStatusNew: (status: number) => boolean, - refreshStatus: () => Promise, - - // Retrieving Diffs - getDiffStats: (filePath: string) => {added: number, deleted: number}, - getLineDiffs: (aPath: string, text: string) => Array, - - // Checking Out - checkoutHead: (aPath: string) => boolean, - checkoutReference: (reference: string, create: boolean) => Promise, - - // Event Subscription - onDidDestroy(callback: () => mixed): IDisposable, - isDestroyed(): boolean, -} - -declare class atom$GitRepositoryInternal { - // Reading Status - isStatusModified: (status: number) => boolean, - isStatusNew: (status: number) => boolean, - isStatusIgnored: (status: number) => boolean, - isStatusStaged: (status: number) => boolean, - isStatusDeleted: (status: number) => boolean, -} - -// One of text or snippet is required. -// TODO(hansonw): use a union + intersection type -type atom$AutocompleteSuggestion = { - text?: string, - snippet?: string, - displayText?: string, - replacementPrefix?: string, - type?: ?string, - leftLabel?: ?string, - leftLabelHTML?: ?string, - rightLabel?: ?string, - rightLabelHTML?: ?string, - className?: ?string, - iconHTML?: ?string, - description?: ?string, - descriptionMoreURL?: ?string, -}; - -type atom$AutocompleteRequest = { - editor: TextEditor, - bufferPosition: atom$Point, - scopeDescriptor: string, - prefix: string, - activatedManually?: boolean, -}; - -type atom$AutocompleteProvider = { - +selector: string, - +getSuggestions: ( - request: atom$AutocompleteRequest, - ) => Promise>, - +onDidInsertSuggestion?: ( - insertedSuggestion: atom$SuggestionInsertedRequest, - ) => void, - +disableForSelector?: string, - +inclusionPriority?: number, - +excludeLowerPriority?: boolean, -}; - -type atom$SuggestionInsertedRequest = { - editor: atom$TextEditor, - triggerPosition: atom$Point, - suggestion: atom$AutocompleteSuggestion, -}; - -// Undocumented API. -declare class atom$Token { - value: string, - matchesScopeSelector(selector: string): boolean, -} - -declare class atom$Selection { - clear(): void, - getText(): string, - insertText( - text: string, - options?: { - select?: boolean, - autoIndent?: boolean, - autoIndentNewLine?: boolean, - autoDecreaseIdent?: boolean, - normalizeLineEndings?: boolean, - undo?: boolean, - }, - ): string, -} - -declare class atom$PanelContainer { - dock: atom$Dock, - element: HTMLElement, - emitter: atom$Emitter, - location: atom$PaneLocation, - panels: Array, - subscriptions: atom$CompositeDisposable, - viewRegistry: atom$ViewRegistry, - - getPanels(): Array, -}; diff --git a/flow-libs/bom.js.flow b/flow-libs/bom.js.flow deleted file mode 100644 index 5213ea95..00000000 --- a/flow-libs/bom.js.flow +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the license found in the LICENSE file in - * the root directory of this source tree. - * - * @flow - * @format - */ - -declare type PerformanceEntry$EntryType = - | 'frame' - | 'longtask' - | 'mark' - | 'measure' - | 'navigation' - | 'paint' - | 'resource'; - -declare type PerformanceObserverInit = {| - entryTypes: Array, -|}; - -declare type PerformanceEntryFilterOptions = {| - name?: string, - entryType?: PerformanceEntry$EntryType, - initiatorType?: string, -|}; - -declare type PerformanceObserverEntryList = {| - getEntries( - filterOptions?: PerformanceEntryFilterOptions, - ): Array, - getEntriesByName( - name: string, - type: PerformanceEntry$EntryType, - ): Array, - getEntriesByType(type: PerformanceEntry$EntryType): Array, -|}; - -declare type ResizeObserverEntry = {| - target: HTMLElement, - contentRect: DOMRectReadOnly, -|}; - -declare class PerformanceObserver { - constructor( - callback: (entries: PerformanceObserverEntryList) => void, - observer: this, - ): void, - observe(options: PerformanceObserverInit): void, - disconnect(): void, -} - -declare class ResizeObserver { - constructor(callback: (entries: Array) => void): void, - observe(target: HTMLElement): void, - unobserve(target: HTMLElement): void, - disconnect(): void, -} diff --git a/flow-libs/electron.js.flow b/flow-libs/electron.js.flow deleted file mode 100644 index a9bd9832..00000000 --- a/flow-libs/electron.js.flow +++ /dev/null @@ -1,905 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the license found in the LICENSE file in - * the root directory of this source tree. - * - * @flow - */ - -// The properties on this module depend on whether the importer is the main -// process or a renderer process. -declare module 'electron' { - // Main process: - declare var app: ?electron$app; - declare var autoUpdater: ?electron$autoUpdater; - declare var BrowserWindow: ?typeof electron$BrowserWindow; - declare var contentTracing: ?electron$contentTracing; - declare var dialog: ?electron$dialog; - declare var globalShortcut: ?electron$globalShortcut; - declare var ipcMain: ?electron$IpcMain; - declare var Menu: ?typeof electron$Menu; - declare var MenuItem: ?typeof electron$MenuItem; - declare var powerMonitor: ?electron$powerMonitor; - declare var powerSaveBlocker: ?electron$powerSaveBlocker; - declare var protocol: ?electron$protocol; - declare var session: ?electron$session; - declare var electron$Tray: ?typeof electron$Tray; - declare var webContents: ?electron$webContents; - - // Renderer process: - declare var desktopCapturer: ?electron$desktopCapturer; - declare var ipcRenderer: ?electron$IpcRenderer; - declare var remote: ?electron$remote; - declare var webFrame: ?electron$webFrame; - - // Both: - declare var clipboard: electron$clipboard; - declare var crashReporter: electron$crashReporter; - declare var nativeImage: electron$nativeImage; - declare var screen: electron$Screen; - declare var shell: electron$shell; - - declare type electron$BrowserWindow = electron$BrowserWindow; - declare type electron$Menu = electron$Menu; - declare type electron$MenuItem = electron$MenuItem; - declare type electron$NativeImage = electron$NativeImage; - declare type electron$Screen = electron$Screen; - declare type electron$WebContents = electron$WebContents; -} - -// very common struct -type electron$rect = { - x: number, - y: number, - width: number, - height: number, -}; - -//------------------------------------------------------------------------------ -// Custom DOM Elements -//------------------------------------------------------------------------------ - -/** - * https://github.com/electron/electron/blob/master/docs/api/file-object.md - */ - -// HTML5 File API but with a `path` attribute added. - -/** - * https://github.com/electron/electron/blob/master/docs/api/web-view-tag.md - */ - -declare class WebviewElement extends HTMLElement { - src: string, - nodeintegration: boolean, - disablewebsecurity: boolean, - - executeJavaScript(code: string, userGesture: ?boolean): void, - getTitle(): string, - // This used to be `getUrl`, but the old version was dropped in the electron bundled with Atom - // 1.12, and the new version exists at least in Atom 1.10.2 onward. - getURL(): string, - // Not sure when this was introduced - stop?: () => void, - insertCSS(code: string): void, - send(channel: string, ...args: Array): void, - openDevTools(): void, -} - -/** - * https://github.com/electron/electron/blob/master/docs/api/window-open.md - */ - -// window.open - -//------------------------------------------------------------------------------ -// Modules for the Main Process -//------------------------------------------------------------------------------ - -/** - * https://github.com/electron/electron/blob/master/docs/api/app.md - */ - -type electron$app = { - quit(): void, - exit(exitCode?: number): void, - relaunch(options?: {args?: Array, execPath?: string}): void, - isReady(): boolean, - focus(): void, - getAppPath(): string, - getPath(name: string): string, - setPath(name: string, path: string): void, - getVersion(): string, - getName(): string, - setName(name: string): void, - getLocale(): string, - makeSingleInstance(callback: (argv: Array, workingDirectory: string) => void): boolean, - releaseSingleInstance(): void, - disableHardwareAcceleration(): void, -}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/auto-updater.md - */ - -type electron$autoUpdater = {}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/browser-window.md - */ - -type electron$BrowserWindowOptions = { - width?: number, - height?: number, - x?: number, - y?: number, - useContentSize?: boolean, - center?: boolean, - minWidth?: number, - minHeight?: number, - maxWidth?: number, - maxHeight?: number, - resizable?: boolean, - movable?: boolean, - minimizable?: boolean, - maximizable?: boolean, - closable?: boolean, - focusable?: boolean, - alwaysOnTop?: boolean, - fullscreen?: boolean, - fullscreenable?: boolean, - skipTaskbar?: boolean, - kiosk?: boolean, - title?: string, - icon?: electron$NativeImage, - show?: boolean, - frame?: boolean, - parent?: electron$BrowserWindow, - modal?: boolean, - acceptFirstMouse?: boolean, - disableAutoHideCursor?: boolean, - autoHideMenuBar?: boolean, - enableLargerThanScreen?: boolean, - backgroundColor?: string, - hasShadow?: boolean, - darkTheme?: boolean, - transparent?: boolean, - type?: 'desktop' | 'dock' | 'toolbar' | 'splash' | 'notification' | - /* macOS */ 'desktop' | 'textured' | - /* Windows */ 'toolbar', - titleBarStyle?: 'default' | 'hidden' | 'hidden-inset', - thickFrame?: boolean, - webPreferences?: electron$BrowserWindowWebPreferences, -}; - -type electron$BrowserWindowWebPreferences = { - nodeIntegration?: boolean, - preload?: string, - session?: electron$session, - partition?: string, - zoomFactor?: number, - javascript?: boolean, - webSecurity?: boolean, - allowDisplayingInsecureContent?: boolean, - allowRunningInsecureContent?: boolean, - images?: boolean, - textAreasAreResizable?: boolean, - webgl?: boolean, - webaudio?: boolean, - plugins?: boolean, - experimentalFeatures?: boolean, - experimentalCanvasFeatures?: boolean, - scrollBounce?: boolean, - blinkFeatures?: string, - disableBlinkFeatures?: string, - defaultFontFamily?: { - standard?: string, - serif?: string, - sansSerif?: string, - monospace?: string, - }, - defaultFontSize?: number, - defaultMonospaceFontSize?: number, - minimumFontSize?: number, - defaultEncoding?: string, - backgroundThrottling?: boolean, - offscreen?: boolean, -}; - -type electron$BrowserWindowEvents = - | 'page-title-updated' - | 'close' - | 'closed' - | 'unresponsive' - | 'responsive' - | 'blur' - | 'focus' - | 'show' - | 'hide' - | 'ready-to-show' - | 'maximize' - | 'unmaximize' - | 'minimize' - | 'restore' - | 'resize' - | 'move' - | 'moved' - | 'enter-full-screen' - | 'leave-full-screen' - | 'enter-html-full-screen' - | 'leave-html-full-screen' - | 'context-menu' - | 'app-command' // Windows - | 'scroll-touch-begin' // macOS - | 'scroll-touch-end' // macOS - | 'swipe'; // macOS - -type electron$BrowserWindowListener = ( - event: electron$BrowserWindowEvents, - callback: (event: Object, ...args: Array) => void, -) => electron$BrowserWindow; - -declare class electron$BrowserWindow { - constructor(options: electron$BrowserWindowOptions): void, - on: electron$BrowserWindowListener, - once: electron$BrowserWindowListener, - removeAllListeners(event?: electron$BrowserWindowEvents): electron$BrowserWindow, - removeListener(event?: electron$BrowserWindowEvents, callback: Function): electron$BrowserWindow, - send(channel: string, ...args: Array): void, - - static getAllWindows(): Array, - static getFocusedWindow(): ?electron$BrowserWindow, - static fromWebContents(webContents: electron$WebContents): ?electron$BrowserWindow, - static fromId(id: number): ?electron$BrowserWindow, - static addDevToolsExtension(path: string): void, - static removeDevToolsExtension(name: string): void, - static getDevToolsExtensions(): {[name: string]: {[name: string]: string}}, - - webContents: electron$WebContents, - id: string, - destroy(): void, - close(): void, - focus(): void, - blur(): void, - isFocused(): boolean, - show(): void, - showInactive(): void, - hide(): void, - isVisible(): boolean, - isModal(): boolean, - maximize(): void, - unmaximize(): void, - isMaximized(): boolean, - minimize(): void, - restore(): void, - isMinimized(): boolean, - setFullScreen(flag: boolean): void, - isFullScreen(): boolean, - setAspectRatio(aspectRatio: number, extraSize?: {width: number, height: number}): void, // macOS - setBounds(options: electron$rect, /* macOS */ animate?: boolean): void, - getBounds(): electron$rect, - setSize(width: number, height: number, /* macOS */ animate?: boolean): void, - getSize(): [number, number], - setContentSize(width: number, height: number, /* macOS */ animate?: boolean): void, - getContentSize(): [number, number], - setMinimumSize(width: number, height: number): void, - getMinimumSize(): [number, number], - setMaximumSize(width: number, height: number): void, - getMaximumSize(): [number, number], - setResizable(resizable: boolean): void, - isResizable(): boolean, - setMovable(movable: boolean): void, // macOS Windows - isMovable(): boolean, // macOS Windows - setMinimizable(minimizable: boolean): void, // macOS Windows - isMinimizable(): boolean, // macOS Windows - setMaximizable(maximizable: boolean): void, // macOS Windows - isMaximizable(): boolean, // macOS Windows - setFullScreenable(fullscreenable: boolean): void, - isFullScreenable(): boolean, - setClosable(closable: boolean): void, // macOS Windows - isClosable(): boolean, // macOS Windows - setAlwaysOnTop(flag: boolean): void, - isAlwaysOnTop(): boolean, - center(): void, - setPosition(x: number, y: number, /* macOS */ animate?: boolean): void, - getPosition(): [number, number], - setTitle(title: string): void, - getTitle(): string, - setSheetOffset(offsetY: number, offsetX?: number): void, // macOS - flashFrame(flag: boolean): void, - setSkipTaskbar(skip: boolean): void, - setKiosk(flag: boolean): void, - isKiosk(): boolean, - getNativeWindowHandle(): Buffer, - hookWindowMessage(message: number, callback: Function): void, // Windows - isWindowMessageHooked(message: number): boolean, // Windows - unhookWindowMessage(message: number): void, // Windows - unhookAllWindowMessages(): void, // Windows - setRepresentedFilename(filename: string): void, // macOS - getRepresentedFilename(): string, // macOS - setDocumentEdited(edited: boolean): void, // macOS - isDocumentEdited(): boolean, // macOS - focusOnWebView(): void, - blurWebView(): void, - capturePage(rect: electron$rect, callback: (image: electron$NativeImage) => void): void, - capturePage(callback: (image: electron$NativeImage) => void): void, - loadURL( - url: string, - options?: {httpReferrer?: string, userAgent?: string, extraHeaders?: string}, - ): void, - reload(): void, - setMenu(menu: electron$Menu): void, // Linux Windows - setProgressBar(progress: number): void, - setOverlayIcon(overlay: electron$NativeImage, description: string): void, // Windows - setHasShadow(hasShadow: boolean): void, // macOS - hasShadow(): boolean, // macOS - setThumbarButtons(buttons: Array<{ - icon: electron$NativeImage, - click: Function, - tooltip?: string, - flags?: Array<'enabled' | 'disabled' | 'dismissonclick' | 'nobackground' | - 'hidden' | 'noninteractive'>, - }>): void, // Windows - setThumbnailClip(region: electron$rect): void, // Windows - showDefinitionForSelection(): void, // macOS - setIcon(icon: electron$NativeImage): void, // Windows Linux - setAutoHideMenuBar(hide: boolean): void, - isMenuBarAutoHide(): boolean, - setMenuBarVisibility(visible: boolean): void, - isMenuBarVisible(): boolean, - setVisibleOnAllWorkspaces(visible: boolean): void, - isVisibleOnAllWorkspaces(): boolean, - setIgnoreMouseEvents(ignore: boolean): void, - setContentProtection(enable: boolean): void, // macOS Windows - setFocusable(focusable: boolean): void, // Windows - setParentWindow(parent: electron$BrowserWindow): void, // Linux macOS - getParentWindow(): ?electron$BrowserWindow, - getChildWindows(): Array, - - // Atom sets this during window setup (see: src/main-process/atom-window.coffee). - loadSettings?: Object, -} - -/** - * https://github.com/electron/electron/blob/master/docs/api/content-tracing.md - */ - -type electron$contentTracing = {}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/dialog.md - */ - -type electron$dialog = { - showOpenDialog( - browserWindow?: electron$BrowserWindow, - options: electron$dialogOpenOptions, - callback?: Function, - ): Array, - showSaveDialog( - browserWindow?: electron$BrowserWindow, - options: electron$dialogSaveOptions, - callback?: Function, - ): string, - showMessageBox( - browserWindow?: electron$BrowserWindow, - options: electron$dialogMessageBoxOptions, - callback?: Function, - ): number, - showErrorBox(title: string, content: string): void, -}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/dialog.md - * See `dialog.showOpenDialog()` - */ - -type electron$dialogOpenOptions = { - title?: string, - defaultPath?: string, - buttonLabel?: string, - filters?: Array, - properties?: Array, -}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/dialog.md - * See `dialog.showSaveDialog()` - */ - -type electron$dialogSaveOptions = { - title?: string, - defaultPath?: string, - buttonLabel?: string, - filters?: Array, -}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/dialog.md - * See `dialog.showMessageBox()` - */ - -type electron$dialogMessageBoxOptions = { - type?: string, - buttons?: Array, - defaultId?: number, - title?: string, - message?: string, - detail?: string, - icon?: electron$NativeImage, - cancelId?: number, - noLink?: boolean, -}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/global-shortcut.md - */ - -type electron$globalShortcut = {}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/ipc-main.md - */ - -declare class electron$IpcMain {} - -/** - * https://github.com/electron/electron/blob/master/docs/api/menu.md - */ - -declare class electron$Menu { - static setApplicationMenu(menu: electron$Menu): void, - static getApplicationMenu(): ?electron$Menu, - static sendActionToFirstResponder(action: string): void, - static buildFromTemplate(templates: Array): electron$Menu, - popup( - browserWindow: electron$BrowserWindow, - x?: number, - y?: number, - positioningItem?: number, - ): void, - popup(x?: number, y?: number, positioningItem?: number): void, - append(menuItem: electron$MenuItem): void, - insert(pos: number, menuItem: electron$MenuItem): void, - items: Array, -} - -/** - * https://github.com/electron/electron/blob/master/docs/api/menu-item.md - */ - -type electron$MenuItemOptions = { - click?: ( - menuItem: electron$MenuItem, - browserWindow: electron$BrowserWindow, - event: Object - ) => void, - role?: 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'pasteandmatchstyle' | - 'selectall' | 'delete' | 'minimize' | 'close' | 'quit' | 'togglefullscreen' | - // macOS-only - 'about' | 'hide' | 'hideothers' | 'unhide' | 'front' | 'zoom' | 'window' | - 'help' | 'services', - type?: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio', - label?: string, - sublabel?: string, - accelerator?: string, - icon?: electron$NativeImage, - enabled?: boolean, - visible?: boolean, - checked?: boolean, - submenu?: electron$MenuItem | electron$MenuItemOptions, - id?: string, - position?: string, -}; - -declare class electron$MenuItem { - constructor(options: electron$MenuItemOptions): void, - enabled: boolean, - visible: boolean, - checked: boolean, -} - -/** - * https://github.com/electron/electron/blob/master/docs/api/power-monitor.md - */ - -type electron$powerMonitor = {}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/power-save-blocker.md - */ - -type electron$powerSaveBlocker = {}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/protocol.md - */ - -type electron$protocol = {}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/session.md - */ - -type electron$session = {}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/system-preferences.md - */ - -type electron$systemPreferences = {}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/tray.md - */ - -declare class electron$Tray {} - -/** - * https://github.com/electron/electron/blob/master/docs/api/web-contents.md - */ - -type electron$InputEventModifiers = - Array<'shift' | 'control' | 'alt' | 'meta' | - 'isKeypad' | 'isAutoRepeat' | 'leftButtonDown' | 'middleButtonDown' | - 'rightButtonDown' | 'capsLock' | 'numLock' | 'left' | 'right'>; - -declare class electron$WebContents extends events$EventEmitter { - loadURL( - url: string, - options?: {httpReferrer?: string, userAgent?: string, extraHeaders?: string}, - ): void, - downloadURL(url: string): void, - getURL(): string, - getTitle(): string, - isDestroyed(): boolean, - isFocused(): boolean, - isLoading(): boolean, - isLoadingMainFrame(): boolean, - isWaitingForResponse(): boolean, - stop(): void, - reload(): void, - reloadIgnoringCache(): void, - canGoBack(): boolean, - canGoForward(): boolean, - canGoToOffset(offset: number): boolean, - clearHistory(): void, - goBack(): void, - goForward(): void, - goToIndex(index: number): void, - goToOffset(index: number): void, - isCrashed(): boolean, - setUserAgent(userAgent: string): void, - getUserAgent(): string, - insertCSS(css: string): void, - // Keep `result` as mixed (and not any) to make this unsafe function less so. - executeJavaScript(code: string, callback: (result: mixed) => void): void, - executeJavaScript(code: string, userGesture?: boolean, callback?: (result: mixed) => void): void, - setAudioMuted(muted: boolean): void, - isAudioMuted(): boolean, - setZoomFactor(factor: number): void, - getZoomFactor(callback: (factor: number) => void): void, - setZoomLevel(level: number): void, - getZoomLevel(callback: (level: number) => void): void, - setZoomLevelLimits(minimumLevel: number, maximumLevel: number): void, - setVisualZoomLevelLimits(minimumLevel: number, maximumLevel: number): void, - setLayoutZoomLevelLimits(minimumLevel: number, maximumLevel: number): void, - undo(): void, - redo(): void, - cut(): void, - copy(): void, - copyImageAt(x: number, y: number): void, - paste(): void, - pasteAndMatchStyle(): void, - delete(): void, - selectAll(): void, - unselect(): void, - replace(text: string): void, - replaceMisspelling(text: string): void, - insertText(text: string): void, - inserfindInPagetText( - text: string, - options?: { - forward?: boolean, - findNext?: boolean, - matchCase?: boolean, - wordStart?: boolean, - medialCapitalAsWordStart?: boolean, - }, - ): void, - stopFindInPage(action: 'clearSelection' | 'keepSelection' | 'activateSelection'): void, - capturePage(rect: electron$rect, callback: (image: electron$NativeImage) => void): void, - capturePage(callback: (image: electron$NativeImage) => void): void, - hasServiceWorker(callback: (result: boolean) => void): void, - unregisterServiceWorker(callback: (result: boolean) => void): void, - print(options?: {silent?: boolean, printBackground?: boolean}): void, - printToPDF(options: { - marginsType: number, - pageSize: string, - pageSize: string, - printBackground: boolean, - printSelectionOnly: boolean, - landscape: boolean, - }, callback: (err: ?mixed, data: ?Buffer) => void): void, - addWorkSpace(path: string): void, - removeWorkSpace(path: string): void, - openDevTools(options?: {mode: 'right' | 'bottom' | 'undocked' | 'detach'}): void, - closeDevTools(): void, - isDevToolsOpened(): boolean, - isDevToolsFocused(): boolean, - toggleDevTools(): void, - inspectElement(x: number, y: number): void, - inspectServiceWorker(): void, - send(channel: string, ...args: Array): void, - enableDeviceEmulation(parameters: { - screenPosition?: 'desktop' | 'mobile', - screenSize: {width: number, height: number}, - viewPosition?: {x: number, y: number}, - deviceScaleFactor?: number, - viewSize?: {width: number, height: number}, - fitToView?: boolean, - offset?: {x: number, y: number}, - scale?: number, - }): void, - disableDeviceEmulation(): void, - sendInputEvent( - event: - { - type: 'keyDown' | 'keyUp' | 'char', - modifiers?: electron$InputEventModifiers, - keyCode: string, - } | { - type: 'mouseDown' | 'mouseUp' | 'mouseEnter' | 'mouseLeave' | 'contextMenu', - modifiers?: electron$InputEventModifiers, - x: number, - y: number, - button: 'left' | 'middle' | 'right', - globalX: number, - globalY: number, - movementX: number, - movementY: number, - clickCount: number, - } | { - type: 'mouseWheel', - modifiers?: electron$InputEventModifiers, - x: number, - y: number, - button: 'left' | 'middle' | 'right', - globalX: number, - globalY: number, - movementX: number, - movementY: number, - clickCount: number, - deltaX: number, - deltaY: number, - wheelTicksX: number, - wheelTicksY: number, - accelerationRatioX: number, - accelerationRatioY: number, - hasPreciseScrollingDeltas: boolean, - canScroll: boolean, - }, - ): void, - beginFrameSubscription( - callback: (frameBuffer: Buffer, dirtyRect: electron$rect) => void, - ): void, - beginFrameSubscription( - onlyDirty?: boolean, - callback: (frameBuffer: Buffer, dirtyRect: electron$rect) => void, - ): void, - endFrameSubscription(): void, - startDrag(item: {file: string, icon: electron$NativeImage}): void, - savePage( - fullPath: string, - saveType: 'HTMLOnly' | 'HTMLComplete' | 'MHTML', - callback: (error: ?mixed) => void, - ): void, - showDefinitionForSelection(): void, - isOffscreen(): boolean, - startPainting(): void, - stopPainting(): void, - isPainting(): boolean, - setFrameRate(fps: number): void, - getFrameRate(): ?number, - - id: number, - session: electron$session, - hostWebContents: ?electron$WebContents, - devToolsWebContents: ?electron$WebContents, - debugger: ?electron$Debugger, -} - -declare class electron$Debugger extends events$EventEmitter { - attach(protocolVersion?: string): void, - isAttached(): boolean, - detach(): void, - sendCommand( - method: string, - callback?: (error: ?mixed, result: ?mixed) => void, - ): void, - sendCommand( - method: string, - commandParams?: Object, - callback?: (error: ?mixed, result: ?mixed) => void, - ): void, -} - -type electron$webContents = { - getAllWebContents(): Array, - getFocusedWebContents: ?electron$WebContents, - fromId(id: number): ?electron$WebContents, -}; - -//------------------------------------------------------------------------------ -// Modules for the Renderer Process (Web Page) -//------------------------------------------------------------------------------ - -/** - * https://github.com/electron/electron/blob/master/docs/api/desktop-capturer.md - */ - -type electron$desktopCapturer = {}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/ipc-renderer.md - */ - -declare class electron$IpcRenderer { - on(channel: string, callback: (...args: Array) => void): electron$IpcRenderer, - once(channel: string, callback: (...args: Array) => void): electron$IpcRenderer, - removeListener(channel: string, callback: (...args: Array) => void): electron$IpcRenderer, - removeAllListeners(channel?: string): electron$IpcRenderer, - send(channel: string, ...args: Array): void, - sendSync(channel: string, ...args: Array): void, - sendToHost(channel: string, ...args: Array): void, -} - -/** - * https://github.com/electron/electron/blob/master/docs/api/remote.md - */ - -type electron$remote = { - // main process built-in modules: - app: electron$app, - autoUpdater: electron$autoUpdater, - BrowserWindow: typeof electron$BrowserWindow, - contentTracing: electron$contentTracing, - dialog: electron$dialog, - globalShortcut: electron$globalShortcut, - ipcMain: electron$IpcMain, - Menu: typeof electron$Menu, - MenuItem: typeof electron$MenuItem, - powerMonitor: electron$powerMonitor, - powerSaveBlocker: electron$powerSaveBlocker, - protocol: electron$protocol, - session: electron$session, - electron$Tray: typeof electron$Tray, - webContents: electron$webContents, - // methods: - require(module: string): any, - getCurrentWindow(): electron$BrowserWindow, - getCurrentWebContents(): electron$WebContents, - getGlobal(name: string): ?mixed, - process: typeof process, -}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/web-frame.md - */ - -type electron$webFrame = {}; - - -//------------------------------------------------------------------------------ -// Modules for Both Processes -//------------------------------------------------------------------------------ - -/** - * https://github.com/electron/electron/blob/master/docs/api/clipboard.md - */ - -type electron$clipboard = {}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/crash-reporter.md - */ - -type electron$crashReporter = {}; - -/** - * https://github.com/electron/electron/blob/master/docs/api/native-image.md - */ - -type electron$nativeImage = { - createEmpty(): electron$NativeImage, - createFromPath(path: string): electron$NativeImage, - createFromBuffer(buffer: Buffer, scaleFactor?: number): electron$NativeImage, - createFromDataURL(dataURL: string): electron$NativeImage, -}; - -declare class electron$NativeImage { - toPNG(): Uint8Array, - toJPEG(quality: number): Uint8Array, - toBitmap(): Uint8Array, - toDataURL(): string, - getNativeHandle(): Uint8Array, - isEmpty(): boolean, - getSize(): {width: number, height: number}, - setTemplateImage(option: boolean): void, - isTemplateImage(): boolean, - // Deprecated, but Atom is behind - so keep them around. - toPng(): Uint8Array, - toJpeg(quality: number): Uint8Array, - toDataUrl(): string, -} - -/** - * https://github.com/electron/electron/blob/master/docs/api/screen.md - */ - -type electron$Display = { - id: number, - rotation: 0 | 90 | 180 | 270, - scaleFactor: number, - touchSupport: 'available' | 'unavailable' | 'unknown', - bounds: electron$rect, - size: {height: number, width: number}, - workArea: electron$rect, - workAreaSize: {height: number, width: number}, -}; - -type electron$DisplayEvents = - 'display-added' - | 'display-removed' - | 'display-metrics-changed'; - -type electron$ScreenListener = ( - event: electron$DisplayEvents, - callback: ( - event: Object, - display: electron$Display, - changedMetrics?: Array<'bounds' | 'workArea' | 'scaleFactor' | 'rotation'>, - ) => void, -) => electron$Screen; - -declare class electron$Screen { - on: electron$ScreenListener, - once: electron$ScreenListener, - removeAllListeners(event?: electron$DisplayEvents): electron$Screen, - removeListener(event?: electron$DisplayEvents, callback: Function): electron$Screen, - getCursorScreenPoint(): {x: number, y: number}, - getPrimaryDisplay(): electron$Display, - getAllDisplays(): Array, - getDisplayNearestPoint(point: {x: number, y: number}): electron$Display, - getDisplayMatching(rect: electron$rect): electron$Display, -} - -/** - * https://github.com/electron/electron/blob/master/docs/api/shell.md - */ - -type electron$shell = { - showItemInFolder(fullPath: string): void, - openItem(fullPath: string): void, - openExternal(url: string, options?: {activate: boolean}): void, - moveItemToTrash(fullPath: string): boolean, - beep(): void, - // Windows-only - writeShortcutLink( - shortcutPath: string, - operation?: 'create' | 'update' | 'replace', - options?: { - target: string, - cwd?: string, - args?: string, - description?: string, - icon?: string, - iconIndex?: number, - appUserModelId?: string, - } - ): void, - // Windows-only - readShortcutLink(shortcutPath: string): void, -}; diff --git a/flow-libs/event-kit.js.flow b/flow-libs/event-kit.js.flow deleted file mode 100644 index 67af4f8f..00000000 --- a/flow-libs/event-kit.js.flow +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the license found in the LICENSE file in - * the root directory of this source tree. - * - * @flow - */ - -declare module 'event-kit' { - declare var Emitter: typeof atom$Emitter; - declare var Disposable: typeof atom$Disposable; - declare var CompositeDisposable: typeof atom$CompositeDisposable; -} diff --git a/flow-libs/jasmine.js.flow b/flow-libs/jasmine.js.flow deleted file mode 100644 index 2b952bca..00000000 --- a/flow-libs/jasmine.js.flow +++ /dev/null @@ -1,138 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the license found in the LICENSE file in - * the root directory of this source tree. - * - * @flow - */ - -// Type declarations for Jasmine v1.3 -// https://jasmine.github.io/1.3/introduction.html - -type JasmineMatcher = { - not: JasmineMatcher, - toBe(expected: mixed, msg?: string): boolean, - toContain(item: mixed, msg?: string): boolean, - toBeCloseTo(expected: number, precision: number, msg?: string): boolean, - toBeDefined(msg?: string): boolean, - toBeFalsy(msg?: string): boolean, - toBeTruthy(msg?: string): boolean, - toBeGreaterThan(expected: number, msg?: string): boolean, - toBeLessThan(expected: number, msg?: string): boolean, - toBeNull(msg?: string): boolean, - toBeUndefined(msg?: string): boolean, - toEqual(expected: mixed, msg?: string): boolean, - toExist(msg?: string): boolean, - toHaveBeenCalled(msg?: string): boolean, - toHaveBeenCalledWith(...args: Array): boolean, - toMatch(expected: mixed, msg?: string): boolean, - toMatchSelector(expected: string, msg?: string): boolean, - toThrow(expected?: string | Error, msg?: string): boolean, - - // Custom Matchers from nuclide-test-helpers - diffJson(expected: mixed, msg?: string): boolean, - diffLines(expected: string, msg?: string): boolean, - - // Custom Matchers from nuclide-atom-test-helpers - toEqualAtomRange(expected: ?atom$Range, msg?: string): boolean, - toEqualAtomRanges(expected: ?Array, msg?: string): boolean, -}; - -// Declaring, describing, and grouping tests -declare function afterEach(func: () => mixed): void; -declare function beforeEach(func: () => mixed): void; -declare function describe(title: string, spec: () => mixed): void; -declare function expect(actual: mixed): JasmineMatcher; -declare function it(title: string, spec: () => mixed): void; - -// Disabling Specs and Suites -// https://jasmine.github.io/1.3/introduction.html#section-Disabling_Specs_and_Suites -declare function xdescribe(title: string, spec: () => mixed): void; -declare function xit(title: string, spec: () => mixed): void; - -// Spies -// https://jasmine.github.io/1.3/introduction.html#section-Spies -type JasmineSpyCall = { - args: Array, -}; - -type JasmineSpy = { - (...args: Array): any, - andCallFake(fake: (...args: Array) => mixed): JasmineSpy, - andCallThrough(): JasmineSpy, - argsForCall: Array>, - andReturn(value: T): JasmineSpy, - andThrow(error: mixed): JasmineSpy, - callCount: number, - calls: Array, - identity: string, - mostRecentCall: JasmineSpyCall, - wasCalled: boolean, - reset(): void, -}; - -declare function spyOn(object: Object, method: string): JasmineSpy; - -// Mocking the JavaScript Clock -// https://jasmine.github.io/1.3/introduction.html#section-Mocking_the_JavaScript_Clock -type JasmineMockClock = { - tick(milliseconds: number): void, - useMock(): void, -}; - -// Asynchronous Support -// https://jasmine.github.io/1.3/introduction.html#section-Asynchronous_Support -declare function runs(func: () => mixed): void; - -// Apparently the arguments for waitsFor() can be specified in any order. -type WaitsForArg = string | number | () => mixed; - -declare function waitsFor( - latchFunction?: WaitsForArg, failureMessage?: WaitsForArg, timeout?: WaitsForArg): void; - -declare function waits(milliseconds: number): void; - -type JasmineEnvironment = { - currentSpec: { - fail(message: string): void, - }, - defaultTimeoutInterval: number, - afterEach: afterEach, - beforeEach: beforeEach, - describe: describe, - it: it, -}; - -type JasmineSpec = { - addMatchers(matchersPrototype: {[methodName: string]: (expected: any) => boolean}): void, -}; - -type JasmineMatchers = { - message: () => string, -}; - -// Jasmine global -declare var jasmine: { - // Default timeout. - DEFAULT_TIMEOUT_INTERVAL: number, - - Clock: JasmineMockClock, - Matchers: JasmineMatchers, - any(expected: string | Object): mixed, - - /** - * This is a non-standard method that Atom adds to Jasmine via spec-helper.coffee. - * Ideally, we would declare this in atom-jasmine.js, but we can't extend this global here. - */ - attachToDOM(element: Element): ?HTMLElement, - - createSpy: (name?: string) => JasmineSpy, - createSpyObj: (name: string, spyNames: Array) => {[key: string]: JasmineSpy}, - getEnv: () => JasmineEnvironment, - pp: (value: mixed) => string, - unspy: (obj: Object, methodName: string) => void, - useMockClock: () => void, - useRealClock: () => void, -}; diff --git a/flow-libs/need-to-upstream-to-flow-lib.js.flow b/flow-libs/need-to-upstream-to-flow-lib.js.flow deleted file mode 100644 index 16e86d68..00000000 --- a/flow-libs/need-to-upstream-to-flow-lib.js.flow +++ /dev/null @@ -1,127 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the license found in the LICENSE file in - * the root directory of this source tree. - * - * @flow - */ - -/* - * APIs listed in this file are ones that should be built into Flow and need to be upstreamed. - */ - -type IDisposable = { - dispose(): mixed, -}; - -/* - * These Notification & NotificationOptions definitions are not exhaustive while standardization, - * browser, and Electron support remain incomplete. - */ -type NotificationOptions = { - body?: string, - icon?: string, -}; - -declare class Notification { - constructor( - message: string, - options?: NotificationOptions, - ): void, -} - -// T9254051 - Fix flow http/https definitions. -declare class http$fixed$Server extends events$EventEmitter { - listen(port: number, hostname?: string, backlog?: number, callback?: Function): http$fixed$Server, - listen(path: string, callback?: Function): http$fixed$Server, - listen(handle: Object, callback?: Function): http$fixed$Server, - close(callback?: Function): http$fixed$Server, - address(): {port: number, fmaily: string, address: string}, - maxHeadersCount: number, -} - -declare class http$fixed$IncomingMessage extends stream$Readable { - headers: Object, - httpVersion: string, - method: string, - trailers: Object, - setTimeout(msecs: number, callback: Function): void, - socket: any, // TODO net.Socket - statusCode: number, - url: string, - connection: { destroy: () => void }, -} - -declare class http$fixed$ClientRequest extends stream$Writable { -} - -declare class http$fixed$ServerResponse { - setHeader(name: string, value: string): void, - statusCode: number, - write(value: string): void, - end(): void, -} - -declare class https$fixed { - Server: typeof http$fixed$Server, - createServer( - options: Object, - requestListener?: ( - request: http$fixed$IncomingMessage, - response: http$fixed$ServerResponse, - ) => void, - ): http$fixed$Server, - request( - options: Object | string, - callback: (response: http$fixed$IncomingMessage) => void - ): http$fixed$ClientRequest, - get( - options: Object | string, - callback: (response: http$fixed$IncomingMessage) => void - ): http$fixed$ClientRequest, -} - -declare class http$fixed { - Server: typeof http$fixed$Server, - createServer( - requestListener?: ( - request: http$fixed$IncomingMessage, - response: http$fixed$ServerResponse, - ) => void - ): http$fixed$Server, - request( - options: Object | string, - callback: (response: http$fixed$IncomingMessage) => void - ): http$fixed$ClientRequest, - get( - options: Object | string, - callback: (response: http$fixed$IncomingMessage) => void - ): http$fixed$ClientRequest, -} - -declare class module$Module { - constructor( - id?: string, - parent?: string | module$Module - ): void, - id: ?string, - exports: any, - parent?: string | module$Module, - filename?: string, - loaded: boolean, - children: Array, - paths: Array, - _compile: (content: string, filename: string) => void, - - static _resolveFilename(filename: string, module: any): string, -} - -declare module 'module' { - declare var exports: typeof module$Module; -} - -declare module 'console' { - declare var exports: any; -} diff --git a/flow-libs/simple-text-buffer.js.flow b/flow-libs/simple-text-buffer.js.flow deleted file mode 100644 index 7cc09d46..00000000 --- a/flow-libs/simple-text-buffer.js.flow +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the license found in the LICENSE file in - * the root directory of this source tree. - * - * @flow - */ - -declare class simpleTextBuffer$TextBuffer { - constructor(contents: string): void, - - // Mixin - static deserialize: (state: Object, params: Object) => mixed, - - // Events - onWillChange(callback: (event: atom$TextEditEvent) => mixed): IDisposable, - onDidChange(callback: (event: atom$TextEditEvent) => mixed): IDisposable, - onDidStopChanging(callback: () => mixed): IDisposable, - onDidChangeModified(callback: () => mixed): IDisposable, - onDidChangeEncoding(callback: () => mixed): IDisposable, - onDidDestroy(callback: () => mixed): IDisposable, - - // File Details - setEncoding(encoding: string): void, - getEncoding(): string, - getId(): string, - - // Reading Text - isEmpty(): boolean, - getText(): string, - getTextInRange(range: atom$RangeLike): string, - getLineCount(): number, - getLines(): Array, - getLastLine(): string, - lineForRow(row: number): string, - lineEndingForRow(row: number): string, - lineLengthForRow(row: number): number, - isRowBlank(row: number): boolean, - previousNonBlankRow(startRow: number): ?number, - nextNonBlankRow(startRow: number): ?number, - - // Mutating Text - setText(text: string): atom$Range, - setTextInRange( - range: atom$RangeLike, text: string, options?: Object): atom$Range, - setTextViaDiff(text: string): void, - insert( - position: atom$Point, - text: string, - options?: { - normalizeLineEndings?: boolean, - undo?: string, - }, - ): atom$Range, - append(text: string, options: ?{ - normalizeLineEndings?: boolean, - undo?: string, - }): atom$Range, - delete(range: atom$Range): atom$Range, - deleteRows(startRow: number, endRow: number): atom$Range, - - // History - undo(): void, - redo(): void, - transact(fn: () => mixed, _: void): void, - transact(groupingInterval: number, fn: () => mixed): void, - clearUndoStack(): void, - createCheckpoint(): atom$TextBufferCheckpoint, - revertToCheckpoint(checkpoint: atom$TextBufferCheckpoint): boolean, - groupChangesSinceCheckpoint(checkpoint: atom$TextBufferCheckpoint): boolean, - // TODO describe the return type more precisely. - getChangesSinceCheckpoint(checkpoint: atom$TextBufferCheckpoint): Array, - - // Search And Replace - scanInRange(regex: RegExp, range: atom$Range, iterator: TextBufferScanIterator): void, - backwardsScanInRange( - regex: RegExp, range: atom$Range, iterator: TextBufferScanIterator): void, - - // Buffer Range Details - getLastRow(): number, - getRange(): atom$Range, - rangeForRow(row: number, includeNewLine?: boolean): atom$Range, - - // Position/Index mapping - characterIndexForPosition(position: atom$PointLike): number, - positionForCharacterIndex(index: number): atom$Point, - - // Private APIs - emitter: atom$Emitter, - refcount: number, - changeCount: number, - destroy(): void, - isDestroyed(): boolean, - - static Point: typeof atom$Point, - static Range: typeof atom$Range, -} - -declare module 'simple-text-buffer' { - declare export var Point: typeof atom$Point; - declare export var Range: typeof atom$Range; - declare export default typeof simpleTextBuffer$TextBuffer; -} diff --git a/flow-libs/suda-toolbar.js.flow b/flow-libs/suda-toolbar.js.flow deleted file mode 100644 index 66b25aba..00000000 --- a/flow-libs/suda-toolbar.js.flow +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the license found in the LICENSE file in - * the root directory of this source tree. - * - * @flow - */ - -type toolbar$ToolbarManager = { - addButton(options: { - priority?: number, - tooltip?: string, - iconset?: string, - icon?: string, - callback?: string | (() => void), - }): toolbar$ToolbarButtonView, - addSpacer(options: { - priority?: number, - }): toolbar$ToolbarButtonView, - removeItems(): void, - onDidDestroy(callback: () => void): IDisposable, -}; - -type toolbar$ToolbarButtonView = { - setEnabled(enabled: boolean): void, - destroy(): void, - element: HTMLElement, -}; - -type toolbar$GetToolbar = (group: string) => toolbar$ToolbarManager; diff --git a/flow-typed/README.md b/flow-typed/README.md deleted file mode 100644 index 66f90f9a..00000000 --- a/flow-typed/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## flow-typed - -The definitions under the `npm` folder here are pulled down from -[`flow-typed`](https://github.com/flowtype/flow-typed). Please do not change these files directly. - -### Updating these definitions - -1. Put up a pull request on [`flow-typed`](https://github.com/flowtype/flow-typed) with the proposed changes. Include tests. -2. Once it's merged, update the files here by either bothering @nmote, or - - `npm install -g flow-typed` (as of this writing, it's in beta so you will need to install `flow-typed@2.0.0-beta4` to get the CLI). - - `flow-typed install packageName -f flowVersion -o`, where: - - `packageName` is the name of the package (e.g. `classnames` or `rxjs`) - - `flowVersion` is the Flow version we are currently using e.g. `0.25.0` - - `-o` just indicates the the existing defs should be overwritten diff --git a/flow-typed/npm/classnames_v2.x.x.js b/flow-typed/npm/classnames_v2.x.x.js deleted file mode 100644 index 10bdf3f4..00000000 --- a/flow-typed/npm/classnames_v2.x.x.js +++ /dev/null @@ -1,22 +0,0 @@ -// flow-typed signature: 24cdb511d3752119d012d31eab9e5c8d -// flow-typed version: 7a7121569e/classnames_v2.x.x/flow_>=v0.25.x - -type $npm$classnames$Classes = - | string - | { [className: string]: * } - | Array - | false - | void - | null; - -declare module 'classnames' { - declare function exports(...classes: Array<$npm$classnames$Classes>): string; -} - -declare module 'classnames/bind' { - declare module.exports: $Exports<'classnames'>; -} - -declare module 'classnames/dedupe' { - declare module.exports: $Exports<'classnames'>; -} diff --git a/flow-typed/npm/escape-string-regexp_v1.x.x.js b/flow-typed/npm/escape-string-regexp_v1.x.x.js deleted file mode 100644 index b2842c27..00000000 --- a/flow-typed/npm/escape-string-regexp_v1.x.x.js +++ /dev/null @@ -1,6 +0,0 @@ -// flow-typed signature: ed810fce1a8248c9f857e4b34ac68c14 -// flow-typed version: 94e9f7e0a4/escape-string-regexp_v1.x.x/flow_>=v0.28.x - -declare module 'escape-string-regexp' { - declare module.exports: (input: string) => string; -} diff --git a/flow-typed/npm/flow-bin_v0.x.x.js b/flow-typed/npm/flow-bin_v0.x.x.js deleted file mode 100644 index c538e208..00000000 --- a/flow-typed/npm/flow-bin_v0.x.x.js +++ /dev/null @@ -1,6 +0,0 @@ -// flow-typed signature: 6a5610678d4b01e13bbfbbc62bdaf583 -// flow-typed version: 3817bc6980/flow-bin_v0.x.x/flow_>=v0.25.x - -declare module "flow-bin" { - declare module.exports: string; -} diff --git a/flow-typed/npm/invariant_v2.x.x.js b/flow-typed/npm/invariant_v2.x.x.js deleted file mode 100644 index 14974ead..00000000 --- a/flow-typed/npm/invariant_v2.x.x.js +++ /dev/null @@ -1 +0,0 @@ -// Empty stub to prevent flow-typed from installing its own definition diff --git a/flow-typed/npm/log4js_v1.x.x.js b/flow-typed/npm/log4js_v1.x.x.js deleted file mode 100644 index 4c9927c9..00000000 --- a/flow-typed/npm/log4js_v1.x.x.js +++ /dev/null @@ -1,44 +0,0 @@ -// flow-typed signature: c69efc63ea2cb8646a8685b0e937fb25 -// flow-typed version: b43dff3e0e/log4js_v1.x.x/flow_>=v0.25.x - -type log4js$Logger = { - level: string, - setLevel(level: string): void, - removeLevel(): void, - isLevelEnabled(level: string): boolean, - - log(...args: Array): void, - trace(...args: Array): void, - debug(...args: Array): void, - info(...args: Array): void, - warn(...args: Array): void, - error(...args: Array): void, - fatal(...args: Array): void, - mark(...args: Array): void, -} - -type log4js$Appender = { - type: string, -} - -type log4js$Config = { - appenders?: Array, - levels?: {[name: string]: string}, -} - -declare module 'log4js' { - declare module.exports: { - getLogger(category?: string): log4js$Logger, - - configure( - configurationFileOrObject: string | log4js$Config, - options?: Object, - ): void, - - shutdown(callback: () => mixed): void, - - connectLogger(logger: log4js$Logger, options?: Object): any, - - levels: Object, - } -} diff --git a/flow-typed/npm/lru-cache_v4.0.x.js b/flow-typed/npm/lru-cache_v4.0.x.js deleted file mode 100644 index b4d37b34..00000000 --- a/flow-typed/npm/lru-cache_v4.0.x.js +++ /dev/null @@ -1,26 +0,0 @@ -// flow-typed signature: 2e415f033284600956b323d56d206449 -// flow-typed version: b43dff3e0e/lru-cache_v4.0.x/flow_>=v0.20.0 - -declare module 'lru-cache' { - - declare type LRUCache = { - set: (key: K, value: V, maxAge?: number) => void; - get: (key: K) => V; - peek: (key: K) => V; - del: (key: K) => void; - reset: () => void; - has: (key: K) => boolean; - // TODO add the rest of the things documented at https://www.npmjs.com/package/lru-cache - }; - - declare type Options = { - max?: number; - maxAge?: number; - length?: (value: V, key: K) => number; - dispose?: (key: K, value: V) => void; - stale?: boolean; - }; - - // TODO You can supply just an integer (max size), or even nothing at all. - declare var exports: (options: Options) => LRUCache; -} diff --git a/flow-typed/npm/mkdirp_v0.5.x.js b/flow-typed/npm/mkdirp_v0.5.x.js deleted file mode 100644 index e26f9a4b..00000000 --- a/flow-typed/npm/mkdirp_v0.5.x.js +++ /dev/null @@ -1,13 +0,0 @@ -// flow-typed signature: 82aa0feffc2bbd64dce3bec492f5d601 -// flow-typed version: 3315d89a00/mkdirp_v0.5.x/flow_>=v0.25.0 - -declare module 'mkdirp' { - declare type Options = number | { mode?: number; fs?: mixed }; - - declare type Callback = (err: ?Error, path: ?string) => void; - - declare module.exports: { - (path: string, options?: Options | Callback, callback?: Callback): void; - sync(path: string, options?: Options): void; - }; -} diff --git a/flow-typed/npm/react-addons-test-utils_v15.x.x.js b/flow-typed/npm/react-addons-test-utils_v15.x.x.js deleted file mode 100644 index 2a57e98d..00000000 --- a/flow-typed/npm/react-addons-test-utils_v15.x.x.js +++ /dev/null @@ -1,29 +0,0 @@ -// flow-typed signature: edc151d4ee06b1d20021425952030a4b -// flow-typed version: cdb403dbea/react-addons-test-utils_v15.x.x/flow_>=v0.15.x - -import React from 'react'; - -declare module 'react-addons-test-utils' { - declare var Simulate: { - [eventName: string]: (element: Element, eventData?: Object) => void; - }; - declare function renderIntoDocument(instance: React.Element): React.Component; - declare function mockComponent(componentClass: React.ElementType, mockTagName?: string): Object; - declare function isElement(element: React.Element): boolean; - declare function isElementOfType(element: React.Element, componentClass: React.ElementType): boolean; - declare function isDOMComponent(instance: React.Component): boolean; - declare function isCompositeComponent(instance: React.Component): boolean; - declare function isCompositeComponentWithType(instance: React.Component, componentClass: React.ElementType): boolean; - declare function findAllInRenderedTree(tree: React.Component, test: (child: React.Component) => boolean): Array; - declare function scryRenderedDOMComponentsWithClass(tree: React.Component, className: string): Array; - declare function findRenderedDOMComponentWithClass(tree: React.Component, className: string): ?Element; - declare function scryRenderedDOMComponentsWithTag(tree: React.Component, tagName: string): Array; - declare function findRenderedDOMComponentWithTag(tree: React.Component, tagName: string): ?Element; - declare function scryRenderedComponentsWithType(tree: React.Component, componentClass: React.ElementType): Array; - declare function findRenderedComponentWithType(tree: React.Component, componentClass: React.ElementType): ?React.Component; - declare class ReactShallowRender { - render(element: React.Element): void; - getRenderOutput(): React.Element; - } - declare function createRenderer(): ReactShallowRender; -} diff --git a/flow-typed/npm/react-redux_v5.x.x.js b/flow-typed/npm/react-redux_v5.x.x.js deleted file mode 100644 index 30380824..00000000 --- a/flow-typed/npm/react-redux_v5.x.x.js +++ /dev/null @@ -1,114 +0,0 @@ -// flow-typed signature: f0d96df48e9abc14bcc1405ba2a47dde -// flow-typed version: 83053e4020/react-redux_v5.x.x/flow_>=v0.53.x - -// flow-typed signature: 8db7b853f57c51094bf0ab8b2650fd9c -// flow-typed version: ab8db5f14d/react-redux_v5.x.x/flow_>=v0.30.x - -import type { Dispatch, Store } from "redux"; - -declare module "react-redux" { - /* - - S = State - A = Action - OP = OwnProps - SP = StateProps - DP = DispatchProps - - */ - - declare type MapStateToProps = ( - state: S, - ownProps: OP - ) => ((state: S, ownProps: OP) => SP) | SP; - - declare type MapDispatchToProps = - | ((dispatch: Dispatch, ownProps: OP) => DP) - | DP; - - declare type MergeProps = ( - stateProps: SP, - dispatchProps: DP, - ownProps: OP - ) => P; - - declare type Context = { store: Store<*, *> }; - - declare class ConnectedComponent extends React$Component { - static WrappedComponent: Class>, - getWrappedInstance(): React$Component

, - props: OP, - state: void - } - - declare type ConnectedComponentClass = Class< - ConnectedComponent - >; - - declare type Connector = ( - component: React$ComponentType

- ) => ConnectedComponentClass; - - declare class Provider extends React$Component<{ - store: Store, - children?: any - }> {} - - declare function createProvider( - storeKey?: string, - subKey?: string - ): Provider<*, *>; - - declare type ConnectOptions = { - pure?: boolean, - withRef?: boolean - }; - - declare type Null = null | void; - - declare function connect( - ...rest: Array // <= workaround for https://github.com/facebook/flow/issues/2360 - ): Connector } & OP>>; - - declare function connect( - mapStateToProps: Null, - mapDispatchToProps: Null, - mergeProps: Null, - options: ConnectOptions - ): Connector } & OP>>; - - declare function connect( - mapStateToProps: MapStateToProps, - mapDispatchToProps: Null, - mergeProps: Null, - options?: ConnectOptions - ): Connector } & OP>>; - - declare function connect( - mapStateToProps: Null, - mapDispatchToProps: MapDispatchToProps, - mergeProps: Null, - options?: ConnectOptions - ): Connector>; - - declare function connect( - mapStateToProps: MapStateToProps, - mapDispatchToProps: MapDispatchToProps, - mergeProps: Null, - options?: ConnectOptions - ): Connector>; - - declare function connect( - mapStateToProps: MapStateToProps, - mapDispatchToProps: Null, - mergeProps: MergeProps, - options?: ConnectOptions - ): Connector; - - declare function connect( - mapStateToProps: MapStateToProps, - mapDispatchToProps: MapDispatchToProps, - mergeProps: MergeProps, - options?: ConnectOptions - ): Connector; -} diff --git a/flow-typed/npm/reselect_v3.x.x.js b/flow-typed/npm/reselect_v3.x.x.js deleted file mode 100644 index 589c5757..00000000 --- a/flow-typed/npm/reselect_v3.x.x.js +++ /dev/null @@ -1,753 +0,0 @@ -// flow-typed signature: 0199525b667f385f2e61dbeae3215f21 -// flow-typed version: b43dff3e0e/reselect_v3.x.x/flow_>=v0.28.x - -declare module 'reselect' { - declare type Selector = { - (state: TState, props: TProps, ...rest: any[]): TResult; - }; - - declare type SelectorCreator = { - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - selector6: Selector, - selector7: Selector, - selector8: Selector, - selector9: Selector, - selector10: Selector, - selector11: Selector, - selector12: Selector, - selector13: Selector, - selector14: Selector, - selector15: Selector, - selector16: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11, - arg12: T12, - arg13: T13, - arg14: T14, - arg15: T15, - arg16: T16 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11, - arg12: T12, - arg13: T13, - arg14: T14, - arg15: T15, - arg16: T16 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - selector6: Selector, - selector7: Selector, - selector8: Selector, - selector9: Selector, - selector10: Selector, - selector11: Selector, - selector12: Selector, - selector13: Selector, - selector14: Selector, - selector15: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11, - arg12: T12, - arg13: T13, - arg14: T14, - arg15: T15 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11, - arg12: T12, - arg13: T13, - arg14: T14, - arg15: T15 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - selector6: Selector, - selector7: Selector, - selector8: Selector, - selector9: Selector, - selector10: Selector, - selector11: Selector, - selector12: Selector, - selector13: Selector, - selector14: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11, - arg12: T12, - arg13: T13, - arg14: T14 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11, - arg12: T12, - arg13: T13, - arg14: T14 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - selector6: Selector, - selector7: Selector, - selector8: Selector, - selector9: Selector, - selector10: Selector, - selector11: Selector, - selector12: Selector, - selector13: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11, - arg12: T12, - arg13: T13 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11, - arg12: T12, - arg13: T13 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - selector6: Selector, - selector7: Selector, - selector8: Selector, - selector9: Selector, - selector10: Selector, - selector11: Selector, - selector12: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11, - arg12: T12 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11, - arg12: T12 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - selector6: Selector, - selector7: Selector, - selector8: Selector, - selector9: Selector, - selector10: Selector, - selector11: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10, - arg11: T11 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - selector6: Selector, - selector7: Selector, - selector8: Selector, - selector9: Selector, - selector10: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9, - arg10: T10 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - selector6: Selector, - selector7: Selector, - selector8: Selector, - selector9: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8, - arg9: T9 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - selector6: Selector, - selector7: Selector, - selector8: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7, - arg8: T8 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - selector6: Selector, - selector7: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6, - arg7: T7 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - selector6: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5, - arg6: T6 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - selector5: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4, - arg5: T5 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - selector4: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3, - arg4: T4 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - selector3: Selector, - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2, - arg3: T3 - ) => TResult - ): Selector; - - ( - selector1: Selector, - selector2: Selector, - resultFunc: ( - arg1: T1, - arg2: T2 - ) => TResult - ): Selector; - ( - selectors: [ - Selector, - Selector - ], - resultFunc: ( - arg1: T1, - arg2: T2 - ) => TResult - ): Selector; - - ( - selector1: Selector, - resultFunc: ( - arg1: T1 - ) => TResult - ): Selector; - ( - selectors: [ - Selector - ], - resultFunc: ( - arg1: T1 - ) => TResult - ): Selector; - }; - - declare type Reselect = { - createSelector: SelectorCreator; - - defaultMemoize: ( - func: TFunc, - equalityCheck?: (a: any, b: any) => boolean - ) => TFunc; - - createSelectorCreator: ( - memoize: Function, - ...memoizeOptions: any[] - ) => SelectorCreator; - - createStructuredSelector: ( - inputSelectors: { - [k: string | number]: Selector - }, - selectorCreator?: SelectorCreator - ) => Selector; - }; - - declare var exports: Reselect; -}; diff --git a/flow-typed/npm/rxjs_v5.0.x.js b/flow-typed/npm/rxjs_v5.0.x.js deleted file mode 100644 index be400f3b..00000000 --- a/flow-typed/npm/rxjs_v5.0.x.js +++ /dev/null @@ -1,855 +0,0 @@ -// flow-typed signature: 0723ec09e223e3f8a0a66ef5ab1fa253 -// flow-typed version: 96963f4e58/rxjs_v5.0.x/flow_>=v0.34.x - -// FIXME(samgoldman) Remove top-level interface once Babel supports -// `declare interface` syntax. -// FIXME(samgoldman) Remove this once rxjs$Subject can mixin rxjs$Observer -interface rxjs$IObserver<-T> { - closed?: boolean, - next(value: T): mixed; - error(error: any): mixed; - complete(): mixed; -} - -type rxjs$PartialObserver<-T> = - | { - +next: (value: T) => mixed; - +error?: (error: any) => mixed; - +complete?: () => mixed; - } - | { - +next?: (value: T) => mixed; - +error: (error: any) => mixed; - +complete?: () => mixed; - } - | { - +next?: (value: T) => mixed; - +error?: (error: any) => mixed; - +complete: () => mixed; - } - -interface rxjs$ISubscription { - unsubscribe(): void; -} - -type rxjs$TeardownLogic = rxjs$ISubscription | () => void; - -type rxjs$EventListenerOptions = { - capture?: boolean; - passive?: boolean; - once?: boolean; -} | boolean; - -declare class rxjs$Observable<+T> { - static bindCallback(callbackFunc: (callback: (_: void) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): () => rxjs$Observable; - static bindCallback(callbackFunc: (callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): () => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T) => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, v2: T2, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2) => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3) => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4) => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5) => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6) => rxjs$Observable; - static bindCallback(callbackFunc: (callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): () => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T) => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, v2: T2, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2) => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3) => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4) => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5) => rxjs$Observable; - static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6) => rxjs$Observable; - static bindCallback(callbackFunc: Function, selector?: void, scheduler?: rxjs$SchedulerClass): (...args: Array) => rxjs$Observable; - static bindCallback(callbackFunc: Function, selector?: (...args: Array) => T, scheduler?: rxjs$SchedulerClass): (...args: Array) => rxjs$Observable; - - static bindNodeCallback(callbackFunc: (callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): () => rxjs$Observable; - static bindNodeCallback(callbackFunc: (v1: T, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T) => rxjs$Observable; - static bindNodeCallback(callbackFunc: (v1: T, v2: T2, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2) => rxjs$Observable; - static bindNodeCallback(callbackFunc: (v1: T, v2: T2, v3: T3, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3) => rxjs$Observable; - static bindNodeCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4) => rxjs$Observable; - static bindNodeCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5) => rxjs$Observable; - static bindNodeCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6) => rxjs$Observable; - static bindNodeCallback(callbackFunc: Function, selector?: void, scheduler?: rxjs$SchedulerClass): (...args: Array) => rxjs$Observable; - static bindNodeCallback(callbackFunc: Function, selector?: (...args: Array) => T, scheduler?: rxjs$SchedulerClass): (...args: Array) => rxjs$Observable; - - static concat(...sources: rxjs$Observable[]): rxjs$Observable; - - static create( - subscribe: (observer: rxjs$Observer) => rxjs$ISubscription | Function | void - ): rxjs$Observable; - - static defer(observableFactory: () => rxjs$Observable | Promise): rxjs$Observable; - - static from(iterable: Iterable): rxjs$Observable; - - static fromEvent(element: any, eventName: string, ...none: Array): rxjs$Observable; - static fromEvent( - element: any, - eventName: string, - options: rxjs$EventListenerOptions, - ...none: Array - ): rxjs$Observable; - static fromEvent( - element: any, - eventName: string, - selector: () => T, - ...none: Array - ): rxjs$Observable; - static fromEvent( - element: any, - eventName: string, - options: rxjs$EventListenerOptions, - selector: () => T, - ): rxjs$Observable; - - static fromEventPattern( - addHandler: (handler: (item: T) => void) => void, - removeHandler: (handler: (item: T) => void) => void, - selector?: () => T, - ): rxjs$Observable; - - static fromPromise(promise: Promise): rxjs$Observable; - - static empty(): rxjs$Observable; - - static interval(period: number): rxjs$Observable; - - static timer(initialDelay: (number | Date), period?: number, scheduler?: rxjs$SchedulerClass): rxjs$Observable; - - static merge( - source0: rxjs$Observable, - source1: rxjs$Observable, - ): rxjs$Observable; - static merge( - source0: rxjs$Observable, - source1: rxjs$Observable, - source2: rxjs$Observable, - ): rxjs$Observable; - static merge(...sources: rxjs$Observable[]): rxjs$Observable; - - static never(): rxjs$Observable; - - static of(...values: T[]): rxjs$Observable; - - static throw(error: any): rxjs$Observable; - - audit(durationSelector: (value: T) => rxjs$Observable | Promise): rxjs$Observable; - - race(other: rxjs$Observable): rxjs$Observable; - - repeat(): rxjs$Observable; - - buffer(bufferBoundaries: rxjs$Observable): rxjs$Observable>; - - catch(selector: (err: any, caught: rxjs$Observable) => rxjs$Observable): rxjs$Observable; - - concat(...sources: rxjs$Observable[]): rxjs$Observable; - - concatAll(): rxjs$Observable; - - concatMap( - f: (value: T) => rxjs$Observable | Promise | Iterable - ): rxjs$Observable; - - debounceTime(dueTime: number, scheduler?: rxjs$SchedulerClass): rxjs$Observable; - - delay(dueTime: number, scheduler?: rxjs$SchedulerClass): rxjs$Observable; - - distinctUntilChanged(compare?: (x: T, y: T) => boolean): rxjs$Observable; - - distinct(keySelector?: (value: T) => U, flushes?: rxjs$Observable): rxjs$Observable; - - distinctUntilKeyChanged(key: string, compare?: (x: mixed, y: mixed) => boolean): rxjs$Observable; - - elementAt(index: number, defaultValue?: T): rxjs$Observable; - - expand( - project: (value: T, index: number) => rxjs$Observable, - concurrent?: number, - scheduler?: rxjs$SchedulerClass, - ): rxjs$Observable; - - filter(predicate: (value: T, index: number) => boolean, thisArg?: any): rxjs$Observable; - - finally(f: () => mixed): rxjs$Observable; - - first( - predicate?: (value: T, index: number, source: rxjs$Observable) => boolean, - ): rxjs$Observable; - first( - predicate: ?(value: T, index: number, source: rxjs$Observable) => boolean, - resultSelector: (value: T, index: number) => U, - ): rxjs$Observable; - first( - predicate: ?(value: T, index: number, source: rxjs$Observable) => boolean, - resultSelector: ?(value: T, index: number) => U, - defaultValue: U, - ): rxjs$Observable; - - groupBy( - keySelector: (value: T) => mixed, - elementSelector?: (value: T) => T, - compare?: (x: T, y: T) => boolean, - ): rxjs$Observable>; - - ignoreElements(): rxjs$Observable; - - let(project: (self: rxjs$Observable) => rxjs$Observable): rxjs$Observable; - - // Alias for `let` - letBind(project: (self: rxjs$Observable) => rxjs$Observable): rxjs$Observable; - - switch(): T; // assumption: T is Observable - - // Alias for `mergeMap` - flatMap( - project: (value: T) => rxjs$Observable | Promise | Iterable, - index?: number, - ): rxjs$Observable; - - flatMapTo( - innerObservable: rxjs$Observable - ): rxjs$Observable; - - flatMapTo( - innerObservable: rxjs$Observable < U >, - resultSelector: (outerValue: T, innerValue: U, outerIndex: number, innerIndex: number) => V, - concurrent ?: number - ): rxjs$Observable; - - switchMap( - project: (value: T) => rxjs$Observable | Promise | Iterable, - index?: number, - ): rxjs$Observable; - - switchMapTo( - innerObservable: rxjs$Observable, - ): rxjs$Observable; - - map(f: (value: T) => U): rxjs$Observable; - - mapTo(value: U): rxjs$Observable; - - merge(other: rxjs$Observable): rxjs$Observable; - - mergeAll(): rxjs$Observable; - - mergeMap( - project: (value: T, index?: number) => rxjs$Observable | Promise | Iterable, - index?: number, - ): rxjs$Observable; - - mergeMapTo( - innerObservable: rxjs$Observable - ): rxjs$Observable; - - mergeMapTo( - innerObservable: rxjs$Observable < U >, - resultSelector: (outerValue: T, innerValue: U, outerIndex: number, innerIndex: number) => V, - concurrent ?: number - ): rxjs$Observable; - - multicast( - subjectOrSubjectFactory: rxjs$Subject | () => rxjs$Subject, - ): rxjs$ConnectableObservable; - - observeOn(scheduler: rxjs$SchedulerClass): rxjs$Observable; - - pairwise(): rxjs$Observable<[T, T]>; - - publish(): rxjs$ConnectableObservable; - - publishLast(): rxjs$ConnectableObservable; - - reduce( - accumulator: ( - acc: U, - currentValue: T, - index: number, - source: rxjs$Observable, - ) => U, - seed: U, - ): rxjs$Observable; - - sample(notifier: rxjs$Observable): rxjs$Observable; - - sampleTime(delay: number, scheduler?: rxjs$SchedulerClass): rxjs$Observable; - - publishReplay(bufferSize?: number, windowTime?: number, scheduler?: rxjs$SchedulerClass): rxjs$ConnectableObservable; - - retry(retryCount: ?number): rxjs$Observable; - - retryWhen(notifier: (errors: rxjs$Observable) => rxjs$Observable): rxjs$Observable; - - scan( - f: (acc: U, value: T) => U, - initialValue: U, - ): rxjs$Observable; - - share(): rxjs$Observable; - - skip(count: number): rxjs$Observable; - - skipUntil(other: rxjs$Observable | Promise): rxjs$Observable; - - skipWhile(predicate: (value: T, index: number) => boolean): rxjs$Observable; - - startWith(...values: Array): rxjs$Observable; - - subscribeOn(scheduler: rxjs$SchedulerClass): rxjs$Observable; - - take(count: number): rxjs$Observable; - - takeUntil(other: rxjs$Observable): rxjs$Observable; - - takeWhile(predicate: (value: T, index: number) => boolean): rxjs$Observable; - - do( - onNext?: (value: T) => mixed, - onError?: (error: any) => mixed, - onCompleted?: () => mixed, - ): rxjs$Observable; - do(observer: { - next?: (value: T) => mixed; - error?: (error: any) => mixed; - complete?: () => mixed; - }): rxjs$Observable; - - throttleTime(duration: number): rxjs$Observable; - - timeout(due: number | Date, _: void): rxjs$Observable; - - toArray(): rxjs$Observable; - - toPromise(): Promise; - - subscribe(observer: rxjs$PartialObserver): rxjs$Subscription; - subscribe( - onNext: ?(value: T) => mixed, - onError: ?(error: any) => mixed, - onCompleted: ?() => mixed, - ): rxjs$Subscription; - - static combineLatest( - a: rxjs$Observable, - resultSelector: (a: A) => B, - ): rxjs$Observable; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - resultSelector: (a: A, b: B) => C, - ): rxjs$Observable; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - resultSelector: (a: A, b: B, c: C) => D, - ): rxjs$Observable; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D) => E, - ): rxjs$Observable; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E) => F, - ): rxjs$Observable; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F) => G, - ): rxjs$Observable; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - g: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => H, - ): rxjs$Observable; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B]>; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C]>; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C, D]>; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C, D, E]>; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C, D, E, F]>; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - g: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C, D, E, F, G]>; - - static combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - g: rxjs$Observable, - h: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C, D, E, F, G, H]>; - - combineLatest( - a: rxjs$Observable, - _: void, - ): rxjs$Observable<[T, A]>; - - combineLatest( - a: rxjs$Observable, - resultSelector: (a: A) => B, - ): rxjs$Observable; - - combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - resultSelector: (a: A, b: B) => C, - ): rxjs$Observable; - - combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - resultSelector: (a: A, b: B, c: C) => D, - ): rxjs$Observable; - - combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D) => E, - ): rxjs$Observable; - - combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E) => F, - ): rxjs$Observable; - - combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F) => G, - ): rxjs$Observable; - - combineLatest( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - g: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => H, - ): rxjs$Observable; - - static forkJoin( - a: rxjs$Observable, - resultSelector: (a: A) => B, - ): rxjs$Observable; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - resultSelector: (a: A, b: B) => C, - ): rxjs$Observable; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - resultSelector: (a: A, b: B, c: C) => D, - ): rxjs$Observable; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D) => E, - ): rxjs$Observable; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E) => F, - ): rxjs$Observable; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F) => G, - ): rxjs$Observable; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - g: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => H, - ): rxjs$Observable; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B]>; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C]>; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C, D]>; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C, D, E]>; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C, D, E, F]>; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - g: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C, D, E, F, G]>; - - static forkJoin( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - g: rxjs$Observable, - h: rxjs$Observable, - _: void, - ): rxjs$Observable<[A, B, C, D, E, F, G, H]>; - - withLatestFrom( - a: rxjs$Observable, - _: void, - ): rxjs$Observable<[T, A]>; - - withLatestFrom( - a: rxjs$Observable, - resultSelector: (a: A) => B, - ): rxjs$Observable; - - withLatestFrom( - a: rxjs$Observable, - b: rxjs$Observable, - resultSelector: (a: A, b: B) => C, - ): rxjs$Observable; - - withLatestFrom( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - resultSelector: (a: A, b: B, c: C) => D, - ): rxjs$Observable; - - withLatestFrom( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D) => E, - ): rxjs$Observable; - - withLatestFrom( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E) => F, - ): rxjs$Observable; - - withLatestFrom( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F) => G, - ): rxjs$Observable; - - withLatestFrom( - a: rxjs$Observable, - b: rxjs$Observable, - c: rxjs$Observable, - d: rxjs$Observable, - e: rxjs$Observable, - f: rxjs$Observable, - g: rxjs$Observable, - resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => H, - ): rxjs$Observable; - - static using( - resourceFactory: () => ?R, - observableFactory: (resource: R) => rxjs$Observable | Promise | void, - ): rxjs$Observable; - - _subscribe(observer: rxjs$Subscriber): rxjs$Subscription; - - _isScalar: boolean; - source: ?rxjs$Observable; - operator: ?rxjs$Operator; -} - -declare class rxjs$ConnectableObservable extends rxjs$Observable { - connect(): rxjs$Subscription; - refCount(): rxjs$Observable; -} - -declare class rxjs$Observer { - next(value: T): mixed; - - error(error: any): mixed; - - complete(): mixed; -} - -declare interface rxjs$Operator { - call(subscriber: rxjs$Subscriber, source: any): rxjs$TeardownLogic; -} - -// FIXME(samgoldman) should be `mixins rxjs$Observable, rxjs$Observer` -// once Babel parsing support exists: https://phabricator.babeljs.io/T6821 -declare class rxjs$Subject extends rxjs$Observable { - asObservable(): rxjs$Observable; - - observers: Array>; - - unsubscribe(): void; - - // Copied from rxjs$Observer - next(value: T): mixed; - error(error: any): mixed; - complete(): mixed; - - // For use in subclasses only: - _next(value: T): void; -} - -declare class rxjs$AnonymousSubject extends rxjs$Subject { - source: ?rxjs$Observable; - destination: ?rxjs$Observer; - - constructor(destination?: rxjs$IObserver, source?: rxjs$Observable): void; - next(value: T): void; - error(err: any): void; - complete(): void; -} - -declare class rxjs$BehaviorSubject extends rxjs$Subject { - constructor(initialValue: T): void; - - getValue(): T; -} - -declare class rxjs$ReplaySubject extends rxjs$Subject { - constructor(bufferSize?: number, windowTime?: number, scheduler?: rxjs$SchedulerClass): void; -} - -declare class rxjs$Subscription { - unsubscribe(): void; - add(teardown: rxjs$TeardownLogic): rxjs$Subscription; -} - -declare class rxjs$Subscriber extends rxjs$Subscription { - static create( - next?: (x?: T) => void, - error?: (e?: any) => void, - complete?: () => void, - ): rxjs$Subscriber; - - constructor( - destinationOrNext?: (rxjs$PartialObserver | ((value: T) => void)), - error?: (e?: any) => void, - complete?: () => void, - ): void; - next(value?: T): void; - error(err?: any): void; - complete(): void; - unsubscribe(): void; -} - -declare class rxjs$SchedulerClass { - schedule(work: (state?: T) => void, delay?: number, state?: T): rxjs$Subscription; -} - -declare class rxjs$TimeoutError extends Error { -} - -declare module 'rxjs' { - declare module.exports: { - Observable: typeof rxjs$Observable, - Observer: typeof rxjs$Observer, - ConnectableObservable: typeof rxjs$ConnectableObservable, - Subject: typeof rxjs$Subject, - Subscriber: typeof rxjs$Subscriber, - AnonymousSubject: typeof rxjs$AnonymousSubject, - BehaviorSubject: typeof rxjs$BehaviorSubject, - ReplaySubject: typeof rxjs$ReplaySubject, - Scheduler: { - asap: rxjs$SchedulerClass, - queue: rxjs$SchedulerClass, - animationFrame: rxjs$SchedulerClass, - async: rxjs$SchedulerClass, - }, - Subscription: typeof rxjs$Subscription, - TimeoutError: typeof rxjs$TimeoutError, - } -} - -declare module 'rxjs/Observable' { - declare module.exports: { - Observable: typeof rxjs$Observable - } -} - -declare module 'rxjs/Observer' { - declare module.exports: { - Observer: typeof rxjs$Observer - } -} - -declare module 'rxjs/BehaviorSubject' { - declare module.exports: { - BehaviorSubject: typeof rxjs$BehaviorSubject - } -} - -declare module 'rxjs/ReplaySubject' { - declare module.exports: { - ReplaySubject: typeof rxjs$ReplaySubject - } -} - -declare module 'rxjs/Subject' { - declare module.exports: { - Subject: typeof rxjs$Subject, - AnonymousSubject: typeof rxjs$AnonymousSubject - } -} - -declare module 'rxjs/Subscriber' { - declare module.exports: { - Subscriber: typeof rxjs$Subscriber - } -} - -declare module 'rxjs/Subscription' { - declare module.exports: { - Subscription: typeof rxjs$Subscription - } -} - -declare module 'rxjs/testing/TestScheduler' { - declare module.exports: { - TestScheduler: typeof rxjs$SchedulerClass - } -} diff --git a/flow-typed/npm/semver_v5.1.x.js b/flow-typed/npm/semver_v5.1.x.js deleted file mode 100644 index d1066121..00000000 --- a/flow-typed/npm/semver_v5.1.x.js +++ /dev/null @@ -1,110 +0,0 @@ -// flow-typed signature: 1d1f54a0e3983f7bd1d91411d7e64f22 -// flow-typed version: 99dfe36842/semver_v5.1.x/flow_>=v0.20.x - -declare module 'semver' { - declare type Release = - 'major' | - 'premajor' | - 'minor' | - 'preminor' | - 'patch' | - 'prepatch' | - 'prerelease'; - - // The supported comparators are taken from the source here: - // https://github.com/npm/node-semver/blob/8bd070b550db2646362c9883c8d008d32f66a234/semver.js#L623 - declare type Operator = - '===' | - '!==' | - '==' | - '=' | - '' | // Not sure why you would want this, but whatever. - '!=' | - '>' | - '>=' | - '<' | - '<='; - - declare class SemVer { - build: Array; - loose: ?boolean; - major: number; - minor: number; - patch: number; - prerelease: Array; - raw: string; - version: string; - - constructor(version: string | SemVer, loose?: boolean): SemVer; - compare(other: string | SemVer): -1 | 0 | 1; - compareMain(other: string | SemVer): -1 | 0 | 1; - comparePre(other: string | SemVer): -1 | 0 | 1; - format(): string; - inc(release: Release, identifier: string): this; - } - - declare class Comparator { - loose?: boolean; - operator: Operator; - semver: SemVer; - value: string; - - constructor(comp: string | Comparator, loose?: boolean): Comparator; - parse(comp: string): void; - test(version: string): boolean; - } - - declare class Range { - loose: ?boolean; - raw: string; - set: Array>; - - constructor(range: string | Range, loose?: boolean): Range; - format(): string; - parseRange(range: string): Array; - test(version: string): boolean; - toString(): string; - } - - declare var SEMVER_SPEC_VERSION: string; - declare var re: Array; - declare var src: Array; - - // Functions - declare function valid(v: string | SemVer, loose?: boolean): string | null; - declare function clean(v: string | SemVer, loose?: boolean): string | null; - declare function inc(v: string | SemVer, release: Release, loose?: boolean, identifier?: string): string | null; - declare function inc(v: string | SemVer, release: Release, identifier: string): string | null; - declare function major(v: string | SemVer, loose?: boolean): number; - declare function minor(v: string | SemVer, loose?: boolean): number; - declare function patch(v: string | SemVer, loose?: boolean): number; - - // Comparison - declare function gt(v1: string | SemVer, v2: string | SemVer, loose?: boolean): boolean; - declare function gte(v1: string | SemVer, v2: string | SemVer, loose?: boolean): boolean; - declare function lt(v1: string | SemVer, v2: string | SemVer, loose?: boolean): boolean; - declare function lte(v1: string | SemVer, v2: string | SemVer, loose?: boolean): boolean; - declare function eq(v1: string | SemVer, v2: string | SemVer, loose?: boolean): boolean; - declare function neq(v1: string | SemVer, v2: string | SemVer, loose?: boolean): boolean; - declare function cmp(v1: string | SemVer, comparator: Operator, v2: string | SemVer, loose?: boolean): boolean; - declare function compare(v1: string | SemVer, v2: string | SemVer, loose?: boolean): -1 | 0 | 1; - declare function rcompare(v1: string | SemVer, v2: string | SemVer, loose?: boolean): -1 | 0 | 1; - declare function compareLoose(v1: string | SemVer, v2: string | SemVer): -1 | 0 | 1; - declare function diff(v1: string | SemVer, v2: string | SemVer): ?Release; - declare function sort(list: Array, loose?: boolean): Array; - declare function rsort(list: Array, loose?: boolean): Array; - declare function compareIdentifiers(v1: string | SemVer, v2: string | SemVer): -1 | 0 | 1; - declare function rcompareIdentifiers(v1: string | SemVer, v2: string | SemVer): -1 | 0 | 1; - - // Ranges - declare function validRange(range: string | Range, loose?: boolean): string | null; - declare function satisfies(version: string | SemVer, range: string | Range, loose?: boolean): boolean; - declare function maxSatisfying(versions: Array, range: string | Range, loose?: boolean): string | SemVer | null; - declare function gtr(version: string | SemVer, range: string | Range, loose?: boolean): boolean; - declare function ltr(version: string | SemVer, range: string | Range, loose?: boolean): boolean; - declare function outside(version: string | SemVer, range: string | Range, hilo: '>' | '<', loose?: boolean): boolean; - - // Not explicitly documented, or deprecated - declare function parse(version: string, loose?: boolean): ?SemVer; - declare function toComparators(range: string | Range, loose?: boolean): Array>; -} diff --git a/flow-typed/npm/strip-ansi_v3.x.x.js b/flow-typed/npm/strip-ansi_v3.x.x.js deleted file mode 100644 index d36b7653..00000000 --- a/flow-typed/npm/strip-ansi_v3.x.x.js +++ /dev/null @@ -1,6 +0,0 @@ -// flow-typed signature: 8b05dd8048f5193e21269eab58859283 -// flow-typed version: 94e9f7e0a4/strip-ansi_v3.x.x/flow_>=v0.28.x - -declare module 'strip-ansi' { - declare module.exports: (input: string) => string; -} diff --git a/flow-typed/npm/uuid_v3.x.x.js b/flow-typed/npm/uuid_v3.x.x.js deleted file mode 100644 index 9ac28a03..00000000 --- a/flow-typed/npm/uuid_v3.x.x.js +++ /dev/null @@ -1,15 +0,0 @@ -// flow-typed signature: ca3f7f1b46804b3c09c838773ece34ba -// flow-typed version: b43dff3e0e/uuid_v3.x.x/flow_>=v0.32.x - -declare module 'uuid' { - declare function v1(options?: {| - node?: number[], - clockseq?: number, - msecs?: number | Date, - nsecs?: number, - |}, buffer?: number[] | Buffer, offset?: number): string; - declare function v4(options?: {| - random?: number[], - rng?: () => number[] | Buffer, - |}, buffer?: number[] | Buffer, offset?: number): string; -} diff --git a/index.js b/index.js index 6d25409b..5af6c15e 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,23 @@ +'use strict'; + +var _fs = _interopRequireDefault(require('fs')); + +var _path = _interopRequireDefault(require('path')); + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _FeatureLoader; + +function _load_FeatureLoader() { + return _FeatureLoader = _interopRequireDefault(require('nuclide-commons-atom/FeatureLoader')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,103 +26,79 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ /* eslint-disable rulesdir/no-commonjs */ -import fs from 'fs'; +const HIDE_WARNING_KEY = 'atom-ide-ui.hideNuclideWarning'; // eslint-disable-next-line rulesdir/prefer-nuclide-uri -import path from 'path'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import FeatureLoader from 'nuclide-commons-atom/FeatureLoader'; -const HIDE_WARNING_KEY = 'atom-ide-ui.hideNuclideWarning'; function displayNuclideWarning() { if (!atom.config.get(HIDE_WARNING_KEY)) { - const notification = atom.notifications.addInfo( - 'Atom IDE UI is bundled with Nuclide', - { - description: - '`atom-ide-ui` will be deactivated in favor of Nuclide.
' + - 'Please disable Nuclide if you only want to use `atom-ide-ui`.', - dismissable: true, - buttons: [ - { - text: 'Disable Nuclide and reload', - onDidClick() { - atom.packages.disablePackage('nuclide'); - atom.reload(); - notification.dismiss(); - }, - }, - { - text: "Don't warn me again", - onDidClick() { - atom.config.set(HIDE_WARNING_KEY, true); - notification.dismiss(); - }, - }, - ], - }, - ); + const notification = atom.notifications.addInfo('Atom IDE UI is bundled with Nuclide', { + description: '`atom-ide-ui` will be deactivated in favor of Nuclide.
' + 'Please disable Nuclide if you only want to use `atom-ide-ui`.', + dismissable: true, + buttons: [{ + text: 'Disable Nuclide and reload', + onDidClick() { + atom.packages.disablePackage('nuclide'); + atom.reload(); + notification.dismiss(); + } + }, { + text: "Don't warn me again", + onDidClick() { + atom.config.set(HIDE_WARNING_KEY, true); + notification.dismiss(); + } + }] + }); } } -if ( - !atom.packages.isPackageDisabled('nuclide') && - atom.packages.getAvailablePackageNames().includes('nuclide') -) { +if (!atom.packages.isPackageDisabled('nuclide') && atom.packages.getAvailablePackageNames().includes('nuclide')) { displayNuclideWarning(); } else { - const featureDir = path.join(__dirname, 'modules/atom-ide-ui/pkg'); - const features = fs - .readdirSync(featureDir) - .map(item => { - const dirname = path.join(featureDir, item); - try { - const pkgJson = fs.readFileSync( - path.join(dirname, 'package.json'), - 'utf8', - ); - return { - dirname, - pkg: JSON.parse(pkgJson), - }; - } catch (err) { - if (err.code !== 'ENOENT') { - throw err; - } + const featureDir = _path.default.join(__dirname, 'modules/atom-ide-ui/pkg'); + const features = _fs.default.readdirSync(featureDir).map(item => { + const dirname = _path.default.join(featureDir, item); + try { + const pkgJson = _fs.default.readFileSync(_path.default.join(dirname, 'package.json'), 'utf8'); + return { + dirname, + pkg: JSON.parse(pkgJson) + }; + } catch (err) { + if (err.code !== 'ENOENT') { + throw err; } - }) - .filter(Boolean); + } + }).filter(Boolean); /** * Use a unified package loader to load all the feature packages. * See the following post for more context: * https://nuclide.io/blog/2016/01/13/Nuclide-v0.111.0-The-Unified-Package/ */ - let disposables: ?UniversalDisposable; - const featureLoader = new FeatureLoader({ + let disposables; + const featureLoader = new (_FeatureLoader || _load_FeatureLoader()).default({ pkgName: 'atom-ide-ui', config: {}, - features, + features }); featureLoader.load(); module.exports = { config: featureLoader.getConfig(), activate() { - disposables = new UniversalDisposable( - require('nuclide-commons-ui'), - atom.packages.onDidActivatePackage(pkg => { - if (pkg.name === 'nuclide') { - displayNuclideWarning(); - } - }), - ); + disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(require('nuclide-commons-ui'), atom.packages.onDidActivatePackage(pkg => { + if (pkg.name === 'nuclide') { + displayNuclideWarning(); + } + })); featureLoader.activate(); }, deactivate() { @@ -114,6 +110,6 @@ if ( }, serialize() { featureLoader.serialize(); - }, + } }; -} +} \ No newline at end of file diff --git a/modules/.eslintrc b/modules/.eslintrc deleted file mode 100644 index aa6733c3..00000000 --- a/modules/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "rulesdir/license-header": [1, {"useBSDLicense": true}] - } -} diff --git a/modules/atom-ide-ui/index.js b/modules/atom-ide-ui/index.js index 4f755871..65cc5980 100644 --- a/modules/atom-ide-ui/index.js +++ b/modules/atom-ide-ui/index.js @@ -1,3 +1,23 @@ +'use strict'; + +var _fs = _interopRequireDefault(require('fs')); + +var _path = _interopRequireDefault(require('path')); + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _FeatureLoader; + +function _load_FeatureLoader() { + return _FeatureLoader = _interopRequireDefault(require('nuclide-commons-atom/FeatureLoader')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,96 +26,72 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ /* eslint-disable rulesdir/no-commonjs */ -import fs from 'fs'; +const HIDE_WARNING_KEY = 'atom-ide-ui.hideNuclideWarning'; // eslint-disable-next-line rulesdir/prefer-nuclide-uri -import path from 'path'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import FeatureLoader from 'nuclide-commons-atom/FeatureLoader'; -const HIDE_WARNING_KEY = 'atom-ide-ui.hideNuclideWarning'; function displayNuclideWarning() { if (!atom.config.get(HIDE_WARNING_KEY)) { - const notification = atom.notifications.addInfo( - 'Atom IDE UI is bundled with Nuclide', - { - description: - '`atom-ide-ui` will be deactivated in favor of Nuclide.
' + - 'Please disable Nuclide if you only want to use `atom-ide-ui`.', - dismissable: true, - buttons: [ - { - text: 'Disable Nuclide and reload', - onDidClick() { - atom.packages.disablePackage('nuclide'); - atom.reload(); - notification.dismiss(); - }, - }, - { - text: "Don't warn me again", - onDidClick() { - atom.config.set(HIDE_WARNING_KEY, true); - notification.dismiss(); - }, - }, - ], - }, - ); + const notification = atom.notifications.addInfo('Atom IDE UI is bundled with Nuclide', { + description: '`atom-ide-ui` will be deactivated in favor of Nuclide.
' + 'Please disable Nuclide if you only want to use `atom-ide-ui`.', + dismissable: true, + buttons: [{ + text: 'Disable Nuclide and reload', + onDidClick() { + atom.packages.disablePackage('nuclide'); + atom.reload(); + notification.dismiss(); + } + }, { + text: "Don't warn me again", + onDidClick() { + atom.config.set(HIDE_WARNING_KEY, true); + notification.dismiss(); + } + }] + }); } } -if ( - !atom.packages.isPackageDisabled('nuclide') && - atom.packages.getAvailablePackageNames().includes('nuclide') -) { +if (!atom.packages.isPackageDisabled('nuclide') && atom.packages.getAvailablePackageNames().includes('nuclide')) { displayNuclideWarning(); } else { - const featureDir = path.join(__dirname, 'pkg'); - const features = fs - .readdirSync(featureDir) - .map(item => { - const dirname = path.join(featureDir, item); - try { - const pkgJson = fs.readFileSync( - path.join(dirname, 'package.json'), - 'utf8', - ); - return { - dirname, - pkg: JSON.parse(pkgJson), - }; - } catch (err) { - if (err.code !== 'ENOENT') { - throw err; - } + const featureDir = _path.default.join(__dirname, 'pkg'); + const features = _fs.default.readdirSync(featureDir).map(item => { + const dirname = _path.default.join(featureDir, item); + try { + const pkgJson = _fs.default.readFileSync(_path.default.join(dirname, 'package.json'), 'utf8'); + return { + dirname, + pkg: JSON.parse(pkgJson) + }; + } catch (err) { + if (err.code !== 'ENOENT') { + throw err; } - }) - .filter(Boolean); - let disposables: ?UniversalDisposable; - const featureLoader = new FeatureLoader({ + } + }).filter(Boolean); + let disposables; + const featureLoader = new (_FeatureLoader || _load_FeatureLoader()).default({ pkgName: 'atom-ide-ui', config: {}, - features, + features }); featureLoader.load(); module.exports = { config: featureLoader.getConfig(), activate() { - disposables = new UniversalDisposable( - require('nuclide-commons-ui'), - atom.packages.onDidActivatePackage(pkg => { - if (pkg.name === 'nuclide') { - displayNuclideWarning(); - } - }), - ); + disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(require('nuclide-commons-ui'), atom.packages.onDidActivatePackage(pkg => { + if (pkg.name === 'nuclide') { + displayNuclideWarning(); + } + })); featureLoader.activate(); }, deactivate() { @@ -107,6 +103,6 @@ if ( }, serialize() { featureLoader.serialize(); - }, + } }; -} +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/BusyMessageInstance.js b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/BusyMessageInstance.js index 70bc682f..21182d8f 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/BusyMessageInstance.js +++ b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/BusyMessageInstance.js @@ -1,53 +1,46 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import type {BusyMessage} from './types'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.BusyMessageInstance = undefined; -import invariant from 'assert'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class BusyMessageInstance { + + constructor(publishCallback, creationOrder, waitingFor, onDidClick, disposables) { + this._titleElement = document.createElement('span'); + this._currentTitle = null; + this._isVisibleForDebounce = true; + this._isVisibleForFile = true; -export class BusyMessageInstance { - // These things are set at construction-time: - _publishCallback: () => void; - _creationOrder: number; - _waitingFor: 'computer' | 'user'; - _onDidClick: ?() => void; - _disposables: UniversalDisposable; - _titleElement: HTMLElement = document.createElement('span'); - // These things might be modified afterwards: - _currentTitle: ?string = null; - _isVisibleForDebounce: boolean = true; - _isVisibleForFile: boolean = true; - - constructor( - publishCallback: () => void, - creationOrder: number, - waitingFor: 'computer' | 'user', - onDidClick: ?() => void, - disposables: UniversalDisposable, - ) { this._publishCallback = publishCallback; this._creationOrder = creationOrder; this._waitingFor = waitingFor; this._onDidClick = onDidClick; this._disposables = disposables; } + // These things might be modified afterwards: + + // These things are set at construction-time: - get waitingFor(): 'computer' | 'user' { + + get waitingFor() { return this._waitingFor; } - setTitle(val: string): void { - invariant(!this._disposables.disposed); + setTitle(val) { + if (!!this._disposables.disposed) { + throw new Error('Invariant violation: "!this._disposables.disposed"'); + } + if (this._currentTitle === val) { return; } @@ -68,41 +61,58 @@ export class BusyMessageInstance { } } - getTitleElement(): ?HTMLElement { + getTitleElement() { return this._titleElement; } - setIsVisibleForDebounce(val: boolean): void { - invariant(!this._disposables.disposed); + setIsVisibleForDebounce(val) { + if (!!this._disposables.disposed) { + throw new Error('Invariant violation: "!this._disposables.disposed"'); + } + this._isVisibleForDebounce = val; this._publishCallback(); } - setIsVisibleForFile(val: boolean): void { - invariant(!this._disposables.disposed); + setIsVisibleForFile(val) { + if (!!this._disposables.disposed) { + throw new Error('Invariant violation: "!this._disposables.disposed"'); + } + this._isVisibleForFile = val; this._publishCallback(); } - isVisible(): boolean { - invariant(!this._disposables.disposed); - return ( - this._isVisibleForFile && - this._isVisibleForDebounce && - this._currentTitle != null - ); + isVisible() { + if (!!this._disposables.disposed) { + throw new Error('Invariant violation: "!this._disposables.disposed"'); + } + + return this._isVisibleForFile && this._isVisibleForDebounce && this._currentTitle != null; } - compare(that: BusyMessageInstance): number { + compare(that) { return this._creationOrder - that._creationOrder; } - dispose(): void { + dispose() { this._disposables.dispose(); this._currentTitle = null; this._publishCallback(); } } -// This is how we declare that a type fulfills an interface in Flow: -(((null: any): BusyMessageInstance): BusyMessage); +exports.BusyMessageInstance = BusyMessageInstance; // This is how we declare that a type fulfills an interface in Flow: +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +null; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/BusySignalSingleton.js b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/BusySignalSingleton.js index a736a344..f3baef31 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/BusySignalSingleton.js +++ b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/BusySignalSingleton.js @@ -1,3 +1,13 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,23 +16,19 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {BusySignalOptions, BusyMessage} from './types'; -import type {MessageStore} from './MessageStore'; - -export default class BusySignalSingleton { - _messageStore: MessageStore; +class BusySignalSingleton { - constructor(messageStore: MessageStore) { + constructor(messageStore) { this._messageStore = messageStore; } dispose() {} - reportBusy(title: string, options?: BusySignalOptions): BusyMessage { + reportBusy(title, options) { return this._messageStore.add(title, options || {}); } @@ -33,16 +39,17 @@ export default class BusySignalSingleton { * Used to indicate that some work is ongoing while the given asynchronous * function executes. */ - async reportBusyWhile( - title: string, - f: () => Promise, - options?: BusySignalOptions, - ): Promise { - const busySignal = this.reportBusy(title, options); - try { - return await f(); - } finally { - busySignal.dispose(); - } + reportBusyWhile(title, f, options) { + var _this = this; + + return (0, _asyncToGenerator.default)(function* () { + const busySignal = _this.reportBusy(title, options); + try { + return yield f(); + } finally { + busySignal.dispose(); + } + })(); } } +exports.default = BusySignalSingleton; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/MessageStore.js b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/MessageStore.js index 319694f5..724f0ff4 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/MessageStore.js +++ b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/MessageStore.js @@ -1,3 +1,36 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.MessageStore = undefined; + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _collection; + +function _load_collection() { + return _collection = require('nuclide-commons/collection'); +} + +var _BusyMessageInstance; + +function _load_BusyMessageInstance() { + return _BusyMessageInstance = require('./BusyMessageInstance'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// The "busy debounce delay" is for busy messages that were created with the +// 'debounce' option set to true. The icon and tooltip message won't appear +// until this many milliseconds have elapsed; if the busy message gets disposed +// before this time, then the user won't see anything. /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,85 +39,65 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {BusyMessage, BusySignalOptions} from './types'; - -import invariant from 'assert'; -import {Observable, BehaviorSubject} from 'rxjs'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import {arrayEqual} from 'nuclide-commons/collection'; -import {BusyMessageInstance} from './BusyMessageInstance'; - -// The "busy debounce delay" is for busy messages that were created with the -// 'debounce' option set to true. The icon and tooltip message won't appear -// until this many milliseconds have elapsed; if the busy message gets disposed -// before this time, then the user won't see anything. const BUSY_DEBOUNCE_DELAY = 300; -export class MessageStore { - _counter: number = 0; - _messages: Set = new Set(); - _currentVisibleMessages: Array = []; - _messageStream: BehaviorSubject< - Array, - > = new BehaviorSubject([]); +class MessageStore { + constructor() { + this._counter = 0; + this._messages = new Set(); + this._currentVisibleMessages = []; + this._messageStream = new _rxjsBundlesRxMinJs.BehaviorSubject([]); + } - getMessageStream(): Observable> { + getMessageStream() { return this._messageStream; } - dispose(): void { + dispose() { const messagesToDispose = [...this._messages]; for (const message of messagesToDispose) { message.dispose(); } - invariant(this._messages.size === 0); + + if (!(this._messages.size === 0)) { + throw new Error('Invariant violation: "this._messages.size === 0"'); + } + this._messageStream.complete(); } - _publish(): void { - const visibleMessages = [...this._messages] - .filter(m => m.isVisible()) - .sort((m1, m2) => m1.compare(m2)); + _publish() { + const visibleMessages = [...this._messages].filter(m => m.isVisible()).sort((m1, m2) => m1.compare(m2)); // We only send out on messageStream when the list of visible // BusyMessageInstance object identities has changed, e.g. when ones // are made visible or invisible or new ones are created. We don't send // out just on title change. - if (!arrayEqual(this._currentVisibleMessages, visibleMessages)) { + if (!(0, (_collection || _load_collection()).arrayEqual)(this._currentVisibleMessages, visibleMessages)) { this._messageStream.next(visibleMessages); this._currentVisibleMessages = visibleMessages; } } - add(title: string, options: BusySignalOptions): BusyMessage { + add(title, options) { this._counter++; const creationOrder = this._counter; - const waitingFor = - options != null && options.waitingFor != null - ? options.waitingFor - : 'computer'; + const waitingFor = options != null && options.waitingFor != null ? options.waitingFor : 'computer'; const onDidClick = options == null ? null : options.onDidClick; - const messageDisposables = new UniversalDisposable(); - - const message = new BusyMessageInstance( - this._publish.bind(this), - creationOrder, - waitingFor, - onDidClick, - messageDisposables, - ); + const messageDisposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(); + + const message = new (_BusyMessageInstance || _load_BusyMessageInstance()).BusyMessageInstance(this._publish.bind(this), creationOrder, waitingFor, onDidClick, messageDisposables); this._messages.add(message); messageDisposables.add(() => this._messages.delete(message)); // debounce defaults 'true' for busy-signal, and 'false' for action-required - const debounceRaw: ?boolean = options == null ? null : options.debounce; - const debounce: boolean = - debounceRaw == null ? waitingFor === 'computer' : debounceRaw; + const debounceRaw = options == null ? null : options.debounce; + const debounce = debounceRaw == null ? waitingFor === 'computer' : debounceRaw; if (debounce) { message.setIsVisibleForDebounce(false); // After the debounce time, we'll check whether the messageId is still @@ -92,14 +105,21 @@ export class MessageStore { let timeoutId = 0; const teardown = () => clearTimeout(timeoutId); timeoutId = setTimeout(() => { - invariant(!messageDisposables.disposed); - invariant(this._messages.has(message)); + if (!!messageDisposables.disposed) { + throw new Error('Invariant violation: "!messageDisposables.disposed"'); + } + + if (!this._messages.has(message)) { + throw new Error('Invariant violation: "this._messages.has(message)"'); + } // If the message was disposed, then it should have already called // clearTimeout, so this timeout handler shouldn't have been invoked. // And also the message should have been removed from this._messages. // So both tests above should necessary fail. // If the messageStore was disposed, then every message in it should // already have been disposed, as per above. + + messageDisposables.remove(teardown); message.setIsVisibleForDebounce(true); }, BUSY_DEBOUNCE_DELAY); @@ -110,10 +130,7 @@ export class MessageStore { message.setIsVisibleForFile(false); const file = options.onlyForFile; const teardown = atom.workspace.observeActivePaneItem(item => { - const activePane = - item != null && typeof item.getPath === 'function' - ? String(item.getPath()) - : null; + const activePane = item != null && typeof item.getPath === 'function' ? String(item.getPath()) : null; const newVisible = activePane === file; message.setIsVisibleForFile(newVisible); }); @@ -129,3 +146,4 @@ export class MessageStore { return message; } } +exports.MessageStore = MessageStore; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/StatusBarTile.js b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/StatusBarTile.js index d93ac993..06dcd998 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/StatusBarTile.js +++ b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/StatusBarTile.js @@ -1,3 +1,43 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = _interopRequireWildcard(require('react')); + +var _reactDom = _interopRequireDefault(require('react-dom')); + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _collection; + +function _load_collection() { + return _collection = require('nuclide-commons/collection'); +} + +var _Icon; + +function _load_Icon() { + return _Icon = require('nuclide-commons-ui/Icon'); +} + +var _BusyMessageInstance; + +function _load_BusyMessageInstance() { + return _BusyMessageInstance = require('./BusyMessageInstance'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +// We want to be the furthest left on the right side of the status bar so as not to leave a +// conspicuous gap (or cause jitter) when nothing is busy. /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,74 +46,47 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {Observable} from 'rxjs'; - -import invariant from 'assert'; -import * as React from 'react'; -import ReactDOM from 'react-dom'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import {arrayCompact} from 'nuclide-commons/collection'; -import {Icon} from 'nuclide-commons-ui/Icon'; -import {BusyMessageInstance} from './BusyMessageInstance'; - -// We want to be the furthest left on the right side of the status bar so as not to leave a -// conspicuous gap (or cause jitter) when nothing is busy. const STATUS_BAR_PRIORITY = 1000; -type Props = { - waitingForComputer: boolean, - waitingForUser: boolean, - onDidClick: ?() => void, -}; - -function StatusBarTileComponent(props: Props) { +function StatusBarTileComponent(props) { let element; if (props.waitingForUser) { - element = ; + element = _react.createElement((_Icon || _load_Icon()).Icon, { className: 'busy-signal-status-bar', icon: 'unverified' }); } else if (props.waitingForComputer) { - element =

; + element = _react.createElement('div', { className: 'busy-signal-status-bar loading-spinner-tiny' }); } else { element = null; } if (props.onDidClick != null) { - element = ( - - {element} - + element = _react.createElement( + 'a', + { onClick: props.onDidClick }, + element ); } return element; } -export default class StatusBarTile { - _item: HTMLElement; - _tile: atom$StatusBarTile; - _tooltip: ?IDisposable; - _disposables: UniversalDisposable; - _messages: Array = []; - _isMouseOverItem: boolean = false; - _isMouseOverTooltip: number = 0; - _leaveTimeoutId: ?number; - - constructor( - statusBar: atom$StatusBar, - messageStream: Observable>, - ) { +class StatusBarTile { + + constructor(statusBar, messageStream) { + this._messages = []; + this._isMouseOverItem = false; + this._isMouseOverTooltip = 0; + this._item = document.createElement('div'); this._tile = this._createTile(statusBar); - this._disposables = new UniversalDisposable( - messageStream.subscribe(messages => this._handleMessages(messages)), - ); + this._disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(messageStream.subscribe(messages => this._handleMessages(messages))); } - dispose(): void { - ReactDOM.unmountComponentAtNode(this._item); + dispose() { + _reactDom.default.unmountComponentAtNode(this._item); this._tile.destroy(); if (this._tooltip != null) { this._tooltip.dispose(); @@ -81,7 +94,7 @@ export default class StatusBarTile { this._disposables.dispose(); } - _createTile(statusBar: atom$StatusBar): atom$StatusBarTile { + _createTile(statusBar) { const item = this._item; item.className = 'inline-block'; item.addEventListener('mouseenter', () => { @@ -95,25 +108,22 @@ export default class StatusBarTile { }); const tile = statusBar.addRightTile({ item, - priority: STATUS_BAR_PRIORITY, + priority: STATUS_BAR_PRIORITY }); return tile; } - _handleMessages(messages: Array): void { + _handleMessages(messages) { this._messages = messages; - const onDidClicks = arrayCompact(messages.map(m => m._onDidClick)); + const onDidClicks = (0, (_collection || _load_collection()).arrayCompact)(messages.map(m => m._onDidClick)); - const props: Props = { + const props = { waitingForComputer: messages.some(m => m.waitingFor === 'computer'), waitingForUser: messages.some(m => m.waitingFor === 'user'), - onDidClick: - onDidClicks.length > 0 - ? () => onDidClicks.forEach(callback => callback()) - : null, + onDidClick: onDidClicks.length > 0 ? () => onDidClicks.forEach(callback => callback()) : null }; - ReactDOM.render(, this._item); + _reactDom.default.render(_react.createElement(StatusBarTileComponent, props), this._item); if (this._tooltip != null) { // If the user already had the tooltip up, then we'll either // refresh it or hide it, depending on whether the icon is now visible @@ -127,7 +137,7 @@ export default class StatusBarTile { } } - _disposeTooltip(): void { + _disposeTooltip() { if (this._tooltip != null) { this._tooltip.dispose(); this._tooltip = null; @@ -135,7 +145,7 @@ export default class StatusBarTile { } } - _ensureTooltip(): void { + _ensureTooltip() { if (this._tooltip != null) { return; } @@ -145,14 +155,18 @@ export default class StatusBarTile { body.appendChild(document.createElement('br')); } const titleElement = message.getTitleElement(); - invariant(titleElement != null); + + if (!(titleElement != null)) { + throw new Error('Invariant violation: "titleElement != null"'); + } + body.appendChild(titleElement); } this._tooltip = atom.tooltips.add(this._item, { item: body, delay: 0, - trigger: 'manual', + trigger: 'manual' }); const tooltipAtomObjects = atom.tooltips.tooltips.get(this._item); if (tooltipAtomObjects != null) { @@ -170,20 +184,17 @@ export default class StatusBarTile { } } - _startLeaveTimeoutIfNecessary(): void { - if ( - !this._isMouseOverItem && - this._isMouseOverTooltip === 0 && - this._leaveTimeoutId == null - ) { + _startLeaveTimeoutIfNecessary() { + if (!this._isMouseOverItem && this._isMouseOverTooltip === 0 && this._leaveTimeoutId == null) { this._leaveTimeoutId = setTimeout(this._disposeTooltip.bind(this), 200); } } - _stopLeaveTimeout(): void { + _stopLeaveTimeout() { if (this._leaveTimeoutId != null) { clearTimeout(this._leaveTimeoutId); this._leaveTimeoutId = null; } } } +exports.default = StatusBarTile; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/main.js b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/main.js index 0dadbe3e..effc9d5c 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/main.js +++ b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/main.js @@ -1,3 +1,37 @@ +'use strict'; + +var _createPackage; + +function _load_createPackage() { + return _createPackage = _interopRequireDefault(require('nuclide-commons-atom/createPackage')); +} + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _BusySignalSingleton; + +function _load_BusySignalSingleton() { + return _BusySignalSingleton = _interopRequireDefault(require('./BusySignalSingleton')); +} + +var _MessageStore; + +function _load_MessageStore() { + return _MessageStore = require('./MessageStore'); +} + +var _StatusBarTile; + +function _load_StatusBarTile() { + return _StatusBarTile = _interopRequireDefault(require('./StatusBarTile')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,45 +40,32 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {BusySignalService} from './types'; - -import createPackage from 'nuclide-commons-atom/createPackage'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import BusySignalSingleton from './BusySignalSingleton'; -import {MessageStore} from './MessageStore'; -import StatusBarTile from './StatusBarTile'; - class Activation { - _disposables: UniversalDisposable; - _service: BusySignalService; - _messageStore: MessageStore; constructor() { - this._messageStore = new MessageStore(); - this._service = new BusySignalSingleton(this._messageStore); - this._disposables = new UniversalDisposable(this._messageStore); + this._messageStore = new (_MessageStore || _load_MessageStore()).MessageStore(); + this._service = new (_BusySignalSingleton || _load_BusySignalSingleton()).default(this._messageStore); + this._disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(this._messageStore); } dispose() { this._disposables.dispose(); } - consumeStatusBar(statusBar: atom$StatusBar): IDisposable { + consumeStatusBar(statusBar) { // Avoid retaining StatusBarTile by wrapping it. - const disposable = new UniversalDisposable( - new StatusBarTile(statusBar, this._messageStore.getMessageStream()), - ); + const disposable = new (_UniversalDisposable || _load_UniversalDisposable()).default(new (_StatusBarTile || _load_StatusBarTile()).default(statusBar, this._messageStore.getMessageStream())); this._disposables.add(disposable); return disposable; } - provideBusySignal(): BusySignalService { + provideBusySignal() { return this._service; } } -createPackage(module.exports, Activation); +(0, (_createPackage || _load_createPackage()).default)(module.exports, Activation); \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/types.js b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/types.js index ed9e1650..a726efc4 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/types.js +++ b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/lib/types.js @@ -1,54 +1 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {NuclideUri} from 'nuclide-commons/nuclideUri'; - -export type BusySignalOptions = {| - // Can say that a busy signal will only appear when a given file is open. - // Default = null, meaning the busy signal applies to all files. - onlyForFile?: NuclideUri, - // Is user waiting for computer to finish a task? (traditional busy spinner) - // or is the computer waiting for user to finish a task? (action required) - // Default = spinner. - waitingFor?: 'computer' | 'user', - // Debounce it? default = true for busy-signal, and false for action-required. - debounce?: boolean, - // If onClick is set, then the tooltip will be clickable. Default = null. - onDidClick?: () => void, -|}; - -export type BusySignalService = { - // Activates the busy signal with the given title and returns the promise - // from the provided callback. - // The busy signal automatically deactivates when the returned promise - // either resolves or rejects. - reportBusyWhile( - title: string, - f: () => Promise, - options?: BusySignalOptions, - ): Promise, - - // Activates the busy signal. Set the title in the returned BusySignal - // object (you can update the title multiple times) and dispose it when done. - reportBusy(title: string, options?: BusySignalOptions): BusyMessage, - - // This is a no-op. When someone consumes the busy service, they get back a - // reference to the single shared instance, so disposing of it would be wrong. - dispose(): void, -}; - -export type BusyMessage = { - // You can set/update the title. - setTitle(title: string): void, - // Dispose of the signal when done to make it go away. - dispose(): void, -}; +'use strict'; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/spec/BusySignalInstance-spec.js b/modules/atom-ide-ui/pkg/atom-ide-busy-signal/spec/BusySignalInstance-spec.js deleted file mode 100644 index 22da4509..00000000 --- a/modules/atom-ide-ui/pkg/atom-ide-busy-signal/spec/BusySignalInstance-spec.js +++ /dev/null @@ -1,129 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {BusySignalOptions} from '../lib/types'; - -import {MessageStore} from '../lib/MessageStore'; -import BusySignalSingleton from '../lib/BusySignalSingleton'; - -describe('BusySignalSingleton', () => { - let messageStore: MessageStore; - let singleton: BusySignalSingleton; - let messages: Array>; - const options: BusySignalOptions = {debounce: false}; - - beforeEach(() => { - messageStore = new MessageStore(); - singleton = new BusySignalSingleton(messageStore); - messages = []; - messageStore.getMessageStream().skip(1).subscribe(elements => { - const strings = [...elements].map(element => { - const titleElement = element.getTitleElement(); - const child = - titleElement != null && titleElement.childNodes.length >= 1 - ? titleElement.childNodes[0] - : {}; - return child.data != null && typeof child.data === 'string' - ? child.data - : ''; - }); - messages.push(strings); - }); - }); - - it('should record messages before and after a call', () => { - expect(messages.length).toBe(0); - singleton.reportBusyWhile('foo', () => Promise.resolve(5), options); - expect(messages.length).toBe(1); - waitsFor( - () => messages.length === 2, - 'It should publish a second message', - 100, - ); - }); - - it("should send the 'done' message even if the promise rejects", () => { - singleton.reportBusyWhile( - 'foo', - () => Promise.reject(new Error()), - options, - ); - expect(messages.length).toBe(1); - waitsFor( - () => messages.length === 2, - 'It should publish a second message', - 100, - ); - }); - - it('should properly display duplicate messages', () => { - const dispose1 = singleton.reportBusy('foo', options); - expect(messages.length).toBe(1); - expect(messages[0]).toEqual(['foo']); - - const dispose2 = singleton.reportBusy('foo', options); - expect(messages.length).toBe(2); - expect(messages[1]).toEqual(['foo', 'foo']); - - dispose2.dispose(); - expect(messages.length).toBe(3); - expect(messages[2]).toEqual(['foo']); - - dispose1.dispose(); - expect(messages.length).toBe(4); - expect(messages[3]).toEqual([]); - }); - - describe('when onlyForFile is provided', () => { - let editor1: atom$TextEditor = (null: any); - let editor2: atom$TextEditor = (null: any); - let editor3: atom$TextEditor = (null: any); - - beforeEach(() => { - waitsForPromise(async () => { - editor1 = await atom.workspace.open('/file1.txt'); - editor2 = await atom.workspace.open('/file2.txt'); - editor3 = await atom.workspace.open(); - }); - }); - - afterEach(() => { - [editor1, editor2, editor3].forEach(editor => editor.destroy()); - }); - - it('should only display for the proper text editor', () => { - atom.workspace.getActivePane().activateItem(editor1); - - const disposable = singleton.reportBusy('foo', { - onlyForFile: '/file2.txt', - ...options, - }); - expect(messages).toEqual([]); - - atom.workspace.getActivePane().activateItem(editor2); - expect(messages.length).toBe(1); - expect(messages[0]).toEqual(['foo']); - - atom.workspace.getActivePane().activateItem(editor3); - expect(messages.length).toBe(2); - expect(messages[1]).toEqual([]); - - atom.workspace.getActivePane().activateItem(editor2); - expect(messages.length).toBe(3); - expect(messages[2]).toEqual(['foo']); - - disposable.dispose(); - expect(messages.length).toBe(4); - expect(messages[3]).toEqual([]); - }); - }); -}); diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/CodeActionManager.js b/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/CodeActionManager.js index af44194e..146b14d6 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/CodeActionManager.js +++ b/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/CodeActionManager.js @@ -1,60 +1,72 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import ProviderRegistry from 'nuclide-commons-atom/ProviderRegistry'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import {arrayFlatten} from 'nuclide-commons/collection'; - -import type {CodeActionProvider, CodeActionFetcher} from './types'; - -export class CodeActionManager { - _providerRegistry: ProviderRegistry; - _disposables: UniversalDisposable; +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.CodeActionManager = undefined; + +var _ProviderRegistry; + +function _load_ProviderRegistry() { + return _ProviderRegistry = _interopRequireDefault(require('nuclide-commons-atom/ProviderRegistry')); +} + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _collection; + +function _load_collection() { + return _collection = require('nuclide-commons/collection'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class CodeActionManager { constructor() { - this._providerRegistry = new ProviderRegistry(); - this._disposables = new UniversalDisposable(); + this._providerRegistry = new (_ProviderRegistry || _load_ProviderRegistry()).default(); + this._disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(); } dispose() { this._disposables.dispose(); } - addProvider(provider: CodeActionProvider): IDisposable { + addProvider(provider) { const disposable = this._providerRegistry.addProvider(provider); this._disposables.add(disposable); return disposable; } - createCodeActionFetcher(): CodeActionFetcher { + createCodeActionFetcher() { return { getCodeActionForDiagnostic: (diagnostic, editor) => { if (diagnostic.range) { - const {range} = diagnostic; + const { range } = diagnostic; const codeActionRequests = []; - for (const provider of this._providerRegistry.getAllProvidersForEditor( - editor, - )) { - codeActionRequests.push( - provider.getCodeActions(editor, range, [diagnostic]), - ); + for (const provider of this._providerRegistry.getAllProvidersForEditor(editor)) { + codeActionRequests.push(provider.getCodeActions(editor, range, [diagnostic])); } - return Promise.all(codeActionRequests).then(results => - arrayFlatten(results), - ); + return Promise.all(codeActionRequests).then(results => (0, (_collection || _load_collection()).arrayFlatten)(results)); } return Promise.resolve([]); - }, + } }; } } +exports.CodeActionManager = CodeActionManager; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/main.js b/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/main.js index 74d5b390..60b794dd 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/main.js +++ b/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/main.js @@ -1,3 +1,19 @@ +'use strict'; + +var _createPackage; + +function _load_createPackage() { + return _createPackage = _interopRequireDefault(require('nuclide-commons-atom/createPackage')); +} + +var _CodeActionManager; + +function _load_CodeActionManager() { + return _CodeActionManager = require('./CodeActionManager'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,33 +22,27 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import createPackage from 'nuclide-commons-atom/createPackage'; -import {CodeActionManager} from './CodeActionManager'; - -import type {CodeActionProvider, CodeActionFetcher} from './types'; - class Activation { - _codeActionManager: CodeActionManager; constructor() { - this._codeActionManager = new CodeActionManager(); + this._codeActionManager = new (_CodeActionManager || _load_CodeActionManager()).CodeActionManager(); } dispose() { this._codeActionManager.dispose(); } - consumeCodeActionProvider(provider: CodeActionProvider) { + consumeCodeActionProvider(provider) { return this._codeActionManager.addProvider(provider); } - provideCodeActionFetcher(): CodeActionFetcher { + provideCodeActionFetcher() { return this._codeActionManager.createCodeActionFetcher(); } } -createPackage(module.exports, Activation); +(0, (_createPackage || _load_createPackage()).default)(module.exports, Activation); \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/types.js b/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/types.js index e9771d32..a726efc4 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/types.js +++ b/modules/atom-ide-ui/pkg/atom-ide-code-actions/lib/types.js @@ -1,42 +1 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {FileDiagnosticMessage} from '../../../pkg/atom-ide-diagnostics/lib/types'; - -export interface CodeAction { - apply(): Promise, - getTitle(): Promise, - dispose(): void, -} - -export type CodeActionProvider = { - grammarScopes: Array, - priority: number, - getCodeActions( - editor: atom$TextEditor, - range: atom$Range, - diagnostics: Array, - ): Promise>, -}; - -/** -* atom-ide-code-actions provides a CodeActionFetcher which offers an API to -* request CodeActions from all CodeAction providers. For now, CodeActionFetcher -* can only fetch CodeActions for a Diagnostic. In the future, this API can be -* extended to provide a stream of CodeActions based on the cursor position. -*/ -export type CodeActionFetcher = { - getCodeActionForDiagnostic: ( - diagnostic: FileDiagnosticMessage, - editor: atom$TextEditor, - ) => Promise>, -}; +'use strict'; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/CodeFormatManager.js b/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/CodeFormatManager.js index b71da759..9073b1e4 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/CodeFormatManager.js +++ b/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/CodeFormatManager.js @@ -1,3 +1,76 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _atom = require('atom'); + +var _semver; + +function _load_semver() { + return _semver = _interopRequireDefault(require('semver')); +} + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _event; + +function _load_event() { + return _event = require('nuclide-commons/event'); +} + +var _nuclideUri; + +function _load_nuclideUri() { + return _nuclideUri = _interopRequireDefault(require('nuclide-commons/nuclideUri')); +} + +var _observable; + +function _load_observable() { + return _observable = require('nuclide-commons/observable'); +} + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _ProviderRegistry; + +function _load_ProviderRegistry() { + return _ProviderRegistry = _interopRequireDefault(require('nuclide-commons-atom/ProviderRegistry')); +} + +var _textEditor; + +function _load_textEditor() { + return _textEditor = require('nuclide-commons-atom/text-editor'); +} + +var _textEdit; + +function _load_textEdit() { + return _textEdit = require('nuclide-commons-atom/text-edit'); +} + +var _config; + +function _load_config() { + return _config = require('./config'); +} + +var _log4js; + +function _load_log4js() { + return _log4js = require('log4js'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Save events are critical, so don't allow providers to block them. /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,62 +79,20 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {BusySignalService} from '../../atom-ide-busy-signal/lib/types'; -import type { - RangeCodeFormatProvider, - FileCodeFormatProvider, - OnTypeCodeFormatProvider, - OnSaveCodeFormatProvider, -} from './types'; - -import {Range} from 'atom'; -import semver from 'semver'; -import {Observable, Subject} from 'rxjs'; -import {observableFromSubscribeFunction} from 'nuclide-commons/event'; -import nuclideUri from 'nuclide-commons/nuclideUri'; -import {microtask} from 'nuclide-commons/observable'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import ProviderRegistry from 'nuclide-commons-atom/ProviderRegistry'; -import { - observeEditorDestroy, - observeTextEditors, -} from 'nuclide-commons-atom/text-editor'; -import {applyTextEditsToBuffer} from 'nuclide-commons-atom/text-edit'; -import {getFormatOnSave, getFormatOnType} from './config'; -import {getLogger} from 'log4js'; - -// Save events are critical, so don't allow providers to block them. const SAVE_TIMEOUT = 2500; -type FormatEvent = - | { - type: 'command' | 'save' | 'new-save', - editor: atom$TextEditor, - } - | { - type: 'type', - editor: atom$TextEditor, - edit: atom$TextEditEvent, - }; - -export default class CodeFormatManager { - _subscriptions: UniversalDisposable; - _rangeProviders: ProviderRegistry; - _fileProviders: ProviderRegistry; - _onTypeProviders: ProviderRegistry; - _onSaveProviders: ProviderRegistry; - _busySignalService: ?BusySignalService; +class CodeFormatManager { constructor() { - this._subscriptions = new UniversalDisposable(this._subscribeToEvents()); - this._rangeProviders = new ProviderRegistry(); - this._fileProviders = new ProviderRegistry(); - this._onTypeProviders = new ProviderRegistry(); - this._onSaveProviders = new ProviderRegistry(); + this._subscriptions = new (_UniversalDisposable || _load_UniversalDisposable()).default(this._subscribeToEvents()); + this._rangeProviders = new (_ProviderRegistry || _load_ProviderRegistry()).default(); + this._fileProviders = new (_ProviderRegistry || _load_ProviderRegistry()).default(); + this._onTypeProviders = new (_ProviderRegistry || _load_ProviderRegistry()).default(); + this._onSaveProviders = new (_ProviderRegistry || _load_ProviderRegistry()).default(); } /** @@ -70,84 +101,61 @@ export default class CodeFormatManager { * By handling all events in a central location, we ensure that no buffer * runs into race conditions with simultaneous formatters. */ - _subscribeToEvents(): rxjs$Subscription { + _subscribeToEvents() { // Events from the explicit Atom command. - const commandEvents = observableFromSubscribeFunction(callback => - atom.commands.add( - 'atom-text-editor', - 'code-format:format-code', - callback, - ), - ).switchMap(() => { + const commandEvents = (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => atom.commands.add('atom-text-editor', 'code-format:format-code', callback)).switchMap(() => { const editor = atom.workspace.getActiveTextEditor(); if (!editor) { - return Observable.empty(); + return _rxjsBundlesRxMinJs.Observable.empty(); } - return Observable.of({type: 'command', editor}); + return _rxjsBundlesRxMinJs.Observable.of({ type: 'command', editor }); }); // Events from editor actions (saving, typing). - const editorEvents = observableFromSubscribeFunction( - observeTextEditors, - ).mergeMap(editor => this._getEditorEventStream(editor)); - - return ( - Observable.merge(commandEvents, editorEvents) - // Group events by buffer to prevent simultaneous formatting operations. - .groupBy( - event => event.editor.getBuffer(), - event => event, - grouped => - // $FlowFixMe: add durationSelector to groupBy - observableFromSubscribeFunction(callback => - // $FlowFixMe: add key to GroupedObservable - grouped.key.onDidDestroy(callback), - ), - ) - .mergeMap(events => - // Concatenate a null event to ensure that buffer destruction - // interrupts any pending format operations. - events.concat(Observable.of(null)).switchMap(event => { - if (event == null) { - return Observable.empty(); - } - return this._handleEvent(event); - }), - ) - .subscribe() - ); + const editorEvents = (0, (_event || _load_event()).observableFromSubscribeFunction)((_textEditor || _load_textEditor()).observeTextEditors).mergeMap(editor => this._getEditorEventStream(editor)); + + return _rxjsBundlesRxMinJs.Observable.merge(commandEvents, editorEvents) + // Group events by buffer to prevent simultaneous formatting operations. + .groupBy(event => event.editor.getBuffer(), event => event, grouped => + // $FlowFixMe: add durationSelector to groupBy + (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => + // $FlowFixMe: add key to GroupedObservable + grouped.key.onDidDestroy(callback))).mergeMap(events => + // Concatenate a null event to ensure that buffer destruction + // interrupts any pending format operations. + events.concat(_rxjsBundlesRxMinJs.Observable.of(null)).switchMap(event => { + if (event == null) { + return _rxjsBundlesRxMinJs.Observable.empty(); + } + return this._handleEvent(event); + })).subscribe(); } /** * Returns a stream of all typing and saving operations from the editor. */ - _getEditorEventStream(editor: atom$TextEditor): Observable { - const changeEvents = observableFromSubscribeFunction(callback => - editor.getBuffer().onDidChange(callback), - ) - // Debounce to ensure that multiple cursors only trigger one format. - // TODO(hansonw): Use onDidChangeText with 1.17+. - .debounceTime(0); - - const saveEvents = Observable.create(observer => { + _getEditorEventStream(editor) { + const changeEvents = (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => editor.getBuffer().onDidChange(callback)) + // Debounce to ensure that multiple cursors only trigger one format. + // TODO(hansonw): Use onDidChangeText with 1.17+. + .debounceTime(0); + + const saveEvents = _rxjsBundlesRxMinJs.Observable.create(observer => { const realSave = editor.save; - const newSaves = new Subject(); + const newSaves = new _rxjsBundlesRxMinJs.Subject(); // HACK: intercept the real TextEditor.save and handle it ourselves. // Atom has no way of injecting content into the buffer asynchronously // before a save operation. // If we try to format after the save, and then save again, // it's a poor user experience (and also races the text buffer's reload). - const editor_ = (editor: any); + const editor_ = editor; editor_.save = () => { // TODO(19829039): remove check - if (semver.gte(atom.getVersion(), '1.19.0-beta0')) { + if ((_semver || _load_semver()).default.gte(atom.getVersion(), '1.19.0-beta0')) { // In 1.19, TextEditor.save() is async (and the promise is used). // We can just directly format + save here. newSaves.next('new-save'); - return this._safeFormatCodeOnSave(editor) - .takeUntil(newSaves) - .toPromise() - .then(() => realSave.call(editor)); + return this._safeFormatCodeOnSave(editor).takeUntil(newSaves).toPromise().then(() => realSave.call(editor)); } else { observer.next('save'); } @@ -163,81 +171,59 @@ export default class CodeFormatManager { // We need to capture when editors are about to be destroyed in order to // interrupt any pending formatting operations. (Otherwise, we may end up // attempting to save a destroyed editor!) - const willDestroyEvents = observableFromSubscribeFunction(cb => - atom.workspace.onWillDestroyPaneItem(cb), - ).filter(event => event.item === editor); - - return Observable.merge( - changeEvents.map(edit => ({type: 'type', editor, edit})), - saveEvents.map(type => ({type, editor})), - ).takeUntil( - Observable.merge(observeEditorDestroy(editor), willDestroyEvents), - ); + const willDestroyEvents = (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => atom.workspace.onWillDestroyPaneItem(cb)).filter(event => event.item === editor); + + return _rxjsBundlesRxMinJs.Observable.merge(changeEvents.map(edit => ({ type: 'type', editor, edit })), saveEvents.map(type => ({ type, editor }))).takeUntil(_rxjsBundlesRxMinJs.Observable.merge((0, (_textEditor || _load_textEditor()).observeEditorDestroy)(editor), willDestroyEvents)); } - _handleEvent(event: FormatEvent): Observable { - const {editor} = event; + _handleEvent(event) { + const { editor } = event; switch (event.type) { case 'command': - return this._formatCodeInTextEditor(editor) - .map(result => { - if (!result) { - throw new Error('No code formatting providers found!'); - } - }) - .catch(err => { - atom.notifications.addError( - `Failed to format code: ${err.message}`, - { - detail: err.detail, - }, - ); - return Observable.empty(); + return this._formatCodeInTextEditor(editor).map(result => { + if (!result) { + throw new Error('No code formatting providers found!'); + } + }).catch(err => { + atom.notifications.addError(`Failed to format code: ${err.message}`, { + detail: err.detail }); + return _rxjsBundlesRxMinJs.Observable.empty(); + }); case 'type': - return this._formatCodeOnTypeInTextEditor( - editor, - event.edit, - ).catch(err => { - getLogger('code-format').warn('Failed to format code on type:', err); - return Observable.empty(); + return this._formatCodeOnTypeInTextEditor(editor, event.edit).catch(err => { + (0, (_log4js || _load_log4js()).getLogger)('code-format').warn('Failed to format code on type:', err); + return _rxjsBundlesRxMinJs.Observable.empty(); }); case 'save': - return ( - this._safeFormatCodeOnSave(editor) - // Fire-and-forget the original save function. - // This is actually async for remote files, but we don't use the result. - // NOTE: finally is important, as saves should still fire on unsubscribe. - .finally(() => editor.getBuffer().save()) - ); + return this._safeFormatCodeOnSave(editor) + // Fire-and-forget the original save function. + // This is actually async for remote files, but we don't use the result. + // NOTE: finally is important, as saves should still fire on unsubscribe. + .finally(() => editor.getBuffer().save()); case 'new-save': - return Observable.empty(); + return _rxjsBundlesRxMinJs.Observable.empty(); default: - return Observable.throw(`unknown event type ${event.type}`); + return _rxjsBundlesRxMinJs.Observable.throw(`unknown event type ${event.type}`); } } // Checks whether contents are same in the buffer post-format, throwing if // anything has changed. - _checkContentsAreSame(before: string, after: string): void { + _checkContentsAreSame(before, after) { if (before !== after) { - throw new Error( - 'The file contents were changed before formatting was complete.', - ); + throw new Error('The file contents were changed before formatting was complete.'); } } // Formats code in the editor specified, returning whether or not a // code formatter completed successfully. - _formatCodeInTextEditor( - editor: atom$TextEditor, - range?: atom$Range, - ): Observable { - return Observable.defer(() => { + _formatCodeInTextEditor(editor, range) { + return _rxjsBundlesRxMinJs.Observable.defer(() => { const buffer = editor.getBuffer(); const selectionRange = range || editor.getSelectedBufferRange(); - const {start: selectionStart, end: selectionEnd} = selectionRange; - let formatRange: atom$Range; + const { start: selectionStart, end: selectionEnd } = selectionRange; + let formatRange; if (selectionRange.isEmpty()) { // If no selection is done, then, the whole file is wanted to be formatted. formatRange = buffer.getRange(); @@ -249,47 +235,29 @@ export default class CodeFormatManager { // or (2) at the first column of the line AFTER their selection. In both cases // we snap the formatRange to end at the first column of the line after their // selection.) - formatRange = new Range( - [selectionStart.row, 0], - selectionEnd.column === 0 ? selectionEnd : [selectionEnd.row + 1, 0], - ); + formatRange = new _atom.Range([selectionStart.row, 0], selectionEnd.column === 0 ? selectionEnd : [selectionEnd.row + 1, 0]); } const rangeProvider = this._rangeProviders.getProviderForEditor(editor); const fileProvider = this._fileProviders.getProviderForEditor(editor); const contents = editor.getText(); - if ( - rangeProvider != null && - // When formatting the entire file, prefer file-based providers. - (!formatRange.isEqual(buffer.getRange()) || fileProvider == null) - ) { - return Observable.defer(() => - this._reportBusy( - editor, - rangeProvider.formatCode(editor, formatRange), - ), - ).map(edits => { + if (rangeProvider != null && ( + // When formatting the entire file, prefer file-based providers. + !formatRange.isEqual(buffer.getRange()) || fileProvider == null)) { + return _rxjsBundlesRxMinJs.Observable.defer(() => this._reportBusy(editor, rangeProvider.formatCode(editor, formatRange))).map(edits => { // Throws if contents have changed since the time of triggering format code. this._checkContentsAreSame(contents, editor.getText()); - if (!applyTextEditsToBuffer(editor.getBuffer(), edits)) { + if (!(0, (_textEdit || _load_textEdit()).applyTextEditsToBuffer)(editor.getBuffer(), edits)) { throw new Error('Could not apply edits to text buffer.'); } return true; }); } else if (fileProvider != null) { - return Observable.defer(() => - this._reportBusy( - editor, - fileProvider.formatEntireFile(editor, formatRange), - ), - ).map(({newCursor, formatted}) => { + return _rxjsBundlesRxMinJs.Observable.defer(() => this._reportBusy(editor, fileProvider.formatEntireFile(editor, formatRange))).map(({ newCursor, formatted }) => { // Throws if contents have changed since the time of triggering format code. this._checkContentsAreSame(contents, editor.getText()); buffer.setTextViaDiff(formatted); - const newPosition = - newCursor != null - ? buffer.positionForCharacterIndex(newCursor) - : editor.getCursorBufferPosition(); + const newPosition = newCursor != null ? buffer.positionForCharacterIndex(newCursor) : editor.getCursorBufferPosition(); // We call setCursorBufferPosition even when there is no newCursor, // because it unselects the text selection. @@ -297,19 +265,16 @@ export default class CodeFormatManager { return true; }); } else { - return Observable.of(false); + return _rxjsBundlesRxMinJs.Observable.of(false); } }); } - _formatCodeOnTypeInTextEditor( - editor: atom$TextEditor, - event: atom$TextEditEvent, - ): Observable { - return Observable.defer(() => { + _formatCodeOnTypeInTextEditor(editor, event) { + return _rxjsBundlesRxMinJs.Observable.defer(() => { // This also ensures the non-emptiness of event.newText for below. - if (!shouldFormatOnType(event) || !getFormatOnType()) { - return Observable.empty(); + if (!shouldFormatOnType(event) || !(0, (_config || _load_config()).getFormatOnType)()) { + return _rxjsBundlesRxMinJs.Observable.empty(); } // In the case of bracket-matching, we use the last character because that's // the character that will usually cause a reformat (i.e. `}` instead of `{`). @@ -317,7 +282,7 @@ export default class CodeFormatManager { const provider = this._onTypeProviders.getProviderForEditor(editor); if (provider == null) { - return Observable.empty(); + return _rxjsBundlesRxMinJs.Observable.empty(); } const contents = editor.getText(); @@ -334,89 +299,70 @@ export default class CodeFormatManager { // We want to wait until the cursor has actually moved before we issue a // format request, so that we format at the right position (and potentially // also let any other event handlers have their go). - return microtask - .switchMap(() => - provider.formatAtPosition( - editor, - editor.getCursorBufferPosition().translate([0, -1]), - character, - ), - ) - .map(edits => { - if (edits.length === 0) { - return; - } - this._checkContentsAreSame(contents, editor.getText()); - // Note that this modification is not in a transaction, so it applies as a - // separate editing event than the character typing. This means that you - // can undo just the formatting by attempting to undo once, and then undo - // your actual code by undoing again. - if (!applyTextEditsToBuffer(editor.getBuffer(), edits)) { - throw new Error('Could not apply edits to text buffer.'); - } - }); + return (_observable || _load_observable()).microtask.switchMap(() => provider.formatAtPosition(editor, editor.getCursorBufferPosition().translate([0, -1]), character)).map(edits => { + if (edits.length === 0) { + return; + } + this._checkContentsAreSame(contents, editor.getText()); + // Note that this modification is not in a transaction, so it applies as a + // separate editing event than the character typing. This means that you + // can undo just the formatting by attempting to undo once, and then undo + // your actual code by undoing again. + if (!(0, (_textEdit || _load_textEdit()).applyTextEditsToBuffer)(editor.getBuffer(), edits)) { + throw new Error('Could not apply edits to text buffer.'); + } + }); }); } - _safeFormatCodeOnSave(editor: atom$TextEditor): Observable { - return this._formatCodeOnSaveInTextEditor(editor) - .timeout(SAVE_TIMEOUT) - .catch(err => { - getLogger('code-format').warn('Failed to format code on save:', err); - return Observable.empty(); - }); + _safeFormatCodeOnSave(editor) { + return this._formatCodeOnSaveInTextEditor(editor).timeout(SAVE_TIMEOUT).catch(err => { + (0, (_log4js || _load_log4js()).getLogger)('code-format').warn('Failed to format code on save:', err); + return _rxjsBundlesRxMinJs.Observable.empty(); + }); } - _formatCodeOnSaveInTextEditor(editor: atom$TextEditor): Observable { + _formatCodeOnSaveInTextEditor(editor) { const saveProvider = this._onSaveProviders.getProviderForEditor(editor); if (saveProvider != null) { - return Observable.defer(() => - this._reportBusy(editor, saveProvider.formatOnSave(editor)), - ).map(edits => { - applyTextEditsToBuffer(editor.getBuffer(), edits); + return _rxjsBundlesRxMinJs.Observable.defer(() => this._reportBusy(editor, saveProvider.formatOnSave(editor))).map(edits => { + (0, (_textEdit || _load_textEdit()).applyTextEditsToBuffer)(editor.getBuffer(), edits); }); - } else if (getFormatOnSave()) { - return this._formatCodeInTextEditor( - editor, - editor.getBuffer().getRange(), - ).ignoreElements(); + } else if ((0, (_config || _load_config()).getFormatOnSave)()) { + return this._formatCodeInTextEditor(editor, editor.getBuffer().getRange()).ignoreElements(); } - return Observable.empty(); + return _rxjsBundlesRxMinJs.Observable.empty(); } - _reportBusy(editor: atom$TextEditor, promise: Promise): Promise { + _reportBusy(editor, promise) { const busySignalService = this._busySignalService; if (busySignalService != null) { const path = editor.getPath(); - const displayPath = - path != null ? nuclideUri.basename(path) : ''; - return busySignalService.reportBusyWhile( - `Formatting code in ${displayPath}`, - () => promise, - ); + const displayPath = path != null ? (_nuclideUri || _load_nuclideUri()).default.basename(path) : ''; + return busySignalService.reportBusyWhile(`Formatting code in ${displayPath}`, () => promise); } return promise; } - addRangeProvider(provider: RangeCodeFormatProvider): IDisposable { + addRangeProvider(provider) { return this._rangeProviders.addProvider(provider); } - addFileProvider(provider: FileCodeFormatProvider): IDisposable { + addFileProvider(provider) { return this._fileProviders.addProvider(provider); } - addOnTypeProvider(provider: OnTypeCodeFormatProvider): IDisposable { + addOnTypeProvider(provider) { return this._onTypeProviders.addProvider(provider); } - addOnSaveProvider(provider: OnSaveCodeFormatProvider): IDisposable { + addOnSaveProvider(provider) { return this._onSaveProviders.addProvider(provider); } - consumeBusySignal(busySignalService: BusySignalService): IDisposable { + consumeBusySignal(busySignalService) { this._busySignalService = busySignalService; - return new UniversalDisposable(() => { + return new (_UniversalDisposable || _load_UniversalDisposable()).default(() => { this._busySignalService = null; }); } @@ -426,7 +372,8 @@ export default class CodeFormatManager { } } -function shouldFormatOnType(event: atom$TextEditEvent): boolean { +exports.default = CodeFormatManager; +function shouldFormatOnType(event) { // There's not a direct way to figure out what caused this edit event. There // are three cases that we want to pay attention to: // @@ -460,12 +407,10 @@ function shouldFormatOnType(event: atom$TextEditEvent): boolean { * inserting an extra bracket, so we just assume that any pair of brackets that * bracket-matcher recognizes was a pair matched by the package. */ -function isBracketPair(typedText: string): boolean { +function isBracketPair(typedText) { if (atom.packages.getActivePackage('bracket-matcher') == null) { return false; } - const validBracketPairs: Array = (atom.config.get( - 'bracket-matcher.autocompleteCharacters', - ): any); + const validBracketPairs = atom.config.get('bracket-matcher.autocompleteCharacters'); return validBracketPairs.indexOf(typedText) !== -1; -} +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/config.js b/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/config.js index 8c50f9e4..c6ff1528 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/config.js +++ b/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/config.js @@ -1,27 +1,34 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import featureConfig from 'nuclide-commons-atom/feature-config'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getFormatOnSave = getFormatOnSave; +exports.getFormatOnType = getFormatOnType; -export function getFormatOnSave(): boolean { - const formatOnSave = (featureConfig.get( - 'atom-ide-code-format.formatOnSave', - ): any); - return formatOnSave == null ? false : formatOnSave; -} +var _featureConfig; -export function getFormatOnType(): boolean { - return featureConfig.getWithDefaults( - 'atom-ide-code-format.formatOnType', - false, - ); +function _load_featureConfig() { + return _featureConfig = _interopRequireDefault(require('nuclide-commons-atom/feature-config')); } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getFormatOnSave() { + const formatOnSave = (_featureConfig || _load_featureConfig()).default.get('atom-ide-code-format.formatOnSave'); + return formatOnSave == null ? false : formatOnSave; +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +function getFormatOnType() { + return (_featureConfig || _load_featureConfig()).default.getWithDefaults('atom-ide-code-format.formatOnType', false); +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/main.js b/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/main.js index 946f6d7b..04f6c87f 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/main.js +++ b/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/main.js @@ -1,3 +1,19 @@ +'use strict'; + +var _createPackage; + +function _load_createPackage() { + return _createPackage = _interopRequireDefault(require('nuclide-commons-atom/createPackage')); +} + +var _CodeFormatManager; + +function _load_CodeFormatManager() { + return _CodeFormatManager = _interopRequireDefault(require('./CodeFormatManager')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,38 +22,20 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {BusySignalService} from '../../atom-ide-busy-signal/lib/types'; -import type { - CodeFormatProvider, - RangeCodeFormatProvider, - FileCodeFormatProvider, - OnTypeCodeFormatProvider, - OnSaveCodeFormatProvider, -} from './types'; - -import createPackage from 'nuclide-commons-atom/createPackage'; -import CodeFormatManager from './CodeFormatManager'; - class Activation { - codeFormatManager: CodeFormatManager; constructor() { - this.codeFormatManager = new CodeFormatManager(); + this.codeFormatManager = new (_CodeFormatManager || _load_CodeFormatManager()).default(); } - consumeLegacyProvider(provider: CodeFormatProvider): IDisposable { + consumeLegacyProvider(provider) { // Legacy providers used `selector` / `inclusionPriority`. - provider.grammarScopes = - provider.grammarScopes || - (provider.selector != null ? provider.selector.split(', ') : null); - provider.priority = - provider.priority != null - ? provider.priority - : provider.inclusionPriority != null ? provider.inclusionPriority : 0; + provider.grammarScopes = provider.grammarScopes || (provider.selector != null ? provider.selector.split(', ') : null); + provider.priority = provider.priority != null ? provider.priority : provider.inclusionPriority != null ? provider.inclusionPriority : 0; if (provider.formatCode) { return this.consumeRangeProvider(provider); } else if (provider.formatEntireFile) { @@ -50,23 +48,23 @@ class Activation { throw new Error('Invalid code format provider'); } - consumeRangeProvider(provider: RangeCodeFormatProvider): IDisposable { + consumeRangeProvider(provider) { return this.codeFormatManager.addRangeProvider(provider); } - consumeFileProvider(provider: FileCodeFormatProvider): IDisposable { + consumeFileProvider(provider) { return this.codeFormatManager.addFileProvider(provider); } - consumeOnTypeProvider(provider: OnTypeCodeFormatProvider): IDisposable { + consumeOnTypeProvider(provider) { return this.codeFormatManager.addOnTypeProvider(provider); } - consumeOnSaveProvider(provider: OnSaveCodeFormatProvider): IDisposable { + consumeOnSaveProvider(provider) { return this.codeFormatManager.addOnSaveProvider(provider); } - consumeBusySignal(busySignalService: BusySignalService): IDisposable { + consumeBusySignal(busySignalService) { return this.codeFormatManager.consumeBusySignal(busySignalService); } @@ -75,4 +73,4 @@ class Activation { } } -createPackage(module.exports, Activation); +(0, (_createPackage || _load_createPackage()).default)(module.exports, Activation); \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/types.js b/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/types.js index 971a82d6..a726efc4 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/types.js +++ b/modules/atom-ide-ui/pkg/atom-ide-code-format/lib/types.js @@ -1,96 +1 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {TextEdit} from 'nuclide-commons-atom/text-edit'; - -/** - * A brief overview of the different code formatting providers: - * - * == Range formatters == - * These accept a range to format and return a list of edits to apply. - * These will always be preferred over file formatters when a range is selected. - * - * == File formatters == - * These always return the result of formatting the entire file. - * To compensate, they can return a custom cursor position to avoid disruption. - * These will be preferred over range formatters for whole-file formatting. - * - * == onType formatters == - * These are run after every typing event in a selected editor. - * - * == onSave formatters == - * These are run whenever a selected editor is saved. - * If the global format-on-save option is enabled, then file/range formatters - * will be triggered on save (even if no save formatters are provided). - * Obviously, save formatters are preferred in this case. - */ - -/** - * Formats the range specified, and returns a list of text edits to apply. - * Text edits must be non-overlapping and preferably in reverse-sorted order. - */ -export type RangeCodeFormatProvider = {| - formatCode: ( - editor: atom$TextEditor, - range: atom$Range, - ) => Promise>, - priority: number, - grammarScopes: Array, -|}; - -/** - * Formats the range specified, but returns the entire file (along with the new cursor position). - * Useful for less-flexible providers like clang-format. - */ -export type FileCodeFormatProvider = {| - formatEntireFile: ( - editor: atom$TextEditor, - range: atom$Range, - ) => Promise<{ - newCursor?: number, - formatted: string, - }>, - priority: number, - grammarScopes: Array, -|}; - -/** - * Formats around the given position, and returns a list of text edits to - * apply, similar to `formatCode`. The provider determines the exact - * range to format based on what's at that position. - * - * This will automatically triggered after every typing event. - */ -export type OnTypeCodeFormatProvider = {| - formatAtPosition: ( - editor: atom$TextEditor, - position: atom$Point, - triggerCharacter: string, - ) => Promise>, - priority: number, - grammarScopes: Array, -|}; - -/** - * Formats files after save events. - */ -export type OnSaveCodeFormatProvider = {| - formatOnSave: (editor: atom$TextEditor) => Promise>, - priority: number, - grammarScopes: Array, -|}; - -export type CodeFormatProvider = - | RangeCodeFormatProvider - | FileCodeFormatProvider - | OnTypeCodeFormatProvider - | OnSaveCodeFormatProvider; +'use strict'; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-format/spec/CodeFormatManager-spec.js b/modules/atom-ide-ui/pkg/atom-ide-code-format/spec/CodeFormatManager-spec.js deleted file mode 100644 index c1388555..00000000 --- a/modules/atom-ide-ui/pkg/atom-ide-code-format/spec/CodeFormatManager-spec.js +++ /dev/null @@ -1,185 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import {Range} from 'atom'; -import semver from 'semver'; -import temp from 'temp'; -import * as config from '../lib/config'; -import CodeFormatManager from '../lib/CodeFormatManager'; - -describe('CodeFormatManager', () => { - let textEditor; - beforeEach(() => { - waitsForPromise(async () => { - temp.track(); - const file = temp.openSync(); - textEditor = await atom.workspace.open(file.path); - }); - }); - - it('formats an editor on request', () => { - waitsForPromise(async () => { - const manager = new CodeFormatManager(); - manager.addRangeProvider({ - grammarScopes: ['text.plain.null-grammar'], - priority: 1, - formatCode: () => - Promise.resolve([ - { - oldRange: new Range([0, 0], [0, 3]), - oldText: 'abc', - newText: 'def', - }, - ]), - }); - - textEditor.setText('abc'); - atom.commands.dispatch( - atom.views.getView(textEditor), - 'code-format:format-code', - ); - waitsFor(() => textEditor.getText() === 'def'); - }); - }); - - it('format an editor using formatEntireFile', () => { - waitsForPromise(async () => { - const manager = new CodeFormatManager(); - manager.addFileProvider({ - grammarScopes: ['text.plain.null-grammar'], - priority: 1, - formatEntireFile: () => Promise.resolve({formatted: 'ghi'}), - }); - - textEditor.setText('abc'); - atom.commands.dispatch( - atom.views.getView(textEditor), - 'code-format:format-code', - ); - waitsFor(() => textEditor.getText() === 'ghi'); - }); - }); - - it('formats an editor on type', () => { - waitsForPromise(async () => { - spyOn(config, 'getFormatOnType').andReturn(true); - const manager = new CodeFormatManager(); - const provider = { - grammarScopes: ['text.plain.null-grammar'], - priority: 1, - formatAtPosition: () => - Promise.resolve([ - { - oldRange: new Range([0, 0], [0, 3]), - oldText: 'abc', - newText: 'def', - }, - ]), - }; - const spy = spyOn(provider, 'formatAtPosition').andCallThrough(); - manager.addOnTypeProvider(provider); - - textEditor.setText('a'); - textEditor.setCursorBufferPosition([0, 1]); - textEditor.insertText('b'); - textEditor.insertText('c'); - - waitsFor(() => textEditor.getText() === 'def'); - runs(() => { - // Debouncing should ensure only one format call. - expect(spy.callCount).toBe(1); - }); - }); - }); - - it('formats an editor on save', () => { - waitsForPromise(async () => { - spyOn(config, 'getFormatOnSave').andReturn(true); - const manager = new CodeFormatManager(); - manager.addOnSaveProvider({ - grammarScopes: ['text.plain.null-grammar'], - priority: 1, - formatOnSave: () => - Promise.resolve([ - { - oldRange: new Range([0, 0], [0, 3]), - oldText: 'abc', - newText: 'def', - }, - ]), - }); - - textEditor.setText('abc'); - textEditor.save(); - waitsFor(() => textEditor.getText() === 'def'); - }); - }); - - // TODO(19829039): remove check - if (semver.gte(atom.getVersion(), '1.19.0-beta0')) { - it('formats an editor on save in 1.19', () => { - waitsForPromise(async () => { - spyOn(config, 'getFormatOnSave').andReturn(true); - const manager = new CodeFormatManager(); - manager.addOnSaveProvider({ - grammarScopes: ['text.plain.null-grammar'], - priority: 1, - formatOnSave: () => - Promise.resolve([ - { - oldRange: new Range([0, 0], [0, 3]), - oldText: 'abc', - newText: 'def', - }, - ]), - }); - - textEditor.setText('abc'); - await textEditor.save(); - expect(textEditor.getText()).toBe('def'); - }); - }); - } - - it('should still save on timeout', () => { - waitsForPromise(async () => { - jasmine.Clock.useMock(); - spyOn(config, 'getFormatOnSave').andReturn(true); - const manager = new CodeFormatManager(); - manager.addRangeProvider({ - grammarScopes: ['text.plain.null-grammar'], - priority: 1, - formatCode: () => new Promise(() => {}), - }); - - const spy = spyOn(textEditor.getBuffer(), 'save').andCallThrough(); - textEditor.save(); - const savePromise = Promise.resolve(textEditor.save()); - - // The first save should be pushed through after the 2nd. - waitsFor(() => spy.callCount === 1); - - runs(() => { - jasmine.Clock.tick(3000); - }); - - // Hitting the timeout will force the 2nd save through. - waitsFor(() => spy.callCount === 2); - - // The real save should still go through. - waitsForPromise(() => savePromise); - - // Sanity check. - runs(() => expect(spy.callCount).toBe(2)); - }); - }); -}); diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/CodeHighlightManager.js b/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/CodeHighlightManager.js index 4321d9c4..93a98848 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/CodeHighlightManager.js +++ b/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/CodeHighlightManager.js @@ -1,129 +1,137 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {CodeHighlightProvider} from './types'; - -import {getLogger} from 'log4js'; -import {Observable} from 'rxjs'; -import {observableFromSubscribeFunction} from 'nuclide-commons/event'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import ProviderRegistry from 'nuclide-commons-atom/ProviderRegistry'; -import {observeActiveEditorsDebounced} from 'nuclide-commons-atom/debounced'; - -const HIGHLIGHT_DELAY_MS = 250; - -export default class CodeHighlightManager { - _subscriptions: UniversalDisposable; - _providers: ProviderRegistry; - _markers: Array; +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + +var _log4js; + +function _load_log4js() { + return _log4js = require('log4js'); +} + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _event; + +function _load_event() { + return _event = require('nuclide-commons/event'); +} + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _ProviderRegistry; + +function _load_ProviderRegistry() { + return _ProviderRegistry = _interopRequireDefault(require('nuclide-commons-atom/ProviderRegistry')); +} + +var _debounced; + +function _load_debounced() { + return _debounced = require('nuclide-commons-atom/debounced'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const HIGHLIGHT_DELAY_MS = 250; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +class CodeHighlightManager { constructor() { - this._providers = new ProviderRegistry(); + this._providers = new (_ProviderRegistry || _load_ProviderRegistry()).default(); this._markers = []; - this._subscriptions = new UniversalDisposable(this._highlightEditors()); + this._subscriptions = new (_UniversalDisposable || _load_UniversalDisposable()).default(this._highlightEditors()); } - _highlightEditors(): rxjs$Subscription { - return observeActiveEditorsDebounced(0) - .switchMap(editor => { - if (editor == null) { - return Observable.empty(); - } - const changeCursorEvents = observableFromSubscribeFunction( - editor.onDidChangeCursorPosition.bind(editor), - ) - .map(event => event.newBufferPosition) - .filter( - // If we're moving around inside highlighted ranges, that's fine. - position => !this._isPositionInHighlightedRanges(editor, position), - ); - - const changeEvents = observableFromSubscribeFunction( - editor.onDidChange.bind(editor), - ) - // Ensure we start highlighting immediately. - .startWith(null) - .map(() => editor.getCursorBufferPosition()); - - const destroyEvents = observableFromSubscribeFunction( - editor.onDidDestroy.bind(editor), - ); - - return ( - Observable.merge(changeCursorEvents, changeEvents) - // Destroy old markers immediately - never show stale results. - .do(() => this._destroyMarkers()) - .switchMap(position => { - return Observable.timer( - HIGHLIGHT_DELAY_MS, - ).switchMap(async () => { - return { - editor, - ranges: await this._getHighlightedRanges(editor, position), - }; - }); - }) - .takeUntil(destroyEvents) - ); - }) - .subscribe(({editor, ranges}) => { - if (ranges != null) { - this._highlightRanges(editor, ranges); - } - }); + _highlightEditors() { + var _this = this; + + return (0, (_debounced || _load_debounced()).observeActiveEditorsDebounced)(0).switchMap(editor => { + if (editor == null) { + return _rxjsBundlesRxMinJs.Observable.empty(); + } + const changeCursorEvents = (0, (_event || _load_event()).observableFromSubscribeFunction)(editor.onDidChangeCursorPosition.bind(editor)).map(event => event.newBufferPosition).filter( + // If we're moving around inside highlighted ranges, that's fine. + position => !this._isPositionInHighlightedRanges(editor, position)); + + const changeEvents = (0, (_event || _load_event()).observableFromSubscribeFunction)(editor.onDidChange.bind(editor)) + // Ensure we start highlighting immediately. + .startWith(null).map(() => editor.getCursorBufferPosition()); + + const destroyEvents = (0, (_event || _load_event()).observableFromSubscribeFunction)(editor.onDidDestroy.bind(editor)); + + return _rxjsBundlesRxMinJs.Observable.merge(changeCursorEvents, changeEvents) + // Destroy old markers immediately - never show stale results. + .do(() => this._destroyMarkers()).switchMap(position => { + return _rxjsBundlesRxMinJs.Observable.timer(HIGHLIGHT_DELAY_MS).switchMap((0, _asyncToGenerator.default)(function* () { + return { + editor, + ranges: yield _this._getHighlightedRanges(editor, position) + }; + })); + }).takeUntil(destroyEvents); + }).subscribe(({ editor, ranges }) => { + if (ranges != null) { + this._highlightRanges(editor, ranges); + } + }); } - async _getHighlightedRanges( - editor: atom$TextEditor, - position: atom$Point, - ): Promise> { - const provider = this._providers.getProviderForEditor(editor); - if (!provider) { - return null; - } - - try { - return await provider.highlight(editor, position); - } catch (e) { - getLogger('code-highlight').error('Error getting code highlights', e); - return null; - } + _getHighlightedRanges(editor, position) { + var _this2 = this; + + return (0, _asyncToGenerator.default)(function* () { + const provider = _this2._providers.getProviderForEditor(editor); + if (!provider) { + return null; + } + + try { + return yield provider.highlight(editor, position); + } catch (e) { + (0, (_log4js || _load_log4js()).getLogger)('code-highlight').error('Error getting code highlights', e); + return null; + } + })(); } - _highlightRanges(editor: atom$TextEditor, ranges: Array): void { + _highlightRanges(editor, ranges) { this._destroyMarkers(); this._markers = ranges.map(range => editor.markBufferRange(range, {})); this._markers.forEach(marker => { editor.decorateMarker(marker, { type: 'highlight', - class: 'code-highlight-marker', + class: 'code-highlight-marker' }); }); } - _isPositionInHighlightedRanges( - editor: atom$TextEditor, - position: atom$Point, - ): boolean { - return this._markers - .map(marker => marker.getBufferRange()) - .some(range => range.containsPoint(position)); + _isPositionInHighlightedRanges(editor, position) { + return this._markers.map(marker => marker.getBufferRange()).some(range => range.containsPoint(position)); } - _destroyMarkers(): void { + _destroyMarkers() { this._markers.splice(0).forEach(marker => marker.destroy()); } - addProvider(provider: CodeHighlightProvider): IDisposable { + addProvider(provider) { return this._providers.addProvider(provider); } @@ -132,3 +140,4 @@ export default class CodeHighlightManager { this._destroyMarkers(); } } +exports.default = CodeHighlightManager; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/main.js b/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/main.js index 6bdcf457..1c2b2bb3 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/main.js +++ b/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/main.js @@ -1,34 +1,42 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {CodeHighlightProvider} from './types'; - -import createPackage from 'nuclide-commons-atom/createPackage'; -import CodeHighlightManager from './CodeHighlightManager'; +'use strict'; + +var _createPackage; + +function _load_createPackage() { + return _createPackage = _interopRequireDefault(require('nuclide-commons-atom/createPackage')); +} + +var _CodeHighlightManager; + +function _load_CodeHighlightManager() { + return _CodeHighlightManager = _interopRequireDefault(require('./CodeHighlightManager')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class Activation { - _codeHighlightManager: CodeHighlightManager; constructor() { - this._codeHighlightManager = new CodeHighlightManager(); + this._codeHighlightManager = new (_CodeHighlightManager || _load_CodeHighlightManager()).default(); } dispose() { this._codeHighlightManager.dispose(); } - addProvider(provider: CodeHighlightProvider): IDisposable { + addProvider(provider) { return this._codeHighlightManager.addProvider(provider); } -} +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ -createPackage(module.exports, Activation); +(0, (_createPackage || _load_createPackage()).default)(module.exports, Activation); \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/types.js b/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/types.js index 167d70c1..9a390c31 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/types.js +++ b/modules/atom-ide-ui/pkg/atom-ide-code-highlight/lib/types.js @@ -1,20 +1 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -export type CodeHighlightProvider = { - highlight( - editor: atom$TextEditor, - bufferPosition: atom$Point, - ): Promise>, - priority: number, - grammarScopes: Array, -}; +"use strict"; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-code-highlight/spec/CodeHighlightManager-spec.js b/modules/atom-ide-ui/pkg/atom-ide-code-highlight/spec/CodeHighlightManager-spec.js deleted file mode 100644 index 869eecec..00000000 --- a/modules/atom-ide-ui/pkg/atom-ide-code-highlight/spec/CodeHighlightManager-spec.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import {Point, Range} from 'atom'; -import CodeHighlightManager from '../lib/CodeHighlightManager'; - -describe('CodeHighlightManager', () => { - let manager; - let provider; - let editor; - beforeEach(() => { - jasmine.Clock.useMock(); - waitsForPromise(async () => { - manager = new CodeHighlightManager(); - provider = { - priority: 1, - grammarScopes: ['text.plain.null-grammar'], - highlight: (_editor, position) => Promise.resolve([]), - }; - manager.addProvider(provider); - editor = await atom.workspace.open('test.txt'); - editor.setText('abc\ndef\nghi'); - }); - }); - - it('updates highlights on cursor move', () => { - const ranges = [new Range([0, 0], [0, 3])]; - const spy = spyOn(provider, 'highlight').andReturn(ranges); - - // Just opening the editor should trigger highlights. - runs(() => { - jasmine.Clock.tick(300); - expect(spy).toHaveBeenCalled(); - }); - - // (once the promise resolves). - waitsFor(() => manager._markers.length === 1); - - runs(() => { - ranges[0] = new Range([1, 0], [1, 3]); - editor.setCursorBufferPosition(new Point(1, 0)); - // Old markers should be cleared immediately. - expect(manager._markers.length).toBe(0); - jasmine.Clock.tick(300); // trigger debounce - expect(spy.callCount).toBe(2); - }); - - waitsFor(() => manager._markers.length === 1); - - // If we're still inside the range, don't fire a new event. - runs(() => { - editor.setCursorBufferPosition(new Point(1, 1)); - expect(spy.callCount).toBe(2); - }); - - waitsForPromise(() => atom.workspace.open('test2.txt')); - - runs(() => { - // Opening a new editor should clear out old markers. - jasmine.Clock.tick(1); - expect(manager._markers.length).toBe(0); - }); - }); - - it('updates highlights on change', () => { - const ranges = [new Range([0, 0], [0, 1])]; - const spy = spyOn(provider, 'highlight').andReturn(ranges); - - runs(() => { - editor.insertText('a'); - jasmine.Clock.tick(300); // trigger debounce - expect(spy).toHaveBeenCalled(); - }); - - // Wait for the promise to resolve. - waitsFor(() => manager._markers.length === 1); - - runs(() => { - editor.insertText('b'); - // Clear out immediately. - expect(manager._markers.length).toBe(0); - }); - }); -}); diff --git a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/DatatipComponent.js b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/DatatipComponent.js index 4c225936..81d7a3b8 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/DatatipComponent.js +++ b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/DatatipComponent.js @@ -1,83 +1,99 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {Datatip} from './types'; - -import * as React from 'react'; - -import {maybeToString} from 'nuclide-commons/string'; -import MarkedStringDatatip from './MarkedStringDatatip'; - -export const DATATIP_ACTIONS = Object.freeze({ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DatatipComponent = exports.DATATIP_ACTIONS = undefined; + +var _react = _interopRequireWildcard(require('react')); + +var _string; + +function _load_string() { + return _string = require('nuclide-commons/string'); +} + +var _MarkedStringDatatip; + +function _load_MarkedStringDatatip() { + return _MarkedStringDatatip = _interopRequireDefault(require('./MarkedStringDatatip')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const DATATIP_ACTIONS = exports.DATATIP_ACTIONS = Object.freeze({ PIN: 'PIN', - CLOSE: 'CLOSE', + CLOSE: 'CLOSE' }); const IconsForAction = { [DATATIP_ACTIONS.PIN]: 'pin', - [DATATIP_ACTIONS.CLOSE]: 'x', + [DATATIP_ACTIONS.CLOSE]: 'x' }; -type DatatipComponentProps = { - action: string, - actionTitle: string, - className?: string, - datatip: Datatip, - onActionClick: Function, -}; +class DatatipComponent extends _react.Component { + constructor(...args) { + var _temp; -export class DatatipComponent extends React.Component { - handleActionClick = (event: SyntheticEvent<>) => { - this.props.onActionClick(); - }; + return _temp = super(...args), this.handleActionClick = event => { + this.props.onActionClick(); + }, _temp; + } - render(): React.Node { - const { + render() { + const _props = this.props, + { className, action, actionTitle, datatip, - onActionClick, - ...props - } = this.props; + onActionClick + } = _props, + props = _objectWithoutProperties(_props, ['className', 'action', 'actionTitle', 'datatip', 'onActionClick']); let content; if (datatip.component != null) { - content = ; + content = _react.createElement(datatip.component, null); } else if (datatip.markedStrings != null) { - content = ; + content = _react.createElement((_MarkedStringDatatip || _load_MarkedStringDatatip()).default, { markedStrings: datatip.markedStrings }); } let actionButton = null; if (action != null && IconsForAction[action] != null) { const actionIcon = IconsForAction[action]; - actionButton = ( -
- ); + actionButton = _react.createElement('div', { + className: `datatip-pin-button icon-${actionIcon}`, + onClick: this.handleActionClick, + title: actionTitle + }); } - return ( -
-
- {content} -
- {actionButton} -
+ return _react.createElement( + 'div', + Object.assign({ + className: `${(0, (_string || _load_string()).maybeToString)(className)} datatip-container` + }, props), + _react.createElement( + 'div', + { className: 'datatip-content' }, + content + ), + actionButton ); } } +exports.DatatipComponent = DatatipComponent; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/DatatipManager.js b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/DatatipManager.js index d5568318..f76e9863 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/DatatipManager.js +++ b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/DatatipManager.js @@ -1,3 +1,152 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DatatipManager = undefined; + +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + +let getTopDatatipAndProvider = (() => { + var _ref5 = (0, _asyncToGenerator.default)(function* (providers, editor, position, invoke) { + const filteredDatatipProviders = Array.from(providers.getAllProvidersForEditor(editor)); + if (filteredDatatipProviders.length === 0) { + return null; + } + + const datatipPromises = filteredDatatipProviders.map((() => { + var _ref6 = (0, _asyncToGenerator.default)(function* (provider) { + const name = getProviderName(provider); + const timingTracker = new (_analytics || _load_analytics()).default.TimingTracker(name + '.datatip'); + try { + const datatip = yield invoke(provider); + if (!datatip) { + return null; + } + + timingTracker.onSuccess(); + + const result = { + datatip, + provider + }; + return result; + } catch (e) { + timingTracker.onError(e); + (0, (_log4js || _load_log4js()).getLogger)('datatip').error(`Error getting datatip from provider ${name}`, e); + return null; + } + }); + + return function (_x5) { + return _ref6.apply(this, arguments); + }; + })()); + + return (0, (_promise || _load_promise()).asyncFind)(datatipPromises, function (p) { + return p; + }); + }); + + return function getTopDatatipAndProvider(_x, _x2, _x3, _x4) { + return _ref5.apply(this, arguments); + }; +})(); + +var _react = _interopRequireWildcard(require('react')); + +var _reactDom = _interopRequireDefault(require('react-dom')); + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _analytics; + +function _load_analytics() { + return _analytics = _interopRequireDefault(require('nuclide-commons-atom/analytics')); +} + +var _debounce; + +function _load_debounce() { + return _debounce = _interopRequireDefault(require('nuclide-commons/debounce')); +} + +var _featureConfig; + +function _load_featureConfig() { + return _featureConfig = _interopRequireDefault(require('nuclide-commons-atom/feature-config')); +} + +var _idx; + +function _load_idx() { + return _idx = _interopRequireDefault(require('idx')); +} + +var _performanceNow; + +function _load_performanceNow() { + return _performanceNow = _interopRequireDefault(require('nuclide-commons/performanceNow')); +} + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _collection; + +function _load_collection() { + return _collection = require('nuclide-commons/collection'); +} + +var _promise; + +function _load_promise() { + return _promise = require('nuclide-commons/promise'); +} + +var _log4js; + +function _load_log4js() { + return _log4js = require('log4js'); +} + +var _ProviderRegistry; + +function _load_ProviderRegistry() { + return _ProviderRegistry = _interopRequireDefault(require('nuclide-commons-atom/ProviderRegistry')); +} + +var _textEditor; + +function _load_textEditor() { + return _textEditor = require('nuclide-commons-atom/text-editor'); +} + +var _getModifierKeys; + +function _load_getModifierKeys() { + return _getModifierKeys = require('./getModifierKeys'); +} + +var _DatatipComponent; + +function _load_DatatipComponent() { + return _DatatipComponent = require('./DatatipComponent'); +} + +var _PinnedDatatip; + +function _load_PinnedDatatip() { + return _PinnedDatatip = require('./PinnedDatatip'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,66 +155,25 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ /* global performance */ -import type { - AnyDatatipProvider, - Datatip, - DatatipProvider, - ModifierDatatipProvider, - ModifierKey, -} from './types'; - -import * as React from 'react'; -import ReactDOM from 'react-dom'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import analytics from 'nuclide-commons-atom/analytics'; -import debounce from 'nuclide-commons/debounce'; -import featureConfig from 'nuclide-commons-atom/feature-config'; -import idx from 'idx'; -import performanceNow from 'nuclide-commons/performanceNow'; -import {Observable} from 'rxjs'; -import {arrayCompact} from 'nuclide-commons/collection'; -import {asyncFind} from 'nuclide-commons/promise'; -import {getLogger} from 'log4js'; -import ProviderRegistry from 'nuclide-commons-atom/ProviderRegistry'; -import {observeTextEditors} from 'nuclide-commons-atom/text-editor'; -import { - getModifierKeysFromMouseEvent, - getModifierKeyFromKeyboardEvent, -} from './getModifierKeys'; - -import {DatatipComponent, DATATIP_ACTIONS} from './DatatipComponent'; -import {PinnedDatatip} from './PinnedDatatip'; - const CUMULATIVE_WHEELX_THRESHOLD = 20; const DEFAULT_DATATIP_DEBOUNCE_DELAY = 1000; const DEFAULT_DATATIP_INTERACTED_DEBOUNCE_DELAY = 1000; -type PinClickHandler = (editor: atom$TextEditor, datatip: Datatip) => void; - -type DataTipResult = { - datatip: Datatip, - provider: AnyDatatipProvider, -}; - -function getProviderName(provider: AnyDatatipProvider): string { +function getProviderName(provider) { if (provider.providerName == null) { - getLogger('datatip').error('Datatip provider has no name', provider); + (0, (_log4js || _load_log4js()).getLogger)('datatip').error('Datatip provider has no name', provider); return 'unknown'; } return provider.providerName; } -function getBufferPosition( - editor: TextEditor, - editorView: atom$TextEditorElement, - event: ?MouseEvent, -): null | atom$Point { +function getBufferPosition(editor, editorView, event) { if (!event) { return null; } @@ -77,127 +185,64 @@ function getBufferPosition( const screenPosition = text.screenPositionForMouseEvent(event); const pixelPosition = text.pixelPositionForMouseEvent(event); - const pixelPositionFromScreenPosition = text.pixelPositionForScreenPosition( - screenPosition, - ); + const pixelPositionFromScreenPosition = text.pixelPositionForScreenPosition(screenPosition); // Distance (in pixels) between screenPosition and the cursor. - const horizontalDistance = - pixelPosition.left - pixelPositionFromScreenPosition.left; + const horizontalDistance = pixelPosition.left - pixelPositionFromScreenPosition.left; // `screenPositionForMouseEvent.column` cannot exceed the current line length. // This is essentially a heuristic for "mouse cursor is to the left or right // of text content". - if ( - pixelPosition.left < 0 || - horizontalDistance > editor.getDefaultCharWidth() - ) { + if (pixelPosition.left < 0 || horizontalDistance > editor.getDefaultCharWidth()) { return null; } return editor.bufferPositionForScreenPosition(screenPosition); } -async function getTopDatatipAndProvider( - providers: ProviderRegistry, - editor: atom$TextEditor, - position: atom$Point, - invoke: TProvider => Promise, -): Promise { - const filteredDatatipProviders = Array.from( - providers.getAllProvidersForEditor(editor), - ); - if (filteredDatatipProviders.length === 0) { - return null; - } - - const datatipPromises = filteredDatatipProviders.map( - async (provider: TProvider): Promise => { - const name = getProviderName(provider); - const timingTracker = new analytics.TimingTracker(name + '.datatip'); - try { - const datatip: ?Datatip = await invoke(provider); - if (!datatip) { - return null; - } - - timingTracker.onSuccess(); - - const result: DataTipResult = { - datatip, - provider, - }; - return result; - } catch (e) { - timingTracker.onError(e); - getLogger('datatip').error( - `Error getting datatip from provider ${name}`, - e, - ); - return null; - } - }, - ); - - return asyncFind(datatipPromises, p => p); -} - -type PinnableDatatipProps = { - datatip: Datatip, - editor: atom$TextEditor, - onPinClick: PinClickHandler, -}; - function PinnableDatatip({ datatip, editor, - onPinClick, -}: PinnableDatatipProps): React.Element { + onPinClick +}) { let action; let actionTitle; // Datatips are pinnable by default, unless explicitly specified // otherwise. if (datatip.pinnable !== false) { - action = DATATIP_ACTIONS.PIN; + action = (_DatatipComponent || _load_DatatipComponent()).DATATIP_ACTIONS.PIN; actionTitle = 'Pin this Datatip'; } return ( // $FlowFixMe(>=0.53.0) Flow suppress - onPinClick(editor, datatip)} - /> + _react.createElement((_DatatipComponent || _load_DatatipComponent()).DatatipComponent, { + action: action, + actionTitle: actionTitle, + datatip: datatip, + onActionClick: () => onPinClick(editor, datatip) + }) ); } -function mountDatatipWithMarker( - editor, - element, - { - range, - renderedProviders, - }: { - range: atom$Range, - renderedProviders: React.Element, - }, -): atom$Marker { +function mountDatatipWithMarker(editor, element, { + range, + renderedProviders +}) { // Transform the matched element range to the hint range. - const marker: atom$Marker = editor.markBufferRange(range, { - invalidate: 'never', + const marker = editor.markBufferRange(range, { + invalidate: 'never' }); element.style.display = 'block'; - ReactDOM.render(renderedProviders, element); + _reactDom.default.render(renderedProviders, element); editor.decorateMarker(marker, { type: 'overlay', position: 'tail', - item: element, + item: element }); editor.decorateMarker(marker, { type: 'highlight', - class: 'datatip-highlight-region', + class: 'datatip-highlight-region' }); return marker; @@ -206,11 +251,11 @@ function mountDatatipWithMarker( const DatatipState = Object.freeze({ HIDDEN: 'HIDDEN', FETCHING: 'FETCHING', - VISIBLE: 'VISIBLE', + VISIBLE: 'VISIBLE' }); -type State = $Keys; -function ensurePositiveNumber(value: any, defaultValue: number): number { + +function ensurePositiveNumber(value, defaultValue) { if (typeof value !== 'number' || value < 0) { return defaultValue; } @@ -218,39 +263,14 @@ function ensurePositiveNumber(value: any, defaultValue: number): number { } class DatatipManagerForEditor { - _blacklistedPosition: ?atom$Point; - _datatipElement: HTMLElement; - _datatipProviders: ProviderRegistry; - _modifierDatatipProviders: ProviderRegistry; - _datatipState: State; - _editor: atom$TextEditor; - _editorView: atom$TextEditorElement; - _insideDatatip: boolean; - _lastHiddenTime: number; - _lastFetchedFromCursorPosition: boolean; - _lastMoveEvent: ?MouseEvent; - _lastPosition: ?atom$Point; - _lastDatatipAndProviderPromise: ?Promise; - _heldKeys: Set; - _marker: ?atom$Marker; - _pinnedDatatips: Set; - _range: ?atom$Range; - _shouldDropNextMouseMoveAfterFocus: boolean; - _startFetchingDebounce: () => void; - _hideIfOutsideDebounce: () => void; - _subscriptions: UniversalDisposable; - _interactedWith: boolean; - _cumulativeWheelX: number; - - constructor( - editor: atom$TextEditor, - datatipProviders: ProviderRegistry, - modifierDatatipProviders: ProviderRegistry, - ) { + + constructor(editor, datatipProviders, modifierDatatipProviders) { + _initialiseProps.call(this); + this._editor = editor; this._editorView = atom.views.getView(editor); this._pinnedDatatips = new Set(); - this._subscriptions = new UniversalDisposable(); + this._subscriptions = new (_UniversalDisposable || _load_UniversalDisposable()).default(); this._datatipProviders = datatipProviders; this._modifierDatatipProviders = modifierDatatipProviders; this._datatipElement = document.createElement('div'); @@ -263,170 +283,117 @@ class DatatipManagerForEditor { this._lastFetchedFromCursorPosition = false; this._shouldDropNextMouseMoveAfterFocus = false; - this._subscriptions.add( - featureConfig.observe('atom-ide-datatip.datatipDebounceDelay', () => - this._setStartFetchingDebounce(), - ), - featureConfig.observe( - 'atom-ide-datatip.datatipInteractedWithDebounceDelay', - () => this._setHideIfOutsideDebounce(), - ), - Observable.fromEvent(this._editorView, 'focus').subscribe(e => { - this._shouldDropNextMouseMoveAfterFocus = true; - if (!this._insideDatatip) { - this._setState(DatatipState.HIDDEN); - } - }), - Observable.fromEvent(this._editorView, 'blur').subscribe(e => { - if (!this._insideDatatip) { - this._setState(DatatipState.HIDDEN); - } - }), - Observable.fromEvent(this._editorView, 'mousemove').subscribe(e => { - this._lastFetchedFromCursorPosition = false; - if (this._shouldDropNextMouseMoveAfterFocus) { - this._shouldDropNextMouseMoveAfterFocus = false; - return; - } + this._subscriptions.add((_featureConfig || _load_featureConfig()).default.observe('atom-ide-datatip.datatipDebounceDelay', () => this._setStartFetchingDebounce()), (_featureConfig || _load_featureConfig()).default.observe('atom-ide-datatip.datatipInteractedWithDebounceDelay', () => this._setHideIfOutsideDebounce()), _rxjsBundlesRxMinJs.Observable.fromEvent(this._editorView, 'focus').subscribe(e => { + this._shouldDropNextMouseMoveAfterFocus = true; + if (!this._insideDatatip) { + this._setState(DatatipState.HIDDEN); + } + }), _rxjsBundlesRxMinJs.Observable.fromEvent(this._editorView, 'blur').subscribe(e => { + if (!this._insideDatatip) { + this._setState(DatatipState.HIDDEN); + } + }), _rxjsBundlesRxMinJs.Observable.fromEvent(this._editorView, 'mousemove').subscribe(e => { + this._lastFetchedFromCursorPosition = false; + if (this._shouldDropNextMouseMoveAfterFocus) { + this._shouldDropNextMouseMoveAfterFocus = false; + return; + } - this._lastMoveEvent = e; - this._heldKeys = getModifierKeysFromMouseEvent(e); - if (this._datatipState === DatatipState.HIDDEN) { - this._startFetchingDebounce(); - } else { - this._hideIfOutside(); - } - }), - Observable.fromEvent(this._editorView, 'mouseleave').subscribe(() => { - this._lastMoveEvent = null; + this._lastMoveEvent = e; + this._heldKeys = (0, (_getModifierKeys || _load_getModifierKeys()).getModifierKeysFromMouseEvent)(e); + if (this._datatipState === DatatipState.HIDDEN) { + this._startFetchingDebounce(); + } else { this._hideIfOutside(); - }), - Observable.fromEvent(this._editorView, 'mousedown').subscribe(e => { - let node = e.target; - while (node !== null) { - if (node === this._datatipElement) { - return; - } - node = node.parentNode; + } + }), _rxjsBundlesRxMinJs.Observable.fromEvent(this._editorView, 'mouseleave').subscribe(() => { + this._lastMoveEvent = null; + this._hideIfOutside(); + }), _rxjsBundlesRxMinJs.Observable.fromEvent(this._editorView, 'mousedown').subscribe(e => { + let node = e.target; + while (node !== null) { + if (node === this._datatipElement) { + return; } + node = node.parentNode; + } - this._hideOrCancel(); - }), - Observable.fromEvent(this._editorView, 'keydown').subscribe(e => { - const modifierKey = getModifierKeyFromKeyboardEvent(e); - if (modifierKey) { - this._heldKeys.add(modifierKey); - if (this._datatipState !== DatatipState.HIDDEN) { - this._fetchInResponseToKeyPress(); - } - } else { - this._hideOrCancel(); - } - }), - Observable.fromEvent(this._editorView, 'keyup').subscribe(e => { - const modifierKey = getModifierKeyFromKeyboardEvent(e); - if (modifierKey) { - this._heldKeys.delete(modifierKey); - if (this._datatipState !== DatatipState.HIDDEN) { - this._fetchInResponseToKeyPress(); - } - } - }), - Observable.fromEvent(this._datatipElement, 'wheel').subscribe(e => { - this._cumulativeWheelX += Math.abs(e.deltaX); - if (this._cumulativeWheelX > CUMULATIVE_WHEELX_THRESHOLD) { - this._interactedWith = true; + this._hideOrCancel(); + }), _rxjsBundlesRxMinJs.Observable.fromEvent(this._editorView, 'keydown').subscribe(e => { + const modifierKey = (0, (_getModifierKeys || _load_getModifierKeys()).getModifierKeyFromKeyboardEvent)(e); + if (modifierKey) { + this._heldKeys.add(modifierKey); + if (this._datatipState !== DatatipState.HIDDEN) { + this._fetchInResponseToKeyPress(); } - if (this._interactedWith) { - e.stopPropagation(); + } else { + this._hideOrCancel(); + } + }), _rxjsBundlesRxMinJs.Observable.fromEvent(this._editorView, 'keyup').subscribe(e => { + const modifierKey = (0, (_getModifierKeys || _load_getModifierKeys()).getModifierKeyFromKeyboardEvent)(e); + if (modifierKey) { + this._heldKeys.delete(modifierKey); + if (this._datatipState !== DatatipState.HIDDEN) { + this._fetchInResponseToKeyPress(); } - }), - Observable.fromEvent(this._datatipElement, 'mousedown').subscribe(() => { + } + }), _rxjsBundlesRxMinJs.Observable.fromEvent(this._datatipElement, 'wheel').subscribe(e => { + this._cumulativeWheelX += Math.abs(e.deltaX); + if (this._cumulativeWheelX > CUMULATIVE_WHEELX_THRESHOLD) { this._interactedWith = true; - }), - Observable.fromEvent(this._datatipElement, 'mouseenter').subscribe(() => { - this._insideDatatip = true; - this._hideIfOutside(); - }), - Observable.fromEvent(this._datatipElement, 'mouseleave').subscribe(() => { - this._insideDatatip = false; - this._hideIfOutside(); - }), - this._editorView.onDidChangeScrollTop(() => { - this._lastMoveEvent = null; - if (this._datatipState === DatatipState.VISIBLE) { - this._setState(DatatipState.HIDDEN); - } - }), - this._editor.getBuffer().onDidChangeText(() => { - if (this._datatipState === DatatipState.VISIBLE) { - this._setState(DatatipState.HIDDEN); - } - }), - atom.commands.add( - 'atom-text-editor', - 'datatip:toggle', - this._toggleDatatip, - ), - atom.commands.add( - 'atom-text-editor', - 'datatip:copy-to-clipboard', - this._copyDatatipToClipboard, - ), - ); + } + if (this._interactedWith) { + e.stopPropagation(); + } + }), _rxjsBundlesRxMinJs.Observable.fromEvent(this._datatipElement, 'mousedown').subscribe(() => { + this._interactedWith = true; + }), _rxjsBundlesRxMinJs.Observable.fromEvent(this._datatipElement, 'mouseenter').subscribe(() => { + this._insideDatatip = true; + this._hideIfOutside(); + }), _rxjsBundlesRxMinJs.Observable.fromEvent(this._datatipElement, 'mouseleave').subscribe(() => { + this._insideDatatip = false; + this._hideIfOutside(); + }), this._editorView.onDidChangeScrollTop(() => { + this._lastMoveEvent = null; + if (this._datatipState === DatatipState.VISIBLE) { + this._setState(DatatipState.HIDDEN); + } + }), this._editor.getBuffer().onDidChangeText(() => { + if (this._datatipState === DatatipState.VISIBLE) { + this._setState(DatatipState.HIDDEN); + } + }), atom.commands.add('atom-text-editor', 'datatip:toggle', this._toggleDatatip), atom.commands.add('atom-text-editor', 'datatip:copy-to-clipboard', this._copyDatatipToClipboard)); } _fetchInResponseToKeyPress() { if (this._lastFetchedFromCursorPosition) { this._startFetching(() => this._editor.getCursorBufferPosition()); } else { - this._startFetching(() => - getBufferPosition(this._editor, this._editorView, this._lastMoveEvent), - ); + this._startFetching(() => getBufferPosition(this._editor, this._editorView, this._lastMoveEvent)); } } - _setStartFetchingDebounce(): void { - this._startFetchingDebounce = debounce( - () => { - this._startFetching(() => - getBufferPosition( - this._editor, - this._editorView, - this._lastMoveEvent, - ), - ); - }, - ensurePositiveNumber( - (featureConfig.get('atom-ide-datatip.datatipDebounceDelay'): any), - DEFAULT_DATATIP_DEBOUNCE_DELAY, - ), - /* immediate */ false, - ); + _setStartFetchingDebounce() { + this._startFetchingDebounce = (0, (_debounce || _load_debounce()).default)(() => { + this._startFetching(() => getBufferPosition(this._editor, this._editorView, this._lastMoveEvent)); + }, ensurePositiveNumber((_featureConfig || _load_featureConfig()).default.get('atom-ide-datatip.datatipDebounceDelay'), DEFAULT_DATATIP_DEBOUNCE_DELAY), + /* immediate */false); } - _setHideIfOutsideDebounce(): void { - this._hideIfOutsideDebounce = debounce( - () => { - this._hideIfOutsideImmediate(); - }, - ensurePositiveNumber( - (featureConfig.get( - 'atom-ide-datatip.datatipInteractedWithDebounceDelay', - ): any), - DEFAULT_DATATIP_INTERACTED_DEBOUNCE_DELAY, - ), - /* immediate */ false, - ); + _setHideIfOutsideDebounce() { + this._hideIfOutsideDebounce = (0, (_debounce || _load_debounce()).default)(() => { + this._hideIfOutsideImmediate(); + }, ensurePositiveNumber((_featureConfig || _load_featureConfig()).default.get('atom-ide-datatip.datatipInteractedWithDebounceDelay'), DEFAULT_DATATIP_INTERACTED_DEBOUNCE_DELAY), + /* immediate */false); } - dispose(): void { + dispose() { this._setState(DatatipState.HIDDEN); this._subscriptions.dispose(); this._datatipElement.remove(); } - _setState(newState: State): void { + _setState(newState) { const oldState = this._datatipState; this._datatipState = newState; @@ -438,171 +405,143 @@ class DatatipManagerForEditor { } } - async _startFetching(getPosition: () => ?atom$Point): Promise { - const position = getPosition(); - if (!position) { - return; - } + _startFetching(getPosition) { + var _this = this; - const data = await this._fetchAndRender(position); - if (data == null) { - this._setState(DatatipState.HIDDEN); - return; - } - if (this._datatipState !== DatatipState.FETCHING) { - this._setState(DatatipState.HIDDEN); - } + return (0, _asyncToGenerator.default)(function* () { + const position = getPosition(); + if (!position) { + return; + } - if ( - this._blacklistedPosition && - data.range && - data.range.containsPoint(this._blacklistedPosition) - ) { - this._setState(DatatipState.HIDDEN); - return; - } + const data = yield _this._fetchAndRender(position); + if (data == null) { + _this._setState(DatatipState.HIDDEN); + return; + } + if (_this._datatipState !== DatatipState.FETCHING) { + _this._setState(DatatipState.HIDDEN); + } - const currentPosition = getPosition(); - if ( - !currentPosition || - !data.range || - !data.range.containsPoint(currentPosition) - ) { - this._setState(DatatipState.HIDDEN); - return; - } + if (_this._blacklistedPosition && data.range && data.range.containsPoint(_this._blacklistedPosition)) { + _this._setState(DatatipState.HIDDEN); + return; + } - if (this._isHoveringOverPinnedTip()) { - this._setState(DatatipState.HIDDEN); - return; - } + const currentPosition = getPosition(); + if (!currentPosition || !data.range || !data.range.containsPoint(currentPosition)) { + _this._setState(DatatipState.HIDDEN); + return; + } - this._setState(DatatipState.VISIBLE); - this._interactedWith = false; - this._cumulativeWheelX = 0; - this._range = data.range; + if (_this._isHoveringOverPinnedTip()) { + _this._setState(DatatipState.HIDDEN); + return; + } - if (this._marker) { - this._marker.destroy(); - } - this._marker = mountDatatipWithMarker( - this._editor, - this._datatipElement, - data, - ); + _this._setState(DatatipState.VISIBLE); + _this._interactedWith = false; + _this._cumulativeWheelX = 0; + _this._range = data.range; + + if (_this._marker) { + _this._marker.destroy(); + } + _this._marker = mountDatatipWithMarker(_this._editor, _this._datatipElement, data); + })(); } - async _fetch(position: atom$Point): Promise> { - this._setState(DatatipState.FETCHING); + _fetch(position) { + var _this2 = this; - let datatipAndProviderPromise: Promise; - if ( - this._lastPosition != null && - position.isEqual(this._lastPosition) && - this._lastDatatipAndProviderPromise != null - ) { - datatipAndProviderPromise = this._lastDatatipAndProviderPromise; - } else { - this._lastDatatipAndProviderPromise = getTopDatatipAndProvider( - this._datatipProviders, - this._editor, - position, - provider => provider.datatip(this._editor, position), - ); - datatipAndProviderPromise = this._lastDatatipAndProviderPromise; - this._lastPosition = position; - } + return (0, _asyncToGenerator.default)(function* () { + _this2._setState(DatatipState.FETCHING); + + let datatipAndProviderPromise; + if (_this2._lastPosition != null && position.isEqual(_this2._lastPosition) && _this2._lastDatatipAndProviderPromise != null) { + datatipAndProviderPromise = _this2._lastDatatipAndProviderPromise; + } else { + _this2._lastDatatipAndProviderPromise = getTopDatatipAndProvider(_this2._datatipProviders, _this2._editor, position, function (provider) { + return provider.datatip(_this2._editor, position); + }); + datatipAndProviderPromise = _this2._lastDatatipAndProviderPromise; + _this2._lastPosition = position; + } + + const datatipsAndProviders = (0, (_collection || _load_collection()).arrayCompact)((yield Promise.all([datatipAndProviderPromise, getTopDatatipAndProvider(_this2._modifierDatatipProviders, _this2._editor, position, function (provider) { + return provider.modifierDatatip(_this2._editor, position, _this2._heldKeys); + })]))); - const datatipsAndProviders: Array = arrayCompact( - await Promise.all([ - datatipAndProviderPromise, - getTopDatatipAndProvider( - this._modifierDatatipProviders, - this._editor, - position, - provider => - provider.modifierDatatip(this._editor, position, this._heldKeys), - ), - ]), - ); - - return datatipsAndProviders; + return datatipsAndProviders; + })(); } - async _fetchAndRender( - position: atom$Point, - ): Promise, - }> { - const datatipsAndProviders = await this._fetch(position); - if (datatipsAndProviders.length === 0) { - return null; - } + _fetchAndRender(position) { + var _this3 = this; - const range = datatipsAndProviders[0].datatip.range; - analytics.track('datatip-popup', { - scope: this._editor.getGrammar().scopeName, - providerName: getProviderName(datatipsAndProviders[0].provider), - rangeStartRow: String(range.start.row), - rangeStartColumn: String(range.start.column), - rangeEndRow: String(range.end.row), - rangeEndColumn: String(range.end.column), - }); + return (0, _asyncToGenerator.default)(function* () { + const datatipsAndProviders = yield _this3._fetch(position); + if (datatipsAndProviders.length === 0) { + return null; + } - const renderedProviders = ( -
- {datatipsAndProviders.map(({datatip, provider}) => - , - )} -
- ); - - return { - range, - renderedProviders, - }; + const range = datatipsAndProviders[0].datatip.range; + (_analytics || _load_analytics()).default.track('datatip-popup', { + scope: _this3._editor.getGrammar().scopeName, + providerName: getProviderName(datatipsAndProviders[0].provider), + rangeStartRow: String(range.start.row), + rangeStartColumn: String(range.start.column), + rangeEndRow: String(range.end.row), + rangeEndColumn: String(range.end.column) + }); + + const renderedProviders = _react.createElement( + 'div', + null, + datatipsAndProviders.map(function ({ datatip, provider }) { + return _react.createElement(PinnableDatatip, { + datatip: datatip, + editor: _this3._editor, + key: getProviderName(provider), + onPinClick: _this3._handlePinClicked + }); + }) + ); + + return { + range, + renderedProviders + }; + })(); } - _isHoveringOverPinnedTip(): boolean { + _isHoveringOverPinnedTip() { const pinnedDataTips = Array.from(this._pinnedDatatips.values()); const hoveringTips = pinnedDataTips.filter(dt => dt.isHovering()); return hoveringTips != null && hoveringTips.length > 0; } - _hideDatatip(): void { + _hideDatatip() { this._lastHiddenTime = performance.now(); if (this._marker) { this._marker.destroy(); this._marker = null; } this._range = null; - ReactDOM.unmountComponentAtNode(this._datatipElement); + _reactDom.default.unmountComponentAtNode(this._datatipElement); this._datatipElement.style.display = 'none'; } - _hideOrCancel(): void { - if ( - this._datatipState === DatatipState.HIDDEN || - this._datatipState === DatatipState.FETCHING - ) { - this._blacklistedPosition = getBufferPosition( - this._editor, - this._editorView, - this._lastMoveEvent, - ); + _hideOrCancel() { + if (this._datatipState === DatatipState.HIDDEN || this._datatipState === DatatipState.FETCHING) { + this._blacklistedPosition = getBufferPosition(this._editor, this._editorView, this._lastMoveEvent); return; } this._setState(DatatipState.HIDDEN); } - _hideIfOutside(): void { + _hideIfOutside() { if (this._datatipState !== DatatipState.VISIBLE) { return; } @@ -614,7 +553,7 @@ class DatatipManagerForEditor { } } - _hideIfOutsideImmediate(): void { + _hideIfOutsideImmediate() { if (this._datatipState !== DatatipState.VISIBLE) { return; } @@ -627,58 +566,49 @@ class DatatipManagerForEditor { return; } - const currentPosition = getBufferPosition( - this._editor, - this._editorView, - this._lastMoveEvent, - ); - if ( - currentPosition && - this._range && - this._range.containsPoint(currentPosition) - ) { + const currentPosition = getBufferPosition(this._editor, this._editorView, this._lastMoveEvent); + if (currentPosition && this._range && this._range.containsPoint(currentPosition)) { return; } this._setState(DatatipState.HIDDEN); } - createPinnedDataTip(datatip: Datatip, editor: TextEditor): PinnedDatatip { - const pinnedDatatip = new PinnedDatatip( - datatip, - editor, - /* onDispose */ () => { - this._pinnedDatatips.delete(pinnedDatatip); - }, - /* hideDataTips */ () => { - this._hideDatatip(); - }, - ); + createPinnedDataTip(datatip, editor) { + const pinnedDatatip = new (_PinnedDatatip || _load_PinnedDatatip()).PinnedDatatip(datatip, editor, + /* onDispose */() => { + this._pinnedDatatips.delete(pinnedDatatip); + }, + /* hideDataTips */() => { + this._hideDatatip(); + }); return pinnedDatatip; } - _handlePinClicked = (editor: TextEditor, datatip: Datatip) => { - analytics.track('datatip-pinned-open'); - const startTime = performanceNow(); +} + +var _initialiseProps = function () { + var _this4 = this; + + this._handlePinClicked = (editor, datatip) => { + (_analytics || _load_analytics()).default.track('datatip-pinned-open'); + const startTime = (0, (_performanceNow || _load_performanceNow()).default)(); this._setState(DatatipState.HIDDEN); - this._pinnedDatatips.add( - new PinnedDatatip( - datatip, - editor, - /* onDispose */ pinnedDatatip => { - this._pinnedDatatips.delete(pinnedDatatip); - analytics.track('datatip-pinned-close', { - duration: performanceNow() - startTime, - }); - }, - /* hideDataTips */ () => { - this._hideDatatip(); - }, - ), - ); + this._pinnedDatatips.add(new (_PinnedDatatip || _load_PinnedDatatip()).PinnedDatatip(datatip, editor, + /* onDispose */pinnedDatatip => { + this._pinnedDatatips.delete(pinnedDatatip); + (_analytics || _load_analytics()).default.track('datatip-pinned-close', { + duration: (0, (_performanceNow || _load_performanceNow()).default)() - startTime + }); + }, + /* hideDataTips */() => { + this._hideDatatip(); + })); }; - _toggleDatatip = (e?: atom$CustomEvent) => { + this._toggleDatatip = e => { + var _ref, _ref2; + if (atom.workspace.getActiveTextEditor() !== this._editor) { return; } @@ -686,24 +616,19 @@ class DatatipManagerForEditor { // Note that we don't need to hide the tooltip, we already hide it on // keydown, which is going to be triggered before the key binding which is // evaluated on keyup. - const maybeEventType = idx(e, _ => _.originalEvent.type); + const maybeEventType = (_ref = e) != null ? (_ref2 = _ref.originalEvent) != null ? _ref2.type : _ref2 : _ref; // Unfortunately, when you do keydown of the shortcut, it's going to // hide it, we need to make sure that when we do keyup, it doesn't show // it up right away. We assume that a keypress is done within 100ms // and don't show it again if it was hidden so soon. - const forceShow = - maybeEventType === 'keydown' && - performance.now() - this._lastHiddenTime > 100; + const forceShow = maybeEventType === 'keydown' && performance.now() - this._lastHiddenTime > 100; const forceHide = maybeEventType === 'keyup'; - const forceToggle = - maybeEventType !== 'keydown' && maybeEventType !== 'keyup'; + const forceToggle = maybeEventType !== 'keydown' && maybeEventType !== 'keyup'; if ( - // if we have event information, prefer that for determining show/hide - forceShow || - (forceToggle && this._datatipState === DatatipState.HIDDEN) - ) { + // if we have event information, prefer that for determining show/hide + forceShow || forceToggle && this._datatipState === DatatipState.HIDDEN) { this._lastFetchedFromCursorPosition = true; this._startFetching(() => this._editor.getCursorScreenPosition()); } else if (forceHide || forceToggle) { @@ -711,19 +636,21 @@ class DatatipManagerForEditor { } }; - _copyDatatipToClipboard = async () => { - if (atom.workspace.getActiveTextEditor() !== this._editor) { + this._copyDatatipToClipboard = (0, _asyncToGenerator.default)(function* () { + var _ref3, _ref4; + + if (atom.workspace.getActiveTextEditor() !== _this4._editor) { return; } - const pos = this._editor.getCursorScreenPosition(); + const pos = _this4._editor.getCursorScreenPosition(); if (pos == null) { return; } - const results: Array = await this._fetch(pos); - this._setState(DatatipState.HIDDEN); + const results = yield _this4._fetch(pos); + _this4._setState(DatatipState.HIDDEN); - const tip = idx(results, _ => _[0].datatip); + const tip = (_ref3 = results) != null ? (_ref4 = _ref3[0]) != null ? _ref4.datatip : _ref4 : _ref3; if (tip == null || tip.markedStrings == null) { return; } @@ -733,68 +660,55 @@ class DatatipManagerForEditor { return; } - const value = markedStrings.map(string => string.value).join(); + const value = markedStrings.map(function (string) { + return string.value; + }).join(); if (value === '') { return; } atom.clipboard.write(value); - atom.notifications.addInfo( - `Copied data tip to clipboard: \`\`\`${value}\`\`\``, - ); - }; -} + atom.notifications.addInfo(`Copied data tip to clipboard: \`\`\`${value}\`\`\``); + }); +}; -export class DatatipManager { - _datatipProviders: ProviderRegistry; - _modifierDatatipProviders: ProviderRegistry; - _editorManagers: Map; - _subscriptions: UniversalDisposable; +class DatatipManager { constructor() { - this._subscriptions = new UniversalDisposable(); + this._subscriptions = new (_UniversalDisposable || _load_UniversalDisposable()).default(); this._editorManagers = new Map(); - this._datatipProviders = new ProviderRegistry(); - this._modifierDatatipProviders = new ProviderRegistry(); - - this._subscriptions.add( - observeTextEditors(editor => { - const manager = new DatatipManagerForEditor( - editor, - this._datatipProviders, - this._modifierDatatipProviders, - ); - this._editorManagers.set(editor, manager); - const disposable = new UniversalDisposable(() => { - manager.dispose(); - this._editorManagers.delete(editor); - }); - this._subscriptions.add(disposable); - editor.onDidDestroy(() => disposable.dispose()); - }), - ); + this._datatipProviders = new (_ProviderRegistry || _load_ProviderRegistry()).default(); + this._modifierDatatipProviders = new (_ProviderRegistry || _load_ProviderRegistry()).default(); + + this._subscriptions.add((0, (_textEditor || _load_textEditor()).observeTextEditors)(editor => { + const manager = new DatatipManagerForEditor(editor, this._datatipProviders, this._modifierDatatipProviders); + this._editorManagers.set(editor, manager); + const disposable = new (_UniversalDisposable || _load_UniversalDisposable()).default(() => { + manager.dispose(); + this._editorManagers.delete(editor); + }); + this._subscriptions.add(disposable); + editor.onDidDestroy(() => disposable.dispose()); + })); } - addProvider(provider: DatatipProvider): IDisposable { + addProvider(provider) { return this._datatipProviders.addProvider(provider); } - addModifierProvider(provider: ModifierDatatipProvider): IDisposable { + addModifierProvider(provider) { return this._modifierDatatipProviders.addProvider(provider); } - createPinnedDataTip(datatip: Datatip, editor: TextEditor): PinnedDatatip { + createPinnedDataTip(datatip, editor) { const manager = this._editorManagers.get(editor); if (!manager) { - throw new Error( - 'Trying to create a pinned data tip on an editor that has ' + - 'no datatip manager', - ); + throw new Error('Trying to create a pinned data tip on an editor that has ' + 'no datatip manager'); } return manager.createPinnedDataTip(datatip, editor); } - dispose(): void { + dispose() { this._subscriptions.dispose(); this._editorManagers.forEach(manager => { manager.dispose(); @@ -802,3 +716,4 @@ export class DatatipManager { this._editorManagers = new Map(); } } +exports.DatatipManager = DatatipManager; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/MarkedStringDatatip.js b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/MarkedStringDatatip.js index 1bb269b0..655a3735 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/MarkedStringDatatip.js +++ b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/MarkedStringDatatip.js @@ -1,3 +1,27 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _marked; + +function _load_marked() { + return _marked = _interopRequireDefault(require('marked')); +} + +var _react = _interopRequireWildcard(require('react')); + +var _MarkedStringSnippet; + +function _load_MarkedStringSnippet() { + return _MarkedStringSnippet = _interopRequireDefault(require('./MarkedStringSnippet')); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,43 +30,31 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {MarkedString} from './types'; - -import marked from 'marked'; -import * as React from 'react'; - -import MarkedStringSnippet from './MarkedStringSnippet'; - -type Props = { - markedStrings: Array, -}; - -export default class MarkedStringDatatip extends React.PureComponent { - render(): React.Node { +class MarkedStringDatatip extends _react.PureComponent { + render() { const elements = this.props.markedStrings.map((chunk, i) => { if (chunk.type === 'markdown') { - return ( -
- ); + return _react.createElement('div', { + className: 'datatip-marked-container', + dangerouslySetInnerHTML: { + __html: (0, (_marked || _load_marked()).default)(chunk.value, { sanitize: true }) + }, + key: i + }); } else { - return ; + return _react.createElement((_MarkedStringSnippet || _load_MarkedStringSnippet()).default, Object.assign({ key: i }, chunk)); } }); - return ( -
- {elements} -
+ return _react.createElement( + 'div', + { className: 'datatip-marked' }, + elements ); } } +exports.default = MarkedStringDatatip; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/MarkedStringSnippet.js b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/MarkedStringSnippet.js index a1cfce2e..fdd6e2fb 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/MarkedStringSnippet.js +++ b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/MarkedStringSnippet.js @@ -1,65 +1,70 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import {TextBuffer} from 'atom'; -import * as React from 'react'; -import {AtomTextEditor} from 'nuclide-commons-ui/AtomTextEditor'; +Object.defineProperty(exports, "__esModule", { + value: true +}); -// Complex types can end up being super long. Truncate them. -const MAX_LENGTH = 100; +var _atom = require('atom'); + +var _react = _interopRequireWildcard(require('react')); -type Props = { - value: string, - grammar: atom$Grammar, -}; +var _AtomTextEditor; -type State = { - isExpanded: boolean, -}; +function _load_AtomTextEditor() { + return _AtomTextEditor = require('nuclide-commons-ui/AtomTextEditor'); +} -export default class MarkedStringSnippet extends React.Component { - state = { - isExpanded: false, - }; +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +// Complex types can end up being super long. Truncate them. +const MAX_LENGTH = 100; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ - render(): React.Node { - const {value} = this.props; +class MarkedStringSnippet extends _react.Component { + constructor(...args) { + var _temp; + + return _temp = super(...args), this.state = { + isExpanded: false + }, _temp; + } + + render() { + const { value } = this.props; const shouldTruncate = value.length > MAX_LENGTH && !this.state.isExpanded; - const buffer = new TextBuffer( - shouldTruncate ? value.substr(0, MAX_LENGTH) + '...' : value, - ); + const buffer = new _atom.TextBuffer(shouldTruncate ? value.substr(0, MAX_LENGTH) + '...' : value); // Improve the display of Hack snippets. - let {grammar} = this.props; + let { grammar } = this.props; if (grammar.scopeName === 'text.html.hack') { - grammar = - atom.grammars.grammarForScopeName('source.hackfragment') || grammar; + grammar = atom.grammars.grammarForScopeName('source.hackfragment') || grammar; } - return ( -
) => { - this.setState({isExpanded: !this.state.isExpanded}); + return _react.createElement( + 'div', + { + className: 'datatip-marked-text-editor-container', + onClick: e => { + this.setState({ isExpanded: !this.state.isExpanded }); e.stopPropagation(); - }}> - -
+ } }, + _react.createElement((_AtomTextEditor || _load_AtomTextEditor()).AtomTextEditor, { + className: 'datatip-marked-text-editor', + gutterHidden: true, + readOnly: true, + syncTextContents: false, + autoGrow: true, + grammar: grammar, + textBuffer: buffer + }) ); } } +exports.default = MarkedStringSnippet; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/PinnedDatatip.js b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/PinnedDatatip.js index 1a7917b6..e9a5807b 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/PinnedDatatip.js +++ b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/PinnedDatatip.js @@ -1,3 +1,34 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PinnedDatatip = undefined; + +var _atom = require('atom'); + +var _react = _interopRequireWildcard(require('react')); + +var _reactDom = _interopRequireDefault(require('react-dom')); + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _DatatipComponent; + +function _load_DatatipComponent() { + return _DatatipComponent = require('./DatatipComponent'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,74 +37,33 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {Datatip} from './types'; - -type Position = { - x: number, - y: number, -}; - -import {CompositeDisposable, Disposable} from 'atom'; -import * as React from 'react'; -import ReactDOM from 'react-dom'; -import {Observable} from 'rxjs'; -import invariant from 'assert'; -import classnames from 'classnames'; - -import {DatatipComponent, DATATIP_ACTIONS} from './DatatipComponent'; - const LINE_END_MARGIN = 20; let _mouseMove$; -function documentMouseMove$(): Observable { +function documentMouseMove$() { if (_mouseMove$ == null) { - _mouseMove$ = Observable.fromEvent(document, 'mousemove'); + _mouseMove$ = _rxjsBundlesRxMinJs.Observable.fromEvent(document, 'mousemove'); } return _mouseMove$; } let _mouseUp$; -function documentMouseUp$(): Observable { +function documentMouseUp$() { if (_mouseUp$ == null) { - _mouseUp$ = Observable.fromEvent(document, 'mouseup'); + _mouseUp$ = _rxjsBundlesRxMinJs.Observable.fromEvent(document, 'mouseup'); } return _mouseUp$; } -export class PinnedDatatip { - _boundDispose: Function; - _boundHandleMouseDown: Function; - _boundHandleMouseEnter: Function; - _boundHandleMouseLeave: Function; - _boundHandleCapturedClick: Function; - _mouseUpTimeout: ?number; - _hostElement: HTMLElement; - _marker: ?atom$Marker; - _rangeDecoration: ?atom$Decoration; - _mouseSubscription: ?rxjs$ISubscription; - _subscriptions: atom$CompositeDisposable; - _datatip: Datatip; - _editor: TextEditor; - _hostElement: HTMLElement; - _boundDispose: Function; - _dragOrigin: ?Position; - _isDragging: boolean; - _offset: Position; - _isHovering: boolean; - _hideDataTips: () => void; - - constructor( - datatip: Datatip, - editor: TextEditor, - onDispose: (pinnedDatatip: PinnedDatatip) => void, - hideDataTips: () => void, - ) { - this._subscriptions = new CompositeDisposable(); - this._subscriptions.add(new Disposable(() => onDispose(this))); +class PinnedDatatip { + + constructor(datatip, editor, onDispose, hideDataTips) { + this._subscriptions = new _atom.CompositeDisposable(); + this._subscriptions.add(new _atom.Disposable(() => onDispose(this))); this._datatip = datatip; this._editor = editor; this._marker = null; @@ -85,28 +75,14 @@ export class PinnedDatatip { this._boundHandleMouseEnter = this.handleMouseEnter.bind(this); this._boundHandleMouseLeave = this.handleMouseLeave.bind(this); this._boundHandleCapturedClick = this.handleCapturedClick.bind(this); - this._hostElement.addEventListener( - 'mouseenter', - this._boundHandleMouseEnter, - ); - this._hostElement.addEventListener( - 'mouseleave', - this._boundHandleMouseLeave, - ); - this._subscriptions.add( - new Disposable(() => { - this._hostElement.removeEventListener( - 'mouseenter', - this._boundHandleMouseEnter, - ); - this._hostElement.removeEventListener( - 'mouseleave', - this._boundHandleMouseLeave, - ); - }), - ); + this._hostElement.addEventListener('mouseenter', this._boundHandleMouseEnter); + this._hostElement.addEventListener('mouseleave', this._boundHandleMouseLeave); + this._subscriptions.add(new _atom.Disposable(() => { + this._hostElement.removeEventListener('mouseenter', this._boundHandleMouseEnter); + this._hostElement.removeEventListener('mouseleave', this._boundHandleMouseLeave); + })); this._mouseUpTimeout = null; - this._offset = {x: 0, y: 0}; + this._offset = { x: 0, y: 0 }; this._isDragging = false; this._dragOrigin = null; this._isHovering = false; @@ -114,32 +90,36 @@ export class PinnedDatatip { this.render(); } - handleMouseEnter(event: MouseEvent): void { + handleMouseEnter(event) { this._isHovering = true; this._hideDataTips(); } - handleMouseLeave(event: MouseEvent): void { + handleMouseLeave(event) { this._isHovering = false; } - isHovering(): boolean { + isHovering() { return this._isHovering; } - handleGlobalMouseMove(event: Event): void { - const evt: MouseEvent = (event: any); - const {_dragOrigin} = this; - invariant(_dragOrigin); + handleGlobalMouseMove(event) { + const evt = event; + const { _dragOrigin } = this; + + if (!_dragOrigin) { + throw new Error('Invariant violation: "_dragOrigin"'); + } + this._isDragging = true; this._offset = { x: evt.clientX - _dragOrigin.x, - y: evt.clientY - _dragOrigin.y, + y: evt.clientY - _dragOrigin.y }; this.render(); } - handleGlobalMouseUp(): void { + handleGlobalMouseUp() { // If the datatip was moved, push the effects of mouseUp to the next tick, // in order to allow cancelation of captured events (e.g. clicks on child components). this._mouseUpTimeout = setTimeout(() => { @@ -151,73 +131,56 @@ export class PinnedDatatip { }, 0); } - _ensureMouseSubscriptionDisposed(): void { + _ensureMouseSubscriptionDisposed() { if (this._mouseSubscription != null) { this._mouseSubscription.unsubscribe(); this._mouseSubscription = null; } } - handleMouseDown(event: Event): void { - const evt: MouseEvent = (event: any); + handleMouseDown(event) { + const evt = event; this._dragOrigin = { x: evt.clientX - this._offset.x, - y: evt.clientY - this._offset.y, + y: evt.clientY - this._offset.y }; this._ensureMouseSubscriptionDisposed(); - this._mouseSubscription = documentMouseMove$() - .takeUntil(documentMouseUp$()) - .subscribe( - (e: MouseEvent) => { - this.handleGlobalMouseMove(e); - }, - (error: any) => {}, - () => { - this.handleGlobalMouseUp(); - }, - ); + this._mouseSubscription = documentMouseMove$().takeUntil(documentMouseUp$()).subscribe(e => { + this.handleGlobalMouseMove(e); + }, error => {}, () => { + this.handleGlobalMouseUp(); + }); } - handleCapturedClick(event: SyntheticEvent<>): void { + handleCapturedClick(event) { if (this._isDragging) { event.stopPropagation(); } } // Ensure positioning of the Datatip at the end of the current line. - _updateHostElementPosition(): void { - const {_editor, _datatip, _hostElement, _offset} = this; - const {range} = _datatip; + _updateHostElementPosition() { + const { _editor, _datatip, _hostElement, _offset } = this; + const { range } = _datatip; const charWidth = _editor.getDefaultCharWidth(); const lineLength = _editor.getBuffer().getLines()[range.start.row].length; _hostElement.style.display = 'block'; - _hostElement.style.top = - -_editor.getLineHeightInPixels() + _offset.y + 'px'; - _hostElement.style.left = - (lineLength - range.end.column) * charWidth + - LINE_END_MARGIN + - _offset.x + - 'px'; + _hostElement.style.top = -_editor.getLineHeightInPixels() + _offset.y + 'px'; + _hostElement.style.left = (lineLength - range.end.column) * charWidth + LINE_END_MARGIN + _offset.x + 'px'; } - render(): void { - const {_editor, _datatip, _hostElement, _isDragging, _isHovering} = this; + render() { + const { _editor, _datatip, _hostElement, _isDragging, _isHovering } = this; this._updateHostElementPosition(); - ReactDOM.render( - , - _hostElement, - ); + _reactDom.default.render(_react.createElement((_DatatipComponent || _load_DatatipComponent()).DatatipComponent, { + action: (_DatatipComponent || _load_DatatipComponent()).DATATIP_ACTIONS.CLOSE, + actionTitle: 'Close this datatip', + className: (0, (_classnames || _load_classnames()).default)(_isDragging ? 'datatip-dragging' : '', 'datatip-pinned'), + datatip: _datatip, + onActionClick: this._boundDispose, + onMouseDown: this._boundHandleMouseDown, + onClickCapture: this._boundHandleCapturedClick + }), _hostElement); let rangeClassname = 'datatip-highlight-region'; if (_isHovering) { @@ -225,30 +188,33 @@ export class PinnedDatatip { } if (this._marker == null) { - const marker: atom$Marker = _editor.markBufferRange(_datatip.range, { - invalidate: 'never', + const marker = _editor.markBufferRange(_datatip.range, { + invalidate: 'never' }); this._marker = marker; _editor.decorateMarker(marker, { type: 'overlay', position: 'head', - item: this._hostElement, + item: this._hostElement }); this._rangeDecoration = _editor.decorateMarker(marker, { type: 'highlight', - class: rangeClassname, + class: rangeClassname }); } else { // `this._rangeDecoration` is guaranteed to exist iff `this._marker` exists. - invariant(this._rangeDecoration); + if (!this._rangeDecoration) { + throw new Error('Invariant violation: "this._rangeDecoration"'); + } + this._rangeDecoration.setProperties({ type: 'highlight', - class: rangeClassname, + class: rangeClassname }); } } - dispose(): void { + dispose() { if (this._mouseUpTimeout != null) { clearTimeout(this._mouseUpTimeout); } @@ -258,8 +224,9 @@ export class PinnedDatatip { if (this._mouseSubscription != null) { this._mouseSubscription.unsubscribe(); } - ReactDOM.unmountComponentAtNode(this._hostElement); + _reactDom.default.unmountComponentAtNode(this._hostElement); this._hostElement.remove(); this._subscriptions.dispose(); } } +exports.PinnedDatatip = PinnedDatatip; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/getModifierKeys.js b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/getModifierKeys.js index 0ec9fd8d..a0806027 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/getModifierKeys.js +++ b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/getModifierKeys.js @@ -1,3 +1,17 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getModifierKeysFromMouseEvent = getModifierKeysFromMouseEvent; +exports.getModifierKeyFromKeyboardEvent = getModifierKeyFromKeyboardEvent; + +var _types; + +function _load_types() { + return _types = require('./types'); +} + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,40 +20,35 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {ModifierKey} from './types'; -import {ModifierKeys} from './types'; - const KEYNAME_TO_PROPERTY = { - Meta: ModifierKeys.META, - Shift: ModifierKeys.SHIFT, - Alt: ModifierKeys.ALT, - Control: ModifierKeys.CTRL, + Meta: (_types || _load_types()).ModifierKeys.META, + Shift: (_types || _load_types()).ModifierKeys.SHIFT, + Alt: (_types || _load_types()).ModifierKeys.ALT, + Control: (_types || _load_types()).ModifierKeys.CTRL }; -export function getModifierKeysFromMouseEvent(e: MouseEvent): Set { - const keys: Set = new Set(); +function getModifierKeysFromMouseEvent(e) { + const keys = new Set(); if (e.metaKey) { - keys.add(ModifierKeys.META); + keys.add((_types || _load_types()).ModifierKeys.META); } if (e.shiftKey) { - keys.add(ModifierKeys.SHIFT); + keys.add((_types || _load_types()).ModifierKeys.SHIFT); } if (e.altKey) { - keys.add(ModifierKeys.ALT); + keys.add((_types || _load_types()).ModifierKeys.ALT); } if (e.ctrlKey) { - keys.add(ModifierKeys.CTRL); + keys.add((_types || _load_types()).ModifierKeys.CTRL); } return keys; } -export function getModifierKeyFromKeyboardEvent( - e: KeyboardEvent, -): ?ModifierKey { +function getModifierKeyFromKeyboardEvent(e) { return KEYNAME_TO_PROPERTY[e.key]; -} +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/main.js b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/main.js index 3b4b9434..c4bdb806 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/main.js +++ b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/main.js @@ -1,34 +1,42 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {DatatipService} from './types'; - -import createPackage from 'nuclide-commons-atom/createPackage'; -import {DatatipManager} from './DatatipManager'; +'use strict'; + +var _createPackage; + +function _load_createPackage() { + return _createPackage = _interopRequireDefault(require('nuclide-commons-atom/createPackage')); +} + +var _DatatipManager; + +function _load_DatatipManager() { + return _DatatipManager = require('./DatatipManager'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class Activation { - _datatipManager: DatatipManager; constructor() { - this._datatipManager = new DatatipManager(); + this._datatipManager = new (_DatatipManager || _load_DatatipManager()).DatatipManager(); } - provideDatatipService(): DatatipService { + provideDatatipService() { return this._datatipManager; } dispose() { this._datatipManager.dispose(); } -} +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ -createPackage(module.exports, Activation); +(0, (_createPackage || _load_createPackage()).default)(module.exports, Activation); \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/types.js b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/types.js index 91d8d46b..8f8cebc6 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/types.js +++ b/modules/atom-ide-ui/pkg/atom-ide-datatip/lib/types.js @@ -1,3 +1,8 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,7 +11,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ @@ -15,66 +20,11 @@ * You can register providers (which will be triggered on mouseover) or manually * create pinned datatips on-demand. */ -export type DatatipService = { - addProvider(provider: DatatipProvider): IDisposable, - addModifierProvider(provider: ModifierDatatipProvider): IDisposable, - createPinnedDataTip(datatip: Datatip, editor: TextEditor): IDisposable, -}; - -export type DatatipProvider = { - priority: number, - grammarScopes?: Array, - // A unique name for the provider to be used for analytics. - // It is recommended that it be the name of the provider's package. - providerName: string, - datatip( - editor: atom$TextEditor, - bufferPosition: atom$Point, - ): Promise, -}; - -export type ModifierDatatipProvider = { - priority: number, - grammarScopes?: Array, - providerName: string, - modifierDatatip( - editor: atom$TextEditor, - bufferPosition: atom$Point, - heldKeys: Set, - ): Promise, -}; - -export type AnyDatatipProvider = DatatipProvider | ModifierDatatipProvider; - -export type Datatip = - | {| - component: React$ComponentType, - range: atom$Range, - pinnable?: boolean, - |} - | {| - markedStrings: Array, - range: atom$Range, - pinnable?: boolean, - |}; - -// Borrowed from the LSP API. -export type MarkedString = - | { - type: 'markdown', - value: string, - } - | { - type: 'snippet', - grammar: atom$Grammar, - value: string, - }; - -export const ModifierKeys = Object.freeze({ +const ModifierKeys = exports.ModifierKeys = Object.freeze({ META: 'metaKey', SHIFT: 'shiftKey', ALT: 'altKey', - CTRL: 'ctrlKey', + CTRL: 'ctrlKey' }); -export type ModifierKey = 'metaKey' | 'shiftKey' | 'altKey' | 'ctrlKey'; +// Borrowed from the LSP API. \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/DefinitionCache.js b/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/DefinitionCache.js index 412bcd7d..4eaad620 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/DefinitionCache.js +++ b/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/DefinitionCache.js @@ -1,3 +1,34 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + +var _range; + +function _load_range() { + return _range = require('nuclide-commons-atom/range'); +} + +var _range2; + +function _load_range2() { + return _range2 = require('nuclide-commons/range'); +} + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// An atom$Range-aware, single-item cache for the common case of requerying +// a definition (such as previewing hyperclick and then jumping to the +// destination). It invalidates whenever the originating editor changes. /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,62 +37,46 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {DefinitionQueryResult} from './types'; -import {wordAtPosition} from 'nuclide-commons-atom/range'; -import {isPositionInRange} from 'nuclide-commons/range'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; - -// An atom$Range-aware, single-item cache for the common case of requerying -// a definition (such as previewing hyperclick and then jumping to the -// destination). It invalidates whenever the originating editor changes. class DefinitionCache { - _cachedResultEditor: ?atom$TextEditor; - _cachedResultPromise: ?Promise; - _cachedResultRange: ?atom$Range; - _disposables: UniversalDisposable = new UniversalDisposable(); + constructor() { + this._disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(); + } dispose() { this._disposables.dispose(); } - async get( - editor: atom$TextEditor, - position: atom$Point, - getImpl: () => Promise, - ): Promise { - // queryRange is often a list of one range - if ( - this._cachedResultRange != null && - this._cachedResultEditor === editor && - isPositionInRange(position, this._cachedResultRange) - ) { - return this._cachedResultPromise; - } - - // invalidate whenever the buffer changes - const invalidateAndStopListening = () => { - this._cachedResultEditor = null; - this._cachedResultRange = null; - this._cachedResultRange = null; - this._disposables.remove(editorDisposables); - editorDisposables.dispose(); - }; - const editorDisposables = new UniversalDisposable( - editor.onDidChange(invalidateAndStopListening), - editor.onDidDestroy(invalidateAndStopListening), - ); - this._disposables.add(editorDisposables); - - const wordGuess = wordAtPosition(editor, position); - this._cachedResultRange = wordGuess && wordGuess.range; - this._cachedResultPromise = getImpl(); - - return this._cachedResultPromise; + get(editor, position, getImpl) { + var _this = this; + + return (0, _asyncToGenerator.default)(function* () { + // queryRange is often a list of one range + if (_this._cachedResultRange != null && _this._cachedResultEditor === editor && (0, (_range2 || _load_range2()).isPositionInRange)(position, _this._cachedResultRange)) { + return _this._cachedResultPromise; + } + + // invalidate whenever the buffer changes + const invalidateAndStopListening = function () { + _this._cachedResultEditor = null; + _this._cachedResultRange = null; + _this._cachedResultRange = null; + _this._disposables.remove(editorDisposables); + editorDisposables.dispose(); + }; + const editorDisposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(editor.onDidChange(invalidateAndStopListening), editor.onDidDestroy(invalidateAndStopListening)); + _this._disposables.add(editorDisposables); + + const wordGuess = (0, (_range || _load_range()).wordAtPosition)(editor, position); + _this._cachedResultRange = wordGuess && wordGuess.range; + _this._cachedResultPromise = getImpl(); + + return _this._cachedResultPromise; + })(); } } -export default DefinitionCache; +exports.default = DefinitionCache; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/getPreviewDatatipFromDefinitionResult.js b/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/getPreviewDatatipFromDefinitionResult.js index 9786d5e2..38d9e29f 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/getPreviewDatatipFromDefinitionResult.js +++ b/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/getPreviewDatatipFromDefinitionResult.js @@ -1,99 +1,108 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import analytics from 'nuclide-commons-atom/analytics'; -import {getDefinitionPreview as getLocalFileDefinitionPreview} from 'nuclide-commons/symbol-definition-preview'; - -import React from 'react'; -import type {Datatip} from '../../atom-ide-datatip/lib/types'; - -import type { - Definition, - DefinitionQueryResult, - DefinitionPreviewProvider, -} from './types'; - -export default (async function getPreviewDatatipFromDefinition( - definitionResult: DefinitionQueryResult, - definitionPreviewProvider: ?DefinitionPreviewProvider, - grammar: atom$Grammar, -): Promise { - const {queryRange, definitions} = definitionResult; - - if (definitions.length === 1) { - const definition = definitions[0]; - // Some providers (e.g. Flow) return negative positions. - if (definition.position.row < 0) { - return null; - } +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); - const definitionPreview = await getPreview( - definition, - definitionPreviewProvider, - ); +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); - if (definitionPreview == null) { - return null; +let getPreview = (() => { + var _ref2 = (0, _asyncToGenerator.default)(function* (definition, definitionPreviewProvider) { + let getDefinitionPreviewFn; + if (definitionPreviewProvider == null) { + getDefinitionPreviewFn = (_symbolDefinitionPreview || _load_symbolDefinitionPreview()).getDefinitionPreview; + } else { + getDefinitionPreviewFn = definitionPreviewProvider.getDefinitionPreview.bind(definitionPreviewProvider); } - // if mimetype is image return image component with base-64 encoded - // image contents, otherwise use markedStrings - if (definitionPreview.mime.startsWith('image/')) { + return (_analytics || _load_analytics()).default.trackTiming('hyperclickPreview.getDefinitionPreview', function () { + return getDefinitionPreviewFn(definition); + }); + }); + + return function getPreview(_x4, _x5) { + return _ref2.apply(this, arguments); + }; +})(); + +var _analytics; + +function _load_analytics() { + return _analytics = _interopRequireDefault(require('nuclide-commons-atom/analytics')); +} + +var _symbolDefinitionPreview; + +function _load_symbolDefinitionPreview() { + return _symbolDefinitionPreview = require('nuclide-commons/symbol-definition-preview'); +} + +var _react = _interopRequireDefault(require('react')); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = (() => { + var _ref = (0, _asyncToGenerator.default)(function* (definitionResult, definitionPreviewProvider, grammar) { + const { queryRange, definitions } = definitionResult; + + if (definitions.length === 1) { + const definition = definitions[0]; + // Some providers (e.g. Flow) return negative positions. + if (definition.position.row < 0) { + return null; + } + + const definitionPreview = yield getPreview(definition, definitionPreviewProvider); + + if (definitionPreview == null) { + return null; + } + + // if mimetype is image return image component with base-64 encoded + // image contents, otherwise use markedStrings + if (definitionPreview.mime.startsWith('image/')) { + return { + component: function () { + return _react.default.createElement('img', { + src: `data:${definitionPreview.mime};${definitionPreview.encoding},${definitionPreview.contents}` + }); + }, + range: queryRange[0] + }; + } return { - component: () => - , - range: queryRange[0], - }; - } - return { - markedStrings: [ - { + markedStrings: [{ type: 'snippet', value: definitionPreview.contents, - grammar, - }, - ], - range: queryRange[0], - }; - } + grammar + }], + range: queryRange[0] + }; + } - return { - markedStrings: [ - { + return { + markedStrings: [{ type: 'markdown', value: `${definitions.length} definitions found. Click to jump.`, - grammar, - }, - ], - range: queryRange[0], - }; -}); + grammar + }], + range: queryRange[0] + }; + }); -async function getPreview( - definition: Definition, - definitionPreviewProvider: ?DefinitionPreviewProvider, -) { - let getDefinitionPreviewFn; - if (definitionPreviewProvider == null) { - getDefinitionPreviewFn = getLocalFileDefinitionPreview; - } else { - getDefinitionPreviewFn = definitionPreviewProvider.getDefinitionPreview.bind( - definitionPreviewProvider, - ); + function getPreviewDatatipFromDefinition(_x, _x2, _x3) { + return _ref.apply(this, arguments); } - return analytics.trackTiming('hyperclickPreview.getDefinitionPreview', () => - getDefinitionPreviewFn(definition), - ); -} + return getPreviewDatatipFromDefinition; +})(); /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/main.js b/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/main.js index 07fe4c1e..a99b94ea 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/main.js +++ b/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/main.js @@ -1,3 +1,69 @@ +'use strict'; + +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + +var _log4js; + +function _load_log4js() { + return _log4js = require('log4js'); +} + +var _analytics; + +function _load_analytics() { + return _analytics = _interopRequireDefault(require('nuclide-commons-atom/analytics')); +} + +var _createPackage; + +function _load_createPackage() { + return _createPackage = _interopRequireDefault(require('nuclide-commons-atom/createPackage')); +} + +var _featureConfig; + +function _load_featureConfig() { + return _featureConfig = _interopRequireDefault(require('nuclide-commons-atom/feature-config')); +} + +var _nuclideUri; + +function _load_nuclideUri() { + return _nuclideUri = _interopRequireDefault(require('nuclide-commons/nuclideUri')); +} + +var _ProviderRegistry; + +function _load_ProviderRegistry() { + return _ProviderRegistry = _interopRequireDefault(require('nuclide-commons-atom/ProviderRegistry')); +} + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _goToLocation; + +function _load_goToLocation() { + return _goToLocation = require('nuclide-commons-atom/go-to-location'); +} + +var _DefinitionCache; + +function _load_DefinitionCache() { + return _DefinitionCache = _interopRequireDefault(require('./DefinitionCache')); +} + +var _getPreviewDatatipFromDefinitionResult; + +function _load_getPreviewDatatipFromDefinitionResult() { + return _getPreviewDatatipFromDefinitionResult = _interopRequireDefault(require('./getPreviewDatatipFromDefinitionResult')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,205 +72,149 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ // This package provides Hyperclick results for any language which provides a // DefinitionProvider. -import type { - HyperclickProvider, - HyperclickSuggestion, -} from '../../hyperclick/lib/types'; - -import type { - Datatip, - DatatipService, - ModifierDatatipProvider, - ModifierKey, -} from '../../atom-ide-datatip/lib/types'; - -import type { - DefinitionQueryResult, - DefinitionProvider, - DefinitionPreviewProvider, -} from './types'; - -import invariant from 'assert'; -import {getLogger} from 'log4js'; - -import analytics from 'nuclide-commons-atom/analytics'; -import createPackage from 'nuclide-commons-atom/createPackage'; -import FeatureConfig from 'nuclide-commons-atom/feature-config'; -import nuclideUri from 'nuclide-commons/nuclideUri'; -import ProviderRegistry from 'nuclide-commons-atom/ProviderRegistry'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import {goToLocation} from 'nuclide-commons-atom/go-to-location'; - -import DefinitionCache from './DefinitionCache'; -import getPreviewDatatipFromDefinitionResult from './getPreviewDatatipFromDefinitionResult'; - class Activation { - _providers: ProviderRegistry; - _definitionPreviewProvider: ?DefinitionPreviewProvider; - _definitionCache: DefinitionCache; - _disposables: UniversalDisposable; - _triggerKeys: Set; constructor() { - this._providers = new ProviderRegistry(); - this._definitionCache = new DefinitionCache(); + this._providers = new (_ProviderRegistry || _load_ProviderRegistry()).default(); + this._definitionCache = new (_DefinitionCache || _load_DefinitionCache()).default(); this._triggerKeys = new Set(); - this._disposables = new UniversalDisposable( - FeatureConfig.observe( - getPlatformKeys(process.platform), - (newValue: ?string) => { - this._triggerKeys = (new Set( - // flowlint-next-line sketchy-null-string:off - newValue ? newValue.split(',') : null, - ): Set); - }, - ), - ); + this._disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default((_featureConfig || _load_featureConfig()).default.observe(getPlatformKeys(process.platform), newValue => { + this._triggerKeys = new Set( + // flowlint-next-line sketchy-null-string:off + newValue ? newValue.split(',') : null); + })); } dispose() { this._disposables.dispose(); } - async _getDefinition( - editor: atom$TextEditor, - position: atom$Point, - ): Promise { - for (const provider of this._providers.getAllProvidersForEditor(editor)) { - try { - // eslint-disable-next-line no-await-in-loop - const result = await provider.getDefinition(editor, position); - if (result != null) { - return result; + _getDefinition(editor, position) { + var _this = this; + + return (0, _asyncToGenerator.default)(function* () { + for (const provider of _this._providers.getAllProvidersForEditor(editor)) { + try { + // eslint-disable-next-line no-await-in-loop + const result = yield provider.getDefinition(editor, position); + if (result != null) { + return result; + } + } catch (err) { + (0, (_log4js || _load_log4js()).getLogger)('atom-ide-definitions').error(`Error getting definition for ${String(editor.getPath())}`, err); } - } catch (err) { - getLogger('atom-ide-definitions').error( - `Error getting definition for ${String(editor.getPath())}`, - err, - ); } - } - return null; + return null; + })(); } - async getSuggestion( - editor: atom$TextEditor, - position: atom$Point, - ): Promise { - const result = await this._definitionCache.get(editor, position, () => - this._getDefinition(editor, position), - ); + getSuggestion(editor, position) { + var _this2 = this; - if (result == null) { - return null; - } - - const {definitions} = result; - invariant(definitions.length > 0); - - function createCallback(definition) { - return () => { - goToLocation( - definition.path, - definition.position.row, - definition.position.column, - ); - }; - } - - function createTitle(definition) { - const filePath = - definition.projectRoot == null - ? definition.path - : nuclideUri.relative(definition.projectRoot, definition.path); - if (definition.name == null) { - // Fall back to just displaying the path:line. - return `${filePath}:${definition.position.row + 1}`; + return (0, _asyncToGenerator.default)(function* () { + const result = yield _this2._definitionCache.get(editor, position, function () { + return _this2._getDefinition(editor, position); + }); + + if (result == null) { + return null; + } + + const { definitions } = result; + + if (!(definitions.length > 0)) { + throw new Error('Invariant violation: "definitions.length > 0"'); + } + + function createCallback(definition) { + return () => { + (0, (_goToLocation || _load_goToLocation()).goToLocation)(definition.path, definition.position.row, definition.position.column); + }; + } + + function createTitle(definition) { + const filePath = definition.projectRoot == null ? definition.path : (_nuclideUri || _load_nuclideUri()).default.relative(definition.projectRoot, definition.path); + if (definition.name == null) { + // Fall back to just displaying the path:line. + return `${filePath}:${definition.position.row + 1}`; + } + return `${definition.name} (${filePath})`; } - return `${definition.name} (${filePath})`; - } - - if (definitions.length === 1) { - return { - range: result.queryRange, - callback: createCallback(definitions[0]), - }; - } else { - return { - range: result.queryRange, - callback: definitions.map(definition => { - return { - title: createTitle(definition), - callback: createCallback(definition), - }; - }), - }; - } + + if (definitions.length === 1) { + return { + range: result.queryRange, + callback: createCallback(definitions[0]) + }; + } else { + return { + range: result.queryRange, + callback: definitions.map(function (definition) { + return { + title: createTitle(definition), + callback: createCallback(definition) + }; + }) + }; + } + })(); } - async getPreview( - editor: atom$TextEditor, - position: atom$Point, - heldKeys: Set, - ): Promise { - if ( - !this._triggerKeys || + getPreview(editor, position, heldKeys) { + var _this3 = this; + + return (0, _asyncToGenerator.default)(function* () { + if (!_this3._triggerKeys || // are the required keys held down? - !Array.from(this._triggerKeys).every(key => heldKeys.has(key)) - ) { - return; - } + !Array.from(_this3._triggerKeys).every(function (key) { + return heldKeys.has(key); + })) { + return; + } - const result = await this._getDefinition(editor, position); - if (result == null) { - return null; - } - - const grammar = editor.getGrammar(); - const previewDatatip = getPreviewDatatipFromDefinitionResult( - result, - this._definitionPreviewProvider, - grammar, - ); - - // flowlint-next-line sketchy-null-mixed:off - if (previewDatatip != null && previewDatatip.markedStrings) { - analytics.track('hyperclick-preview-popup', { - grammar: grammar.name, - definitionCount: result.definitions.length, - }); - } + const result = yield _this3._getDefinition(editor, position); + if (result == null) { + return null; + } + + const grammar = editor.getGrammar(); + const previewDatatip = (0, (_getPreviewDatatipFromDefinitionResult || _load_getPreviewDatatipFromDefinitionResult()).default)(result, _this3._definitionPreviewProvider, grammar); + + // flowlint-next-line sketchy-null-mixed:off + if (previewDatatip != null && previewDatatip.markedStrings) { + (_analytics || _load_analytics()).default.track('hyperclick-preview-popup', { + grammar: grammar.name, + definitionCount: result.definitions.length + }); + } - return previewDatatip; + return previewDatatip; + })(); } - consumeDefinitionProvider(provider: DefinitionProvider): IDisposable { + consumeDefinitionProvider(provider) { const disposable = this._providers.addProvider(provider); this._disposables.add(disposable); return disposable; } - consumeDefinitionPreviewProvider(provider: DefinitionPreviewProvider) { + consumeDefinitionPreviewProvider(provider) { this._definitionPreviewProvider = provider; } - consumeDatatipService(service: DatatipService): IDisposable { - const datatipProvider: ModifierDatatipProvider = { + consumeDatatipService(service) { + const datatipProvider = { providerName: 'hyperclick-preview', priority: 1, - modifierDatatip: ( - editor: atom$TextEditor, - bufferPosition: atom$Point, - heldKeys: Set, - ) => this.getPreview(editor, bufferPosition, heldKeys), + modifierDatatip: (editor, bufferPosition, heldKeys) => this.getPreview(editor, bufferPosition, heldKeys) }; const disposable = service.addModifierProvider(datatipProvider); @@ -212,11 +222,11 @@ class Activation { return disposable; } - getHyperclickProvider(): HyperclickProvider { + getHyperclickProvider() { return { priority: 20, providerName: 'atom-ide-definitions', - getSuggestion: (editor, position) => this.getSuggestion(editor, position), + getSuggestion: (editor, position) => this.getSuggestion(editor, position) }; } } @@ -230,4 +240,4 @@ function getPlatformKeys(platform) { return 'hyperclick.linuxTriggerKeys'; } -createPackage(module.exports, Activation); +(0, (_createPackage || _load_createPackage()).default)(module.exports, Activation); \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/types.js b/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/types.js index c2ecc784..a726efc4 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/types.js +++ b/modules/atom-ide-ui/pkg/atom-ide-definitions/lib/types.js @@ -1,61 +1 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {NuclideUri} from 'nuclide-commons/nuclideUri'; - -export type Definition = { - // Path of the file in which the definition is located. - path: NuclideUri, - // First character of the definition's identifier. - // e.g. "F" in `class Foo {}` - position: atom$Point, - // Optional: the range of the entire definition. - // e.g. "c" to "}" in `class Foo {}` - range?: atom$Range, - // Optional: `name` and `projectRoot` can be provided to display a more human-readable title - // inside of Hyperclick when there are multiple definitions. - name?: string, - // If provided, `projectRoot` will be used to display a relativized version of `path`. - projectRoot?: NuclideUri, - // `language` may be used by consumers to identify the source of definitions. - language: string, -}; - -// Definition queries supply a point. -// The returned queryRange is the range within which the returned definition is valid. -// Typically queryRange spans the containing identifier around the query point. -export type DefinitionQueryResult = { - queryRange: Array, - definitions: Array, -}; - -// Provides definitions for a set of language grammars. -export type DefinitionProvider = { - // If there are multiple providers for a given grammar, - // the one with the highest priority will be used. - priority: number, - grammarScopes: Array, - getDefinition: ( - editor: TextEditor, - position: atom$Point, - ) => Promise, -}; - -export type DefinitionPreviewProvider = { - getDefinitionPreview( - definition: Definition, - ): Promise, -}; +'use strict'; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-definitions/spec/DefinitionHyperclick-spec.js b/modules/atom-ide-ui/pkg/atom-ide-definitions/spec/DefinitionHyperclick-spec.js deleted file mode 100644 index 613ad65e..00000000 --- a/modules/atom-ide-ui/pkg/atom-ide-definitions/spec/DefinitionHyperclick-spec.js +++ /dev/null @@ -1,212 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type { - HyperclickProvider, - HyperclickSuggestion, -} from '../../hyperclick/lib/types'; -import type {DefinitionProvider} from '../lib/types'; - -import {Point, Range, TextEditor} from 'atom'; -import invariant from 'assert'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; - -describe('DefinitionHyperclick', () => { - let provider: ?HyperclickProvider; - const definitionProvider: DefinitionProvider = { - priority: 20, - name: '', - grammarScopes: ['text.plain.null-grammar'], - getDefinition: () => Promise.resolve(null), - }; - let editor: TextEditor; - const position = new Point(0, 0); - let goToLocation; - let disposables; - - beforeEach(() => { - atom.packages.activatePackage('atom-ide-definitions'); - editor = new TextEditor(); - - goToLocation = spyOn( - require('nuclide-commons-atom/go-to-location'), - 'goToLocation', - ); - - disposables = new UniversalDisposable( - atom.packages.serviceHub.provide( - 'definitions', - '0.1.0', - definitionProvider, - ), - atom.packages.serviceHub.consume('hyperclick', '0.1.0', x => { - provider = x; - }), - ); - }); - - afterEach(() => { - disposables.dispose(); - }); - - it('no definition service', () => { - waitsForPromise(async () => { - spyOn(editor, 'getGrammar').andReturn({scopeName: 'blah'}); - invariant(provider != null); - invariant(provider.getSuggestion != null); - const result = await provider.getSuggestion(editor, position); - expect(result).toBe(null); - }); - }); - - it('no definition', () => { - waitsForPromise(async () => { - const spy = spyOn(definitionProvider, 'getDefinition').andReturn(null); - invariant(provider != null); - invariant(provider.getSuggestion != null); - const result = await provider.getSuggestion(editor, position); - - expect(result).toBe(null); - expect(spy).toHaveBeenCalledWith(editor, position); - }); - }); - - it('definition - single', () => { - waitsForPromise(async () => { - const definition = { - queryRange: [new Range(new Point(1, 1), new Point(1, 5))], - definitions: [ - { - path: 'path1', - position: new Point(1, 2), - range: null, - id: 'symbol-name', - name: null, - projectRoot: null, - }, - ], - }; - const spy = spyOn(definitionProvider, 'getDefinition').andReturn( - Promise.resolve(definition), - ); - - invariant(provider != null); - invariant(provider.getSuggestion != null); - const result = await provider.getSuggestion(editor, position); - - invariant(result != null); - expect(result.range).toEqual(definition.queryRange); - expect(spy).toHaveBeenCalledWith(editor, position); - expect(goToLocation).not.toHaveBeenCalled(); - - invariant(result != null); - invariant(result.callback != null); - invariant(typeof result.callback === 'function'); - result.callback(); - expect(goToLocation).toHaveBeenCalledWith('path1', 1, 2); - }); - }); - - it('definition - multiple', () => { - waitsForPromise(async () => { - const defs = { - queryRange: [new Range(new Point(1, 1), new Point(1, 5))], - definitions: [ - { - path: '/a/b/path1', - position: new Point(1, 2), - range: null, - id: 'symbol-name', - name: 'd1', - projectRoot: '/a', - }, - { - path: '/a/b/path2', - position: new Point(3, 4), - range: null, - id: 'symbol-name2', - name: 'd2', - projectRoot: '/a', - }, - { - path: '/a/b/path3', - position: new Point(3, 4), - range: null, - id: 'symbol-without-name', - projectRoot: '/a', - }, - ], - }; - const spy = spyOn(definitionProvider, 'getDefinition').andReturn( - Promise.resolve(defs), - ); - - invariant(provider != null); - invariant(provider.getSuggestion != null); - const result: ?HyperclickSuggestion = await provider.getSuggestion( - editor, - position, - ); - - invariant(result != null); - expect(result.range).toEqual(defs.queryRange); - expect(spy).toHaveBeenCalledWith(editor, position); - expect(goToLocation).not.toHaveBeenCalled(); - const callbacks: Array<{ - title: string, - callback: () => mixed, - }> = (result.callback: any); - - expect(callbacks.length).toBe(3); - expect(callbacks[0].title).toBe('d1 (b/path1)'); - expect(typeof callbacks[0].callback).toBe('function'); - expect(callbacks[1].title).toBe('d2 (b/path2)'); - expect(typeof callbacks[1].callback).toBe('function'); - expect(callbacks[2].title).toBe('b/path3:4'); - expect(typeof callbacks[2].callback).toBe('function'); - - callbacks[1].callback(); - expect(goToLocation).toHaveBeenCalledWith('/a/b/path2', 3, 4); - }); - }); - - it('falls back to lower-priority providers', () => { - waitsForPromise(async () => { - const def = { - queryRange: [new Range(new Point(1, 1), new Point(1, 5))], - definitions: [ - { - path: 'path1', - position: new Point(1, 2), - range: null, - id: 'symbol-name', - name: null, - projectRoot: null, - }, - ], - }; - const newProvider = { - priority: 10, - name: '', - grammarScopes: ['text.plain.null-grammar'], - getDefinition: () => Promise.resolve(def), - }; - atom.packages.serviceHub.provide('definitions', '0.1.0', newProvider); - invariant(provider != null); - invariant(provider.getSuggestion != null); - const result = await provider.getSuggestion(editor, position); - expect(result).not.toBe(null); - invariant(result != null); - expect(result.range).toEqual(def.queryRange); - }); - }); -}); diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/DiagnosticsSorter.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/DiagnosticsSorter.js index a60d3af9..77387664 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/DiagnosticsSorter.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/DiagnosticsSorter.js @@ -1,3 +1,14 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.sortDiagnostics = sortDiagnostics; + + +/* + * Sorts the diagnostics according to given column and sort direction + */ /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,40 +17,27 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {Row} from 'nuclide-commons-ui/Table'; -import type {DisplayDiagnostic} from './ui/DiagnosticsTable'; - -/* - * Sorts the diagnostics according to given column and sort direction - */ -export function sortDiagnostics( - diagnostics: Array>, - sortedColumnName: ?string, - sortDescending: boolean, -): Array> { +function sortDiagnostics(diagnostics, sortedColumnName, sortDescending) { if (sortedColumnName == null) { return diagnostics; } - const cmp: any = sortedColumnName === 'range' ? _cmpNumber : _cmpString; - const getter = (displayDiagnostic: {+data: DisplayDiagnostic}) => - sortedColumnName === 'description' - ? displayDiagnostic.data.description.text - : displayDiagnostic.data[sortedColumnName]; + const cmp = sortedColumnName === 'range' ? _cmpNumber : _cmpString; + const getter = displayDiagnostic => sortedColumnName === 'description' ? displayDiagnostic.data.description.text : displayDiagnostic.data[sortedColumnName]; return [...diagnostics].sort((a, b) => { return cmp(getter(a), getter(b), !sortDescending); }); } -function _cmpNumber(a: number, b: number, isAsc: boolean): number { +function _cmpNumber(a, b, isAsc) { const cmp = a - b; return isAsc ? cmp : -cmp; } -function _cmpString(a: string, b: string, isAsc: boolean): number { +function _cmpString(a, b, isAsc) { const cmp = a.toLowerCase().localeCompare(b.toLowerCase()); return isAsc ? cmp : -cmp; -} +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/DiagnosticsViewModel.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/DiagnosticsViewModel.js index 4e912d3d..102c252c 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/DiagnosticsViewModel.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/DiagnosticsViewModel.js @@ -1,136 +1,152 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {IconName} from 'nuclide-commons-ui/Icon'; -import type {Props} from './ui/DiagnosticsView'; -import type {FilterType, GlobalViewState} from './types'; -import type {DiagnosticMessage} from '../../atom-ide-diagnostics/lib/types'; -import type {RegExpFilterChange} from 'nuclide-commons-ui/RegExpFilter'; - -import {goToLocation} from 'nuclide-commons-atom/go-to-location'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import React from 'react'; -import DiagnosticsUi from './ui/DiagnosticsUi'; -import analytics from 'nuclide-commons-atom/analytics'; -import Model from 'nuclide-commons/Model'; -import observePaneItemVisibility from 'nuclide-commons-atom/observePaneItemVisibility'; -import {renderReactRoot} from 'nuclide-commons-ui/renderReactRoot'; -import {toggle} from 'nuclide-commons/observable'; -import {bindObservableAsProps} from 'nuclide-commons-ui/bindObservableAsProps'; -import {Observable} from 'rxjs'; -import {getFilterPattern} from 'nuclide-commons-ui/RegExpFilter'; - -type SerializedDiagnosticsViewModel = { - deserializer: 'atom-ide-ui.DiagnosticsViewModel', - state: { - hiddenTypes: Array, - }, -}; +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DiagnosticsViewModel = exports.WORKSPACE_VIEW_URI = undefined; + +var _goToLocation; + +function _load_goToLocation() { + return _goToLocation = require('nuclide-commons-atom/go-to-location'); +} + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _react = _interopRequireDefault(require('react')); + +var _DiagnosticsUi; + +function _load_DiagnosticsUi() { + return _DiagnosticsUi = _interopRequireDefault(require('./ui/DiagnosticsUi')); +} + +var _analytics; + +function _load_analytics() { + return _analytics = _interopRequireDefault(require('nuclide-commons-atom/analytics')); +} + +var _Model; + +function _load_Model() { + return _Model = _interopRequireDefault(require('nuclide-commons/Model')); +} + +var _observePaneItemVisibility; + +function _load_observePaneItemVisibility() { + return _observePaneItemVisibility = _interopRequireDefault(require('nuclide-commons-atom/observePaneItemVisibility')); +} + +var _renderReactRoot; + +function _load_renderReactRoot() { + return _renderReactRoot = require('nuclide-commons-ui/renderReactRoot'); +} + +var _observable; + +function _load_observable() { + return _observable = require('nuclide-commons/observable'); +} + +var _bindObservableAsProps; + +function _load_bindObservableAsProps() { + return _bindObservableAsProps = require('nuclide-commons-ui/bindObservableAsProps'); +} + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _RegExpFilter; + +function _load_RegExpFilter() { + return _RegExpFilter = require('nuclide-commons-ui/RegExpFilter'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -type State = {| - hiddenTypes: Set, - selectedMessage: ?DiagnosticMessage, - textFilter: {| - text: string, - isRegExp: boolean, - invalid: boolean, - pattern: ?RegExp, - |}, -|}; - -export const WORKSPACE_VIEW_URI = 'atom://nuclide/diagnostics'; - -export class DiagnosticsViewModel { - _element: ?HTMLElement; - _model: Model; - _props: Observable; - _disposables: IDisposable; - - constructor(globalStates: Observable) { - const {pattern, invalid} = getFilterPattern('', false); - this._model = new Model({ +const WORKSPACE_VIEW_URI = exports.WORKSPACE_VIEW_URI = 'atom://nuclide/diagnostics'; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +class DiagnosticsViewModel { + + constructor(globalStates) { + _initialiseProps.call(this); + + const { pattern, invalid } = (0, (_RegExpFilter || _load_RegExpFilter()).getFilterPattern)('', false); + this._model = new (_Model || _load_Model()).default({ // TODO: Get this from constructor/serialization. hiddenTypes: new Set(), - textFilter: {text: '', isRegExp: false, pattern, invalid}, - selectedMessage: null, + textFilter: { text: '', isRegExp: false, pattern, invalid }, + selectedMessage: null }); - const visibility = observePaneItemVisibility(this).distinctUntilChanged(); - this._disposables = new UniversalDisposable( - visibility - .debounceTime(1000) - .distinctUntilChanged() - .filter(Boolean) - .subscribe(() => { - analytics.track('diagnostics-show-table'); - }), - ); + const visibility = (0, (_observePaneItemVisibility || _load_observePaneItemVisibility()).default)(this).distinctUntilChanged(); + this._disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(visibility.debounceTime(1000).distinctUntilChanged().filter(Boolean).subscribe(() => { + (_analytics || _load_analytics()).default.track('diagnostics-show-table'); + })); // Combine the state that's shared between instances, the state that's unique to this instance, // and unchanging callbacks, to get the props for our component. - const props = Observable.combineLatest( - globalStates, - this._model.toObservable(), - (globalState, instanceState) => ({ - ...globalState, - ...instanceState, - diagnostics: this._filterDiagnostics( - globalState.diagnostics, - instanceState.textFilter.pattern, - instanceState.hiddenTypes, - ), - onTypeFilterChange: this._handleTypeFilterChange, - onTextFilterChange: this._handleTextFilterChange, - gotoMessageLocation: this._gotoMessageLocation, - }), - ); + const props = _rxjsBundlesRxMinJs.Observable.combineLatest(globalStates, this._model.toObservable(), (globalState, instanceState) => Object.assign({}, globalState, instanceState, { + diagnostics: this._filterDiagnostics(globalState.diagnostics, instanceState.textFilter.pattern, instanceState.hiddenTypes), + onTypeFilterChange: this._handleTypeFilterChange, + onTextFilterChange: this._handleTextFilterChange, + gotoMessageLocation: this._gotoMessageLocation + })); // "Mute" the props stream when the view is hidden so we don't do unnecessary updates. - this._props = toggle(props, visibility); + this._props = (0, (_observable || _load_observable()).toggle)(props, visibility); } - destroy(): void { + destroy() { this._disposables.dispose(); } - getTitle(): string { + getTitle() { return 'Diagnostics'; } - getIconName(): IconName { + getIconName() { return 'law'; } - getURI(): string { + getURI() { return WORKSPACE_VIEW_URI; } - getDefaultLocation(): string { + getDefaultLocation() { return 'bottom'; } - serialize(): SerializedDiagnosticsViewModel { - const {hiddenTypes} = this._model.state; + serialize() { + const { hiddenTypes } = this._model.state; return { deserializer: 'atom-ide-ui.DiagnosticsViewModel', state: { - hiddenTypes: [...hiddenTypes], - }, + hiddenTypes: [...hiddenTypes] + } }; } - getElement(): HTMLElement { + getElement() { if (this._element == null) { - const Component = bindObservableAsProps(this._props, DiagnosticsUi); - const element = renderReactRoot(); + const Component = (0, (_bindObservableAsProps || _load_bindObservableAsProps()).bindObservableAsProps)(this._props, (_DiagnosticsUi || _load_DiagnosticsUi()).default); + const element = (0, (_renderReactRoot || _load_renderReactRoot()).renderReactRoot)(_react.default.createElement(Component, null)); element.classList.add('diagnostics-ui'); this._element = element; } @@ -140,8 +156,28 @@ export class DiagnosticsViewModel { /** * Toggle the filter. */ - _handleTypeFilterChange = (type: FilterType): void => { - const {hiddenTypes} = this._model.state; + + + // TODO: Memoize this. + _filterDiagnostics(diagnostics, pattern, hiddenTypes) { + return diagnostics.filter(message => { + if (hiddenTypes.has(getMessageFilterType(message))) { + return false; + } + if (pattern == null) { + return true; + } + return message.text != null && pattern.test(message.text) || message.html != null && pattern.test(message.html) || pattern.test(message.providerName) || message.scope === 'file' && pattern.test(message.filePath); + }); + } + +} + +exports.DiagnosticsViewModel = DiagnosticsViewModel; + +var _initialiseProps = function () { + this._handleTypeFilterChange = type => { + const { hiddenTypes } = this._model.state; const hidden = hiddenTypes.has(type); const nextHiddenTypes = new Set(hiddenTypes); if (hidden) { @@ -149,47 +185,25 @@ export class DiagnosticsViewModel { } else { nextHiddenTypes.add(type); } - this._model.setState({hiddenTypes: nextHiddenTypes}); + this._model.setState({ hiddenTypes: nextHiddenTypes }); }; - _handleTextFilterChange = (value: RegExpFilterChange): void => { - const {text, isRegExp} = value; + this._handleTextFilterChange = value => { + const { text, isRegExp } = value; // TODO: Fuzzy if !isRegExp? - const {invalid, pattern} = getFilterPattern(text, isRegExp); + const { invalid, pattern } = (0, (_RegExpFilter || _load_RegExpFilter()).getFilterPattern)(text, isRegExp); this._model.setState({ - textFilter: {text, isRegExp, invalid, pattern}, + textFilter: { text, isRegExp, invalid, pattern } }); }; - // TODO: Memoize this. - _filterDiagnostics( - diagnostics: Array, - pattern: ?RegExp, - hiddenTypes: Set, - ): Array { - return diagnostics.filter(message => { - if (hiddenTypes.has(getMessageFilterType(message))) { - return false; - } - if (pattern == null) { - return true; - } - return ( - (message.text != null && pattern.test(message.text)) || - (message.html != null && pattern.test(message.html)) || - pattern.test(message.providerName) || - (message.scope === 'file' && pattern.test(message.filePath)) - ); - }); - } - - _gotoMessageLocation = (message: DiagnosticMessage): void => { - this._model.setState({selectedMessage: message}); + this._gotoMessageLocation = message => { + this._model.setState({ selectedMessage: message }); goToDiagnosticLocation(message); }; -} +}; -function getMessageFilterType(message: DiagnosticMessage): FilterType { +function getMessageFilterType(message) { switch (message.kind) { case 'lint': case null: @@ -212,17 +226,17 @@ function getMessageFilterType(message: DiagnosticMessage): FilterType { } } -function goToDiagnosticLocation(message: DiagnosticMessage): void { +function goToDiagnosticLocation(message) { if (message.scope !== 'file' || message.filePath == null) { return; } - analytics.track('diagnostics-panel-goto-location'); + (_analytics || _load_analytics()).default.track('diagnostics-panel-goto-location'); const uri = message.filePath; // If initialLine is N, Atom will navigate to line N+1. // Flow sometimes reports a row of -1, so this ensures the line is at least one. const line = Math.max(message.range ? message.range.start.row : 0, 0); const column = 0; - goToLocation(uri, line, column); -} + (0, (_goToLocation || _load_goToLocation()).goToLocation)(uri, line, column); +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/KeyboardShortcuts.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/KeyboardShortcuts.js index 1ce3c041..b34a5e26 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/KeyboardShortcuts.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/KeyboardShortcuts.js @@ -1,93 +1,56 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type { - DiagnosticTrace, - FileDiagnosticMessage, - DiagnosticUpdater, -} from '../../atom-ide-diagnostics/lib/types'; - -import invariant from 'assert'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import {goToLocation} from 'nuclide-commons-atom/go-to-location'; -import {observableFromSubscribeFunction} from 'nuclide-commons/event'; +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _goToLocation; + +function _load_goToLocation() { + return _goToLocation = require('nuclide-commons-atom/go-to-location'); +} + +var _event; + +function _load_event() { + return _event = require('nuclide-commons/event'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // TODO(peterhal): The current index should really live in the DiagnosticStore. -export default class KeyboardShortcuts { - _subscriptions: UniversalDisposable; - _diagnostics: Array; - _index: ?number; - _traceIndex: ?number; +class KeyboardShortcuts { - constructor(diagnosticUpdater: DiagnosticUpdater) { + constructor(diagnosticUpdater) { this._index = null; this._diagnostics = []; - this._subscriptions = new UniversalDisposable(); + this._subscriptions = new (_UniversalDisposable || _load_UniversalDisposable()).default(); const first = () => this.setIndex(0); const last = () => this.setIndex(this._diagnostics.length - 1); - this._subscriptions.add( - observableFromSubscribeFunction( - diagnosticUpdater.observeMessages, - ).subscribe(diagnostics => { - this._diagnostics = (diagnostics.filter( - diagnostic => diagnostic.scope === 'file', - ): any); - this._index = null; - this._traceIndex = null; - }), - atom.commands.add( - 'atom-workspace', - 'diagnostics:go-to-first-diagnostic', - first, - ), - atom.commands.add( - 'atom-workspace', - 'diagnostics:go-to-last-diagnostic', - last, - ), - atom.commands.add( - 'atom-workspace', - 'diagnostics:go-to-next-diagnostic', - () => { - this._index == null ? first() : this.setIndex(this._index + 1); - }, - ), - atom.commands.add( - 'atom-workspace', - 'diagnostics:go-to-previous-diagnostic', - () => { - this._index == null ? last() : this.setIndex(this._index - 1); - }, - ), - atom.commands.add( - 'atom-workspace', - 'diagnostics:go-to-next-diagnostic-trace', - () => { - this.nextTrace(); - }, - ), - atom.commands.add( - 'atom-workspace', - 'diagnostics:go-to-previous-diagnostic-trace', - () => { - this.previousTrace(); - }, - ), - ); + this._subscriptions.add((0, (_event || _load_event()).observableFromSubscribeFunction)(diagnosticUpdater.observeMessages).subscribe(diagnostics => { + this._diagnostics = diagnostics.filter(diagnostic => diagnostic.scope === 'file'); + this._index = null; + this._traceIndex = null; + }), atom.commands.add('atom-workspace', 'diagnostics:go-to-first-diagnostic', first), atom.commands.add('atom-workspace', 'diagnostics:go-to-last-diagnostic', last), atom.commands.add('atom-workspace', 'diagnostics:go-to-next-diagnostic', () => { + this._index == null ? first() : this.setIndex(this._index + 1); + }), atom.commands.add('atom-workspace', 'diagnostics:go-to-previous-diagnostic', () => { + this._index == null ? last() : this.setIndex(this._index - 1); + }), atom.commands.add('atom-workspace', 'diagnostics:go-to-next-diagnostic-trace', () => { + this.nextTrace(); + }), atom.commands.add('atom-workspace', 'diagnostics:go-to-previous-diagnostic-trace', () => { + this.previousTrace(); + })); } - setIndex(index: number): void { + setIndex(index) { this._traceIndex = null; if (this._diagnostics.length === 0) { this._index = null; @@ -97,19 +60,25 @@ export default class KeyboardShortcuts { this.gotoCurrentIndex(); } - gotoCurrentIndex(): void { - invariant(this._index != null); - invariant(this._traceIndex == null); + gotoCurrentIndex() { + if (!(this._index != null)) { + throw new Error('Invariant violation: "this._index != null"'); + } + + if (!(this._traceIndex == null)) { + throw new Error('Invariant violation: "this._traceIndex == null"'); + } + const diagnostic = this._diagnostics[this._index]; const range = diagnostic.range; if (range == null) { - goToLocation(diagnostic.filePath); + (0, (_goToLocation || _load_goToLocation()).goToLocation)(diagnostic.filePath); } else { - goToLocation(diagnostic.filePath, range.start.row, range.start.column); + (0, (_goToLocation || _load_goToLocation()).goToLocation)(diagnostic.filePath, range.start.row, range.start.column); } } - nextTrace(): void { + nextTrace() { const traces = this.currentTraces(); if (traces == null) { return; @@ -125,13 +94,12 @@ export default class KeyboardShortcuts { this.gotoCurrentIndex(); } - previousTrace(): void { + previousTrace() { const traces = this.currentTraces(); if (traces == null) { return; } - let candidateTrace = - this._traceIndex == null ? traces.length - 1 : this._traceIndex - 1; + let candidateTrace = this._traceIndex == null ? traces.length - 1 : this._traceIndex - 1; while (candidateTrace >= 0) { if (this.trySetCurrentTrace(traces, candidateTrace)) { return; @@ -142,7 +110,7 @@ export default class KeyboardShortcuts { this.gotoCurrentIndex(); } - currentTraces(): ?Array { + currentTraces() { if (this._index == null) { return null; } @@ -151,24 +119,28 @@ export default class KeyboardShortcuts { } // TODO: Should filter out traces whose location matches the main diagnostic's location? - trySetCurrentTrace( - traces: Array, - traceIndex: number, - ): boolean { + trySetCurrentTrace(traces, traceIndex) { const trace = traces[traceIndex]; if (trace.filePath != null && trace.range != null) { this._traceIndex = traceIndex; - goToLocation( - trace.filePath, - trace.range.start.row, - trace.range.start.column, - ); + (0, (_goToLocation || _load_goToLocation()).goToLocation)(trace.filePath, trace.range.start.row, trace.range.start.column); return true; } return false; } - dispose(): void { + dispose() { this._subscriptions.dispose(); } } +exports.default = KeyboardShortcuts; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/getDiagnosticDatatip.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/getDiagnosticDatatip.js index ffbf7d49..afad0dc0 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/getDiagnosticDatatip.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/getDiagnosticDatatip.js @@ -1,63 +1,85 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {Datatip} from '../../atom-ide-datatip/lib/types'; -import type { - DiagnosticUpdater, - FileDiagnosticMessage, -} from '../../atom-ide-diagnostics/lib/types'; - -import invariant from 'assert'; -import * as React from 'react'; -import {observableFromSubscribeFunction} from 'nuclide-commons/event'; -import {goToLocation} from 'nuclide-commons-atom/go-to-location'; -import {bindObservableAsProps} from 'nuclide-commons-ui/bindObservableAsProps'; -import {DiagnosticsPopup} from './ui/DiagnosticsPopup'; - -function makeDatatipComponent( - messages: Array, - diagnosticUpdater: DiagnosticUpdater, -): React.ComponentType<*> { - const fixer = message => diagnosticUpdater.applyFix(message); - return bindObservableAsProps( - observableFromSubscribeFunction(cb => - diagnosticUpdater.observeCodeActionsForMessage(cb), - ).map(codeActionsForMessage => ({ - messages, - fixer, - goToLocation, - codeActionsForMessage, - })), - DiagnosticsPopup, - ); +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + +var _react = _interopRequireWildcard(require('react')); + +var _event; + +function _load_event() { + return _event = require('nuclide-commons/event'); +} + +var _goToLocation; + +function _load_goToLocation() { + return _goToLocation = require('nuclide-commons-atom/go-to-location'); +} + +var _bindObservableAsProps; + +function _load_bindObservableAsProps() { + return _bindObservableAsProps = require('nuclide-commons-ui/bindObservableAsProps'); } -export default (async function getDiagnosticDatatip( - editor: TextEditor, - position: atom$Point, - messagesAtPosition: Array, - diagnosticUpdater: DiagnosticUpdater, -): Promise { - let range = null; - for (const message of messagesAtPosition) { - if (message.range != null) { - range = range == null ? message.range : message.range.union(range); +var _DiagnosticsPopup; + +function _load_DiagnosticsPopup() { + return _DiagnosticsPopup = require('./ui/DiagnosticsPopup'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function makeDatatipComponent(messages, diagnosticUpdater) { + const fixer = message => diagnosticUpdater.applyFix(message); + return (0, (_bindObservableAsProps || _load_bindObservableAsProps()).bindObservableAsProps)((0, (_event || _load_event()).observableFromSubscribeFunction)(cb => diagnosticUpdater.observeCodeActionsForMessage(cb)).map(codeActionsForMessage => ({ + messages, + fixer, + goToLocation: (_goToLocation || _load_goToLocation()).goToLocation, + codeActionsForMessage + })), (_DiagnosticsPopup || _load_DiagnosticsPopup()).DiagnosticsPopup); +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +exports.default = (() => { + var _ref = (0, _asyncToGenerator.default)(function* (editor, position, messagesAtPosition, diagnosticUpdater) { + let range = null; + for (const message of messagesAtPosition) { + if (message.range != null) { + range = range == null ? message.range : message.range.union(range); + } } + diagnosticUpdater.fetchCodeActions(editor, messagesAtPosition); + + if (!(range != null)) { + throw new Error('Invariant violation: "range != null"'); + } + + return { + component: makeDatatipComponent(messagesAtPosition, diagnosticUpdater), + pinnable: false, + range + }; + }); + + function getDiagnosticDatatip(_x, _x2, _x3, _x4) { + return _ref.apply(this, arguments); } - diagnosticUpdater.fetchCodeActions(editor, messagesAtPosition); - invariant(range != null); - return { - component: makeDatatipComponent(messagesAtPosition, diagnosticUpdater), - pinnable: false, - range, - }; -}); + + return getDiagnosticDatatip; +})(); \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/gutter.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/gutter.js index 520163ae..a3d63f77 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/gutter.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/gutter.js @@ -1,3 +1,62 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.applyUpdateToEditor = applyUpdateToEditor; + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _atom = require('atom'); + +var _react = _interopRequireWildcard(require('react')); + +var _reactDom = _interopRequireDefault(require('react-dom')); + +var _event; + +function _load_event() { + return _event = require('nuclide-commons/event'); +} + +var _goToLocation; + +function _load_goToLocation() { + return _goToLocation = require('nuclide-commons-atom/go-to-location'); +} + +var _range; + +function _load_range() { + return _range = require('nuclide-commons-atom/range'); +} + +var _analytics; + +function _load_analytics() { + return _analytics = _interopRequireDefault(require('nuclide-commons-atom/analytics')); +} + +var _bindObservableAsProps; + +function _load_bindObservableAsProps() { + return _bindObservableAsProps = require('nuclide-commons-ui/bindObservableAsProps'); +} + +var _DiagnosticsPopup; + +function _load_DiagnosticsPopup() { + return _DiagnosticsPopup = require('./ui/DiagnosticsPopup'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,29 +65,10 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type { - DiagnosticUpdater, - FileDiagnosticMessage, - FileDiagnosticMessages, -} from '../../atom-ide-diagnostics/lib/types'; -import type {NuclideUri} from 'nuclide-commons/nuclideUri'; -import classnames from 'classnames'; - -import {Range} from 'atom'; -import invariant from 'assert'; -import * as React from 'react'; -import ReactDOM from 'react-dom'; -import {observableFromSubscribeFunction} from 'nuclide-commons/event'; -import {goToLocation as atomGoToLocation} from 'nuclide-commons-atom/go-to-location'; -import {wordAtPosition} from 'nuclide-commons-atom/range'; -import analytics from 'nuclide-commons-atom/analytics'; -import {bindObservableAsProps} from 'nuclide-commons-ui/bindObservableAsProps'; -import {DiagnosticsPopup} from './ui/DiagnosticsPopup'; - const GUTTER_ID = 'diagnostics-gutter'; // Needs to be the same as glyph-height in gutter.atom-text-editor.less. @@ -51,23 +91,19 @@ const HIGHLIGHT_CSS = 'diagnostics-gutter-ui-highlight'; const HIGHLIGHT_CSS_LEVELS = { Error: 'diagnostics-gutter-ui-highlight-error', Warning: 'diagnostics-gutter-ui-highlight-warning', - Info: 'diagnostics-gutter-ui-highlight-info', + Info: 'diagnostics-gutter-ui-highlight-info' }; const GUTTER_CSS_LEVELS = { Error: 'diagnostics-gutter-ui-gutter-error', Warning: 'diagnostics-gutter-ui-gutter-warning', - Info: 'diagnostics-gutter-ui-gutter-info', + Info: 'diagnostics-gutter-ui-gutter-info' }; -const editorToMarkers: WeakMap> = new WeakMap(); -const itemToEditor: WeakMap = new WeakMap(); +const editorToMarkers = new WeakMap(); +const itemToEditor = new WeakMap(); -export function applyUpdateToEditor( - editor: TextEditor, - update: FileDiagnosticMessages, - diagnosticUpdater: DiagnosticUpdater, -): void { +function applyUpdateToEditor(editor, update, diagnosticUpdater) { let gutter = editor.gutterWithName(GUTTER_ID); if (!gutter) { // TODO(jessicalin): Determine an appropriate priority so that the gutter: @@ -81,7 +117,7 @@ export function applyUpdateToEditor( name: GUTTER_ID, visible: false, // Priority is -200 by default and 0 is the line number - priority: -1000, + priority: -1000 }); } @@ -99,8 +135,8 @@ export function applyUpdateToEditor( markers = new Set(); } - const rowToMessage: Map> = new Map(); - function addMessageForRow(message: FileDiagnosticMessage, row: number) { + const rowToMessage = new Map(); + function addMessageForRow(message, row) { let messages = rowToMessage.get(row); if (!messages) { messages = []; @@ -110,16 +146,10 @@ export function applyUpdateToEditor( } for (const message of update.messages) { - const wordRange = - message.range != null && message.range.isEmpty() - ? wordAtPosition(editor, message.range.start) - : null; + const wordRange = message.range != null && message.range.isEmpty() ? (0, (_range || _load_range()).wordAtPosition)(editor, message.range.start) : null; const range = wordRange != null ? wordRange.range : message.range; - const highlightCssClass = classnames( - HIGHLIGHT_CSS, - HIGHLIGHT_CSS_LEVELS[message.type], - ); + const highlightCssClass = (0, (_classnames || _load_classnames()).default)(HIGHLIGHT_CSS, HIGHLIGHT_CSS_LEVELS[message.type]); let highlightMarker; if (range) { @@ -138,9 +168,7 @@ export function applyUpdateToEditor( for (let line = range.start.row; line <= range.end.row; line++) { let start; let end; - const lineText = editor.getTextInBufferRange( - new Range([line, 0], [line + 1, 0]), - ); + const lineText = editor.getTextInBufferRange(new _atom.Range([line, 0], [line + 1, 0])); if (line === range.start.row) { start = range.start.column; @@ -157,12 +185,10 @@ export function applyUpdateToEditor( end = lineText.length; } - highlightMarker = editor.markBufferRange( - new Range([line, start], [line, end]), - ); + highlightMarker = editor.markBufferRange(new _atom.Range([line, start], [line, end])); editor.decorateMarker(highlightMarker, { type: 'highlight', - class: highlightCssClass, + class: highlightCssClass }); markers.add(highlightMarker); } @@ -176,20 +202,14 @@ export function applyUpdateToEditor( // Show the highest priority marker (note the ordering of GUTTER_CSS). const messageTypes = new Set(); messages.forEach(msg => messageTypes.add(msg.type)); - const firstType = Object.keys(GUTTER_CSS_LEVELS).find(type => - messageTypes.has(type), - ); + const firstType = Object.keys(GUTTER_CSS_LEVELS).find(type => messageTypes.has(type)); const gutterMarkerCssClass = GUTTER_CSS_LEVELS[firstType || 'Error']; // This marker adds some UI to the gutter. - const {item, dispose} = createGutterItem( - messages, - gutterMarkerCssClass, - diagnosticUpdater, - ); + const { item, dispose } = createGutterItem(messages, gutterMarkerCssClass, diagnosticUpdater); itemToEditor.set(item, editor); const gutterMarker = editor.markBufferPosition([row, 0]); - gutter.decorateMarker(gutterMarker, {item}); + gutter.decorateMarker(gutterMarker, { item }); gutterMarker.onDidDestroy(dispose); markers.add(gutterMarker); } @@ -203,11 +223,7 @@ export function applyUpdateToEditor( } } -function createGutterItem( - messages: Array, - gutterMarkerCssClass: string, - diagnosticUpdater: DiagnosticUpdater, -): {item: HTMLElement, dispose: () => void} { +function createGutterItem(messages, gutterMarkerCssClass, diagnosticUpdater) { const item = document.createElement('a'); item.className = gutterMarkerCssClass; let popupElement = null; @@ -221,8 +237,12 @@ function createGutterItem( }; const dispose = () => { if (popupElement) { - ReactDOM.unmountComponentAtNode(popupElement); - invariant(popupElement.parentNode != null); + _reactDom.default.unmountComponentAtNode(popupElement); + + if (!(popupElement.parentNode != null)) { + throw new Error('Invariant violation: "popupElement.parentNode != null"'); + } + popupElement.parentNode.removeChild(popupElement); popupElement = null; } @@ -232,112 +252,104 @@ function createGutterItem( } clearDisposeTimeout(); }; - const goToLocation = (path: string, line: number) => { + const goToLocation = (path, line) => { // Before we jump to the location, we want to close the popup. dispose(); const column = 0; - atomGoToLocation(path, line, column); + (0, (_goToLocation || _load_goToLocation()).goToLocation)(path, line, column); }; - item.addEventListener('mouseenter', (event: MouseEvent) => { + item.addEventListener('mouseenter', event => { // If there was somehow another popup for this gutter item, dispose it. This can happen if the // user manages to scroll and escape disposal. dispose(); - popupElement = showPopupFor( - messages, - item, - goToLocation, - diagnosticUpdater, - ); + popupElement = showPopupFor(messages, item, goToLocation, diagnosticUpdater); popupElement.addEventListener('mouseleave', dispose); popupElement.addEventListener('mouseenter', clearDisposeTimeout); // This makes sure that the popup disappears when you ctrl+tab to switch tabs. paneItemSubscription = atom.workspace.onDidChangeActivePaneItem(dispose); }); - item.addEventListener('mouseleave', (event: MouseEvent) => { + item.addEventListener('mouseleave', event => { // When the popup is shown, we want to dispose it if the user manages to move the cursor off of // the gutter glyph without moving it onto the popup. Even though the popup appears above (as in // Z-index above) the gutter glyph, if you move the cursor such that it is only above the glyph // for one frame you can cause the popup to appear without the mouse ever entering it. disposeTimeout = setTimeout(dispose, POPUP_DISPOSE_TIMEOUT); }); - return {item, dispose}; + return { item, dispose }; } /** * Shows a popup for the diagnostic just below the specified item. */ -function showPopupFor( - messages: Array, - item: HTMLElement, - goToLocation: (filePath: NuclideUri, line: number) => mixed, - diagnosticUpdater: DiagnosticUpdater, -): HTMLElement { +function showPopupFor(messages, item, goToLocation, diagnosticUpdater) { // The popup will be an absolutely positioned child element of so that it appears // on top of everything. - const workspaceElement = atom.views.getView((atom.workspace: Object)); + const workspaceElement = atom.views.getView(atom.workspace); const hostElement = document.createElement('div'); hostElement.classList.add('diagnostics-gutter-popup'); // $FlowFixMe check parentNode for null workspaceElement.parentNode.appendChild(hostElement); // Move it down vertically so it does not end up under the mouse pointer. - const {top, left} = item.getBoundingClientRect(); + const { top, left } = item.getBoundingClientRect(); const trackedFixer = (...args) => { diagnosticUpdater.applyFix(...args); - analytics.track('diagnostics-gutter-autofix'); + (_analytics || _load_analytics()).default.track('diagnostics-gutter-autofix'); }; - const trackedGoToLocation = (filePath: NuclideUri, line: number) => { + const trackedGoToLocation = (filePath, line) => { goToLocation(filePath, line); - analytics.track('diagnostics-gutter-goto-location'); + (_analytics || _load_analytics()).default.track('diagnostics-gutter-goto-location'); }; const editor = itemToEditor.get(item); - invariant(editor != null); + + if (!(editor != null)) { + throw new Error('Invariant violation: "editor != null"'); + } + diagnosticUpdater.fetchCodeActions(editor, messages); - const BoundPopup = bindObservableAsProps( - observableFromSubscribeFunction(cb => - diagnosticUpdater.observeCodeActionsForMessage(cb), - ).map(codeActionsForMessage => ({ - style: {left, top, position: 'absolute'}, - messages, - fixer: trackedFixer, - goToLocation: trackedGoToLocation, - codeActionsForMessage, - })), - DiagnosticsPopup, - ); - ReactDOM.render(, hostElement); + const BoundPopup = (0, (_bindObservableAsProps || _load_bindObservableAsProps()).bindObservableAsProps)((0, (_event || _load_event()).observableFromSubscribeFunction)(cb => diagnosticUpdater.observeCodeActionsForMessage(cb)).map(codeActionsForMessage => ({ + style: { left, top, position: 'absolute' }, + messages, + fixer: trackedFixer, + goToLocation: trackedGoToLocation, + codeActionsForMessage + })), (_DiagnosticsPopup || _load_DiagnosticsPopup()).DiagnosticsPopup); + _reactDom.default.render(_react.createElement(BoundPopup, null), hostElement); // Check to see whether the popup is within the bounds of the TextEditor. If not, display it above // the glyph rather than below it. const editorElement = atom.views.getView(editor); const { top: editorTop, - height: editorHeight, + height: editorHeight } = editorElement.getBoundingClientRect(); - const {top: itemTop, height: itemHeight} = item.getBoundingClientRect(); + const { top: itemTop, height: itemHeight } = item.getBoundingClientRect(); const popupElement = hostElement.firstElementChild; - invariant(popupElement instanceof HTMLElement); + + if (!(popupElement instanceof HTMLElement)) { + throw new Error('Invariant violation: "popupElement instanceof HTMLElement"'); + } + const popupHeight = popupElement.clientHeight; if (itemTop + itemHeight + popupHeight > editorTop + editorHeight) { // Shift the popup back down by GLYPH_HEIGHT, so that the bottom padding overlaps with the // glyph. An additional 4 px is needed to make it look the same way it does when it shows up // below. I don't know why. - popupElement.style.top = - String(itemTop - popupHeight + GLYPH_HEIGHT + 4) + 'px'; + popupElement.style.top = String(itemTop - popupHeight + GLYPH_HEIGHT + 4) + 'px'; } try { return hostElement; } finally { messages.forEach(message => { - analytics.track('diagnostics-gutter-show-popup', { + (_analytics || _load_analytics()).default.track('diagnostics-gutter-show-popup', { 'diagnostics-provider': message.providerName, // flowlint-next-line sketchy-null-string:off - 'diagnostics-message': message.text || message.html || '', + 'diagnostics-message': message.text || message.html || '' }); }); } -} +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/main.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/main.js index 5de67782..814b6e75 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/main.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/main.js @@ -1,161 +1,208 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type { - DatatipProvider, - DatatipService, -} from '../../atom-ide-datatip/lib/types'; - -import type { - DiagnosticMessage, - FileDiagnosticMessage, - FileDiagnosticMessages, - DiagnosticUpdater, -} from '../../atom-ide-diagnostics/lib/types'; -import type {NuclideUri} from 'nuclide-commons/nuclideUri'; -import type {GlobalViewState} from './types'; - -import invariant from 'assert'; - -import analytics from 'nuclide-commons-atom/analytics'; - -import idx from 'idx'; -import KeyboardShortcuts from './KeyboardShortcuts'; -import Model from 'nuclide-commons/Model'; -import createPackage from 'nuclide-commons-atom/createPackage'; -import {observeTextEditors} from 'nuclide-commons-atom/text-editor'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import {observableFromSubscribeFunction} from 'nuclide-commons/event'; -import {DiagnosticsViewModel, WORKSPACE_VIEW_URI} from './DiagnosticsViewModel'; -import StatusBarTile from './ui/StatusBarTile'; -import {applyUpdateToEditor} from './gutter'; -import getDiagnosticDatatip from './getDiagnosticDatatip'; -import {compareMessagesByFile} from './paneUtils'; -import {goToLocation} from 'nuclide-commons-atom/go-to-location'; -import featureConfig from 'nuclide-commons-atom/feature-config'; -import {destroyItemWhere} from 'nuclide-commons-atom/destroyItemWhere'; -import {isValidTextEditor} from 'nuclide-commons-atom/text-editor'; -import {Observable} from 'rxjs'; -import showActionsMenu from './showActionsMenu'; -import showAtomLinterWarning from './showAtomLinterWarning'; - -const MAX_OPEN_ALL_FILES = 20; -const SHOW_TRACES_SETTING = 'atom-ide-diagnostics-ui.showDiagnosticTraces'; +'use strict'; + +var _analytics; + +function _load_analytics() { + return _analytics = _interopRequireDefault(require('nuclide-commons-atom/analytics')); +} + +var _idx; + +function _load_idx() { + return _idx = _interopRequireDefault(require('idx')); +} + +var _KeyboardShortcuts; + +function _load_KeyboardShortcuts() { + return _KeyboardShortcuts = _interopRequireDefault(require('./KeyboardShortcuts')); +} + +var _Model; + +function _load_Model() { + return _Model = _interopRequireDefault(require('nuclide-commons/Model')); +} + +var _createPackage; + +function _load_createPackage() { + return _createPackage = _interopRequireDefault(require('nuclide-commons-atom/createPackage')); +} + +var _textEditor; + +function _load_textEditor() { + return _textEditor = require('nuclide-commons-atom/text-editor'); +} + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _event; + +function _load_event() { + return _event = require('nuclide-commons/event'); +} + +var _DiagnosticsViewModel; + +function _load_DiagnosticsViewModel() { + return _DiagnosticsViewModel = require('./DiagnosticsViewModel'); +} + +var _StatusBarTile; + +function _load_StatusBarTile() { + return _StatusBarTile = _interopRequireDefault(require('./ui/StatusBarTile')); +} + +var _gutter; + +function _load_gutter() { + return _gutter = require('./gutter'); +} + +var _getDiagnosticDatatip; + +function _load_getDiagnosticDatatip() { + return _getDiagnosticDatatip = _interopRequireDefault(require('./getDiagnosticDatatip')); +} -type ActivationState = {| - filterByActiveTextEditor: boolean, -|}; +var _paneUtils; -type DiagnosticsState = {| - ...ActivationState, - diagnosticUpdater: ?DiagnosticUpdater, -|}; +function _load_paneUtils() { + return _paneUtils = require('./paneUtils'); +} + +var _goToLocation; + +function _load_goToLocation() { + return _goToLocation = require('nuclide-commons-atom/go-to-location'); +} + +var _featureConfig; + +function _load_featureConfig() { + return _featureConfig = _interopRequireDefault(require('nuclide-commons-atom/feature-config')); +} + +var _destroyItemWhere; + +function _load_destroyItemWhere() { + return _destroyItemWhere = require('nuclide-commons-atom/destroyItemWhere'); +} + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _showActionsMenu; + +function _load_showActionsMenu() { + return _showActionsMenu = _interopRequireDefault(require('./showActionsMenu')); +} + +var _showAtomLinterWarning; + +function _load_showAtomLinterWarning() { + return _showAtomLinterWarning = _interopRequireDefault(require('./showAtomLinterWarning')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const MAX_OPEN_ALL_FILES = 20; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const SHOW_TRACES_SETTING = 'atom-ide-diagnostics-ui.showDiagnosticTraces'; class Activation { - _subscriptions: UniversalDisposable; - _model: Model; - _statusBarTile: ?StatusBarTile; - _fileDiagnostics: WeakMap>; - _globalViewStates: ?Observable; - - constructor(state: ?Object): void { - this._subscriptions = new UniversalDisposable( - this.registerOpenerAndCommand(), - this._registerActionsMenu(), - showAtomLinterWarning(), - ); - this._model = new Model({ - filterByActiveTextEditor: - idx(state, _ => _.filterByActiveTextEditor) === true, - diagnosticUpdater: null, + + constructor(state) { + var _ref; + + this._subscriptions = new (_UniversalDisposable || _load_UniversalDisposable()).default(this.registerOpenerAndCommand(), this._registerActionsMenu(), (0, (_showAtomLinterWarning || _load_showAtomLinterWarning()).default)()); + this._model = new (_Model || _load_Model()).default({ + filterByActiveTextEditor: ((_ref = state) != null ? _ref.filterByActiveTextEditor : _ref) === true, + diagnosticUpdater: null }); this._fileDiagnostics = new WeakMap(); } - consumeDatatipService(service: DatatipService): IDisposable { - const datatipProvider: DatatipProvider = { + consumeDatatipService(service) { + const datatipProvider = { // show this datatip for every type of file providerName: 'diagnostics-datatip', // Diagnostic datatips should have higher priority than most other datatips. priority: 10, datatip: (editor, position) => { - const messagesAtPosition = this._getMessagesAtPosition( - editor, - position, - ); - const {diagnosticUpdater} = this._model.state; + const messagesAtPosition = this._getMessagesAtPosition(editor, position); + const { diagnosticUpdater } = this._model.state; if (messagesAtPosition.length === 0 || diagnosticUpdater == null) { return Promise.resolve(null); } - return getDiagnosticDatatip( - editor, - position, - messagesAtPosition, - diagnosticUpdater, - ); - }, + return (0, (_getDiagnosticDatatip || _load_getDiagnosticDatatip()).default)(editor, position, messagesAtPosition, diagnosticUpdater); + } }; const disposable = service.addProvider(datatipProvider); this._subscriptions.add(disposable); return disposable; } - consumeDiagnosticUpdates(diagnosticUpdater: DiagnosticUpdater): IDisposable { + consumeDiagnosticUpdates(diagnosticUpdater) { this._getStatusBarTile().consumeDiagnosticUpdates(diagnosticUpdater); this._subscriptions.add(gutterConsumeDiagnosticUpdates(diagnosticUpdater)); // Currently, the DiagnosticsView is designed to work with only one DiagnosticUpdater. if (this._model.state.diagnosticUpdater != null) { - return new UniversalDisposable(); + return new (_UniversalDisposable || _load_UniversalDisposable()).default(); } - this._model.setState({diagnosticUpdater}); + this._model.setState({ diagnosticUpdater }); const atomCommandsDisposable = addAtomCommands(diagnosticUpdater); this._subscriptions.add(atomCommandsDisposable); this._subscriptions.add( - // Track diagnostics for all active editors. - observeTextEditors((editor: TextEditor) => { - this._fileDiagnostics.set(editor, []); - // TODO: this is actually inefficient - this filters all file events - // by their path, so this is actually O(N^2) in the number of editors. - // We should merge the store and UI packages to get direct access. - const subscription = getEditorDiagnosticUpdates( - editor, - diagnosticUpdater, - ) - .finally(() => { - this._subscriptions.remove(subscription); - this._fileDiagnostics.delete(editor); - }) - .subscribe(update => { - this._fileDiagnostics.set(editor, update.messages); - }); - this._subscriptions.add(subscription); - }), - ); - return new UniversalDisposable(atomCommandsDisposable, () => { - invariant(this._model.state.diagnosticUpdater === diagnosticUpdater); - this._model.setState({diagnosticUpdater: null}); + // Track diagnostics for all active editors. + (0, (_textEditor || _load_textEditor()).observeTextEditors)(editor => { + this._fileDiagnostics.set(editor, []); + // TODO: this is actually inefficient - this filters all file events + // by their path, so this is actually O(N^2) in the number of editors. + // We should merge the store and UI packages to get direct access. + const subscription = getEditorDiagnosticUpdates(editor, diagnosticUpdater).finally(() => { + this._subscriptions.remove(subscription); + this._fileDiagnostics.delete(editor); + }).subscribe(update => { + this._fileDiagnostics.set(editor, update.messages); + }); + this._subscriptions.add(subscription); + })); + return new (_UniversalDisposable || _load_UniversalDisposable()).default(atomCommandsDisposable, () => { + if (!(this._model.state.diagnosticUpdater === diagnosticUpdater)) { + throw new Error('Invariant violation: "this._model.state.diagnosticUpdater === diagnosticUpdater"'); + } + + this._model.setState({ diagnosticUpdater: null }); }); } - consumeStatusBar(statusBar: atom$StatusBar): void { + consumeStatusBar(statusBar) { this._getStatusBarTile().consumeStatusBar(statusBar); } - deserializeDiagnosticsViewModel(): DiagnosticsViewModel { + deserializeDiagnosticsViewModel() { return this._createDiagnosticsViewModel(); } - dispose(): void { + dispose() { this._subscriptions.dispose(); if (this._statusBarTile) { this._statusBarTile.dispose(); @@ -163,15 +210,15 @@ class Activation { } } - serialize(): ActivationState { - const {filterByActiveTextEditor} = this._model.state; + serialize() { + const { filterByActiveTextEditor } = this._model.state; return { - filterByActiveTextEditor, + filterByActiveTextEditor }; } - _createDiagnosticsViewModel(): DiagnosticsViewModel { - return new DiagnosticsViewModel(this._getGlobalViewStates()); + _createDiagnosticsViewModel() { + return new (_DiagnosticsViewModel || _load_DiagnosticsViewModel()).DiagnosticsViewModel(this._getGlobalViewStates()); } /** @@ -180,160 +227,104 @@ class Activation { * only have one copy of the diagnostics panel so this is mostly a theoretical distinction, * however, each copy should have its own sorting, filtering, etc. */ - _getGlobalViewStates(): Observable { + _getGlobalViewStates() { if (this._globalViewStates == null) { const packageStates = this._model.toObservable(); - const diagnosticsStream = packageStates - .map(state => state.diagnosticUpdater) - .distinctUntilChanged() - .switchMap( - updater => - updater == null - ? Observable.of([]) - : observableFromSubscribeFunction(updater.observeMessages), - ) - .debounceTime(100) - // FIXME: It's not good for UX or perf that we're providing a default sort here (that users - // can't return to). We should remove this and have the table sorting be more intelligent. - // For example, sorting by type means sorting by [type, filename, description]. - .map(diagnostics => diagnostics.slice().sort(compareMessagesByFile)) - .startWith([]); - - const showTracesStream: Observable< - boolean, - > = (featureConfig.observeAsStream(SHOW_TRACES_SETTING): any); + const diagnosticsStream = packageStates.map(state => state.diagnosticUpdater).distinctUntilChanged().switchMap(updater => updater == null ? _rxjsBundlesRxMinJs.Observable.of([]) : (0, (_event || _load_event()).observableFromSubscribeFunction)(updater.observeMessages)).debounceTime(100) + // FIXME: It's not good for UX or perf that we're providing a default sort here (that users + // can't return to). We should remove this and have the table sorting be more intelligent. + // For example, sorting by type means sorting by [type, filename, description]. + .map(diagnostics => diagnostics.slice().sort((_paneUtils || _load_paneUtils()).compareMessagesByFile)).startWith([]); + + const showTracesStream = (_featureConfig || _load_featureConfig()).default.observeAsStream(SHOW_TRACES_SETTING); const setShowTraces = showTraces => { - featureConfig.set(SHOW_TRACES_SETTING, showTraces); + (_featureConfig || _load_featureConfig()).default.set(SHOW_TRACES_SETTING, showTraces); }; const pathToActiveTextEditorStream = getActiveEditorPaths(); - const filterByActiveTextEditorStream = packageStates - .map(state => state.filterByActiveTextEditor) - .distinctUntilChanged(); + const filterByActiveTextEditorStream = packageStates.map(state => state.filterByActiveTextEditor).distinctUntilChanged(); const setFilterByActiveTextEditor = filterByActiveTextEditor => { - this._model.setState({filterByActiveTextEditor}); + this._model.setState({ filterByActiveTextEditor }); }; - this._globalViewStates = Observable.combineLatest( - diagnosticsStream, - filterByActiveTextEditorStream, - pathToActiveTextEditorStream, - showTracesStream, - ( - diagnostics, - filterByActiveTextEditor, - pathToActiveTextEditor, - showTraces, - ) => ({ - diagnostics, - filterByActiveTextEditor, - pathToActiveTextEditor, - showTraces, - onShowTracesChange: setShowTraces, - onFilterByActiveTextEditorChange: setFilterByActiveTextEditor, - }), - ); + this._globalViewStates = _rxjsBundlesRxMinJs.Observable.combineLatest(diagnosticsStream, filterByActiveTextEditorStream, pathToActiveTextEditorStream, showTracesStream, (diagnostics, filterByActiveTextEditor, pathToActiveTextEditor, showTraces) => ({ + diagnostics, + filterByActiveTextEditor, + pathToActiveTextEditor, + showTraces, + onShowTracesChange: setShowTraces, + onFilterByActiveTextEditorChange: setFilterByActiveTextEditor + })); } return this._globalViewStates; } - registerOpenerAndCommand(): IDisposable { - const commandDisposable = atom.commands.add( - 'atom-workspace', - 'diagnostics:toggle-table', - () => { - atom.workspace.toggle(WORKSPACE_VIEW_URI); - }, - ); - return new UniversalDisposable( - atom.workspace.addOpener(uri => { - if (uri === WORKSPACE_VIEW_URI) { - return this._createDiagnosticsViewModel(); - } - }), - () => { - destroyItemWhere(item => item instanceof DiagnosticsViewModel); - }, - commandDisposable, - ); + registerOpenerAndCommand() { + const commandDisposable = atom.commands.add('atom-workspace', 'diagnostics:toggle-table', () => { + atom.workspace.toggle((_DiagnosticsViewModel || _load_DiagnosticsViewModel()).WORKSPACE_VIEW_URI); + }); + return new (_UniversalDisposable || _load_UniversalDisposable()).default(atom.workspace.addOpener(uri => { + if (uri === (_DiagnosticsViewModel || _load_DiagnosticsViewModel()).WORKSPACE_VIEW_URI) { + return this._createDiagnosticsViewModel(); + } + }), () => { + (0, (_destroyItemWhere || _load_destroyItemWhere()).destroyItemWhere)(item => item instanceof (_DiagnosticsViewModel || _load_DiagnosticsViewModel()).DiagnosticsViewModel); + }, commandDisposable); } - _registerActionsMenu(): IDisposable { - return atom.commands.add( - 'atom-text-editor', - 'diagnostics:show-actions-at-position', - () => { - const editor = atom.workspace.getActiveTextEditor(); - const {diagnosticUpdater} = this._model.state; - if (editor == null || diagnosticUpdater == null) { - return; - } - const position = editor.getCursorBufferPosition(); - const messagesAtPosition = this._getMessagesAtPosition( - editor, - position, - ); - if (messagesAtPosition.length === 0) { - return; - } - showActionsMenu( - editor, - position, - messagesAtPosition, - diagnosticUpdater, - ); - }, - ); + _registerActionsMenu() { + return atom.commands.add('atom-text-editor', 'diagnostics:show-actions-at-position', () => { + const editor = atom.workspace.getActiveTextEditor(); + const { diagnosticUpdater } = this._model.state; + if (editor == null || diagnosticUpdater == null) { + return; + } + const position = editor.getCursorBufferPosition(); + const messagesAtPosition = this._getMessagesAtPosition(editor, position); + if (messagesAtPosition.length === 0) { + return; + } + (0, (_showActionsMenu || _load_showActionsMenu()).default)(editor, position, messagesAtPosition, diagnosticUpdater); + }); } - _getStatusBarTile(): StatusBarTile { + _getStatusBarTile() { if (!this._statusBarTile) { - this._statusBarTile = new StatusBarTile(); + this._statusBarTile = new (_StatusBarTile || _load_StatusBarTile()).default(); } return this._statusBarTile; } - _getMessagesAtPosition( - editor: atom$TextEditor, - position: atom$Point, - ): Array { + _getMessagesAtPosition(editor, position) { const messagesForFile = this._fileDiagnostics.get(editor); if (messagesForFile == null) { return []; } - return messagesForFile.filter( - message => message.range != null && message.range.containsPoint(position), - ); + return messagesForFile.filter(message => message.range != null && message.range.containsPoint(position)); } } -function gutterConsumeDiagnosticUpdates( - diagnosticUpdater: DiagnosticUpdater, -): IDisposable { - const subscriptions = new UniversalDisposable(); - subscriptions.add( - observeTextEditors((editor: TextEditor) => { - const subscription = getEditorDiagnosticUpdates(editor, diagnosticUpdater) - .finally(() => { - subscriptions.remove(subscription); - }) - .subscribe(update => { - // Although the subscription should be cleaned up on editor destroy, - // the very act of destroying the editor can trigger diagnostic updates. - // Thus this callback can still be triggered after the editor is destroyed. - if (!editor.isDestroyed()) { - applyUpdateToEditor(editor, update, diagnosticUpdater); - } - }); - subscriptions.add(subscription); - }), - ); +function gutterConsumeDiagnosticUpdates(diagnosticUpdater) { + const subscriptions = new (_UniversalDisposable || _load_UniversalDisposable()).default(); + subscriptions.add((0, (_textEditor || _load_textEditor()).observeTextEditors)(editor => { + const subscription = getEditorDiagnosticUpdates(editor, diagnosticUpdater).finally(() => { + subscriptions.remove(subscription); + }).subscribe(update => { + // Although the subscription should be cleaned up on editor destroy, + // the very act of destroying the editor can trigger diagnostic updates. + // Thus this callback can still be triggered after the editor is destroyed. + if (!editor.isDestroyed()) { + (0, (_gutter || _load_gutter()).applyUpdateToEditor)(editor, update, diagnosticUpdater); + } + }); + subscriptions.add(subscription); + })); return subscriptions; } -function addAtomCommands(diagnosticUpdater: DiagnosticUpdater): IDisposable { +function addAtomCommands(diagnosticUpdater) { const fixAllInCurrentFile = () => { const editor = atom.workspace.getActiveTextEditor(); if (editor == null) { @@ -343,48 +334,30 @@ function addAtomCommands(diagnosticUpdater: DiagnosticUpdater): IDisposable { if (path == null) { return; } - analytics.track('diagnostics-autofix-all-in-file'); + (_analytics || _load_analytics()).default.track('diagnostics-autofix-all-in-file'); diagnosticUpdater.applyFixesForFile(path); }; const openAllFilesWithErrors = () => { - analytics.track('diagnostics-panel-open-all-files-with-errors'); - observableFromSubscribeFunction(diagnosticUpdater.observeMessages) - .first() - .subscribe((messages: Array) => { - const errorsToOpen = getTopMostErrorLocationsByFilePath(messages); - - if (errorsToOpen.size > MAX_OPEN_ALL_FILES) { - atom.notifications.addError( - `Diagnostics: Will not open more than ${MAX_OPEN_ALL_FILES} files`, - ); - return; - } + (_analytics || _load_analytics()).default.track('diagnostics-panel-open-all-files-with-errors'); + (0, (_event || _load_event()).observableFromSubscribeFunction)(diagnosticUpdater.observeMessages).first().subscribe(messages => { + const errorsToOpen = getTopMostErrorLocationsByFilePath(messages); - const column = 0; - errorsToOpen.forEach((line, uri) => goToLocation(uri, line, column)); - }); + if (errorsToOpen.size > MAX_OPEN_ALL_FILES) { + atom.notifications.addError(`Diagnostics: Will not open more than ${MAX_OPEN_ALL_FILES} files`); + return; + } + + const column = 0; + errorsToOpen.forEach((line, uri) => (0, (_goToLocation || _load_goToLocation()).goToLocation)(uri, line, column)); + }); }; - return new UniversalDisposable( - atom.commands.add( - 'atom-workspace', - 'diagnostics:fix-all-in-current-file', - fixAllInCurrentFile, - ), - atom.commands.add( - 'atom-workspace', - 'diagnostics:open-all-files-with-errors', - openAllFilesWithErrors, - ), - new KeyboardShortcuts(diagnosticUpdater), - ); + return new (_UniversalDisposable || _load_UniversalDisposable()).default(atom.commands.add('atom-workspace', 'diagnostics:fix-all-in-current-file', fixAllInCurrentFile), atom.commands.add('atom-workspace', 'diagnostics:open-all-files-with-errors', openAllFilesWithErrors), new (_KeyboardShortcuts || _load_KeyboardShortcuts()).default(diagnosticUpdater)); } -function getTopMostErrorLocationsByFilePath( - messages: Array, -): Map { - const errorLocations: Map = new Map(); +function getTopMostErrorLocationsByFilePath(messages) { + const errorLocations = new Map(); messages.forEach(message => { if (message.scope !== 'file' || message.filePath == null) { @@ -406,50 +379,23 @@ function getTopMostErrorLocationsByFilePath( return errorLocations; } -function getActiveEditorPaths(): Observable { +function getActiveEditorPaths() { const center = atom.workspace.getCenter(); - return ( - observableFromSubscribeFunction(center.observeActivePaneItem.bind(center)) - .map(paneItem => (isValidTextEditor(paneItem) ? paneItem : null)) - // We want the stream to contain the last valid text editor. Normally that means just ignoring - // non-editors, except initially, when there hasn't been an active editor yet. - .filter((paneItem, index) => paneItem != null || index === 0) - .switchMap(textEditor_ => { - const textEditor: ?atom$TextEditor = (textEditor_: any); - if (textEditor == null) { - return Observable.of(null); - } - // An observable that emits the editor path and then, when the editor's destroyed, null. - return Observable.concat( - Observable.of(textEditor.getPath()), - observableFromSubscribeFunction( - textEditor.onDidDestroy.bind(textEditor), - ) - .take(1) - .mapTo(null), - ); - }) - .distinctUntilChanged() - ); + return (0, (_event || _load_event()).observableFromSubscribeFunction)(center.observeActivePaneItem.bind(center)).map(paneItem => (0, (_textEditor || _load_textEditor()).isValidTextEditor)(paneItem) ? paneItem : null) + // We want the stream to contain the last valid text editor. Normally that means just ignoring + // non-editors, except initially, when there hasn't been an active editor yet. + .filter((paneItem, index) => paneItem != null || index === 0).switchMap(textEditor_ => { + const textEditor = textEditor_; + if (textEditor == null) { + return _rxjsBundlesRxMinJs.Observable.of(null); + } + // An observable that emits the editor path and then, when the editor's destroyed, null. + return _rxjsBundlesRxMinJs.Observable.concat(_rxjsBundlesRxMinJs.Observable.of(textEditor.getPath()), (0, (_event || _load_event()).observableFromSubscribeFunction)(textEditor.onDidDestroy.bind(textEditor)).take(1).mapTo(null)); + }).distinctUntilChanged(); } -function getEditorDiagnosticUpdates( - editor: atom$TextEditor, - diagnosticUpdater: DiagnosticUpdater, -): Observable { - return observableFromSubscribeFunction(editor.onDidChangePath.bind(editor)) - .startWith(editor.getPath()) - .switchMap( - filePath => - filePath != null - ? observableFromSubscribeFunction(cb => - diagnosticUpdater.observeFileMessages(filePath, cb), - ) - : Observable.empty(), - ) - .takeUntil( - observableFromSubscribeFunction(editor.onDidDestroy.bind(editor)), - ); +function getEditorDiagnosticUpdates(editor, diagnosticUpdater) { + return (0, (_event || _load_event()).observableFromSubscribeFunction)(editor.onDidChangePath.bind(editor)).startWith(editor.getPath()).switchMap(filePath => filePath != null ? (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => diagnosticUpdater.observeFileMessages(filePath, cb)) : _rxjsBundlesRxMinJs.Observable.empty()).takeUntil((0, (_event || _load_event()).observableFromSubscribeFunction)(editor.onDidDestroy.bind(editor))); } -createPackage(module.exports, Activation); +(0, (_createPackage || _load_createPackage()).default)(module.exports, Activation); \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/paneUtils.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/paneUtils.js index 3d639b9d..68adf6f7 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/paneUtils.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/paneUtils.js @@ -1,31 +1,31 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import type { - DiagnosticMessage, - DiagnosticMessageType, -} from '../../atom-ide-diagnostics/lib/types'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getProjectRelativePathOfDiagnostic = getProjectRelativePathOfDiagnostic; +exports.compareMessagesByFile = compareMessagesByFile; -function fileOfDiagnosticMessage(diagnostic: DiagnosticMessage): string { + +function fileOfDiagnosticMessage(diagnostic) { if (typeof diagnostic.filePath === 'string') { return diagnostic.filePath; } else { return ''; } -} +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ -export function getProjectRelativePathOfDiagnostic( - diagnostic: DiagnosticMessage, -): string { +function getProjectRelativePathOfDiagnostic(diagnostic) { if (typeof diagnostic.filePath === 'string') { const [, relativePath] = atom.project.relativizePath(diagnostic.filePath); return relativePath; @@ -34,10 +34,7 @@ export function getProjectRelativePathOfDiagnostic( } } -export function compareMessagesByFile( - a: DiagnosticMessage, - b: DiagnosticMessage, -): number { +function compareMessagesByFile(a, b) { // This will sort by: // - errors before warnings // - local before remote @@ -52,27 +49,22 @@ export function compareMessagesByFile( // We don't sort by project relative path as that will interleave diagnostics from // different projects. - compareVal = fileOfDiagnosticMessage(a).localeCompare( - fileOfDiagnosticMessage(b), - ); + compareVal = fileOfDiagnosticMessage(a).localeCompare(fileOfDiagnosticMessage(b)); // If the messages are from the same file (`filePath` is equal and `localeCompare` // returns 0), compare the line numbers within the file to determine their sort order. - if (compareVal === 0 && (a.range !== undefined && b.range !== undefined)) { + if (compareVal === 0 && a.range !== undefined && b.range !== undefined) { compareVal = a.range.start.row - b.range.start.row; } return compareVal; } -const messageLevelRank: {[key: DiagnosticMessageType]: number} = { +const messageLevelRank = { Error: 0, Warning: 1, - Info: 2, + Info: 2 }; -function compareMessagesByLevel( - a: DiagnosticMessage, - b: DiagnosticMessage, -): number { +function compareMessagesByLevel(a, b) { return messageLevelRank[a.type] - messageLevelRank[b.type]; -} +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/showActionsMenu.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/showActionsMenu.js index 00429737..5e251210 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/showActionsMenu.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/showActionsMenu.js @@ -1,107 +1,103 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type { - DiagnosticUpdater, - FileDiagnosticMessage, -} from '../../atom-ide-diagnostics/lib/types'; - -import invariant from 'assert'; -import electron from 'electron'; -import {Observable} from 'rxjs'; -import {arrayCompact, arrayFlatten} from 'nuclide-commons/collection'; -import {observableFromSubscribeFunction} from 'nuclide-commons/event'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; - -const {remote} = electron; -invariant(remote != null); +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = showActionsMenu; + +var _electron = _interopRequireDefault(require('electron')); + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _collection; + +function _load_collection() { + return _collection = require('nuclide-commons/collection'); +} + +var _event; + +function _load_event() { + return _event = require('nuclide-commons/event'); +} + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const { remote } = _electron.default; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +if (!(remote != null)) { + throw new Error('Invariant violation: "remote != null"'); +} const CODE_ACTIONS_TIMEOUT = 2000; -export default function showActionsMenu( - editor: TextEditor, - position: atom$Point, - messagesAtPosition: Array, - diagnosticUpdater: DiagnosticUpdater, -): IDisposable { +function showActionsMenu(editor, position, messagesAtPosition, diagnosticUpdater) { diagnosticUpdater.fetchCodeActions(editor, messagesAtPosition); - return new UniversalDisposable( - observableFromSubscribeFunction(cb => - diagnosticUpdater.observeCodeActionsForMessage(cb), - ) - .filter(codeActionsForMessage => { - return messagesAtPosition.every(message => - codeActionsForMessage.has(message), - ); - }) - .take(1) - .race(Observable.of(new WeakMap()).delay(CODE_ACTIONS_TIMEOUT)) - .subscribe(codeActionsForMessage => { - const currentWindow = remote.getCurrentWindow(); - const menu = new remote.Menu(); - const fixes = arrayCompact( - messagesAtPosition.map(message => { - const {fix} = message; - if (fix == null) { - return null; - } - const fixTitle = fix.title == null ? 'Fix' : fix.title; - return { - title: `${fixTitle} (${message.providerName})`, - apply: () => diagnosticUpdater.applyFix(message), - }; - }), - ); - const actions = arrayFlatten( - messagesAtPosition.map(message => { - const codeActions = codeActionsForMessage.get(message); - if (codeActions == null) { - return []; - } - return Array.from(codeActions).map(([title, codeAction]) => ({ - title, - apply: () => codeAction.apply(), - })); - }), - ); - - [...fixes, ...actions].forEach(action => { - menu.append( - new remote.MenuItem({ - type: 'normal', - label: action.title, - click: () => { - action.apply(); - }, - }), - ); - }); - - const screenPosition = editor.screenPositionForBufferPosition(position); - const editorView = atom.views.getView(editor); - const pixelPosition = editorView.pixelPositionForScreenPosition( - screenPosition, - ); - // Pixel coordinates are relative to the editor's scroll view. - const scrollView = editorView.querySelector('.scroll-view'); - invariant(scrollView != null); - const boundingRect = scrollView.getBoundingClientRect(); - menu.popup( - currentWindow, - boundingRect.left + pixelPosition.left - editorView.getScrollLeft(), - boundingRect.top + pixelPosition.top - editorView.getScrollTop(), - 0, - ); - }), - ); -} + return new (_UniversalDisposable || _load_UniversalDisposable()).default((0, (_event || _load_event()).observableFromSubscribeFunction)(cb => diagnosticUpdater.observeCodeActionsForMessage(cb)).filter(codeActionsForMessage => { + return messagesAtPosition.every(message => codeActionsForMessage.has(message)); + }).take(1).race(_rxjsBundlesRxMinJs.Observable.of(new WeakMap()).delay(CODE_ACTIONS_TIMEOUT)).subscribe(codeActionsForMessage => { + const currentWindow = remote.getCurrentWindow(); + const menu = new remote.Menu(); + const fixes = (0, (_collection || _load_collection()).arrayCompact)(messagesAtPosition.map(message => { + const { fix } = message; + if (fix == null) { + return null; + } + const fixTitle = fix.title == null ? 'Fix' : fix.title; + return { + title: `${fixTitle} (${message.providerName})`, + apply: () => diagnosticUpdater.applyFix(message) + }; + })); + const actions = (0, (_collection || _load_collection()).arrayFlatten)(messagesAtPosition.map(message => { + const codeActions = codeActionsForMessage.get(message); + if (codeActions == null) { + return []; + } + return Array.from(codeActions).map(([title, codeAction]) => ({ + title, + apply: () => codeAction.apply() + })); + })); + + [...fixes, ...actions].forEach(action => { + menu.append(new remote.MenuItem({ + type: 'normal', + label: action.title, + click: () => { + action.apply(); + } + })); + }); + + const screenPosition = editor.screenPositionForBufferPosition(position); + const editorView = atom.views.getView(editor); + const pixelPosition = editorView.pixelPositionForScreenPosition(screenPosition); + // Pixel coordinates are relative to the editor's scroll view. + const scrollView = editorView.querySelector('.scroll-view'); + + if (!(scrollView != null)) { + throw new Error('Invariant violation: "scrollView != null"'); + } + + const boundingRect = scrollView.getBoundingClientRect(); + menu.popup(currentWindow, boundingRect.left + pixelPosition.left - editorView.getScrollLeft(), boundingRect.top + pixelPosition.top - editorView.getScrollTop(), 0); + })); +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/showAtomLinterWarning.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/showAtomLinterWarning.js index 4416531c..6afa0aa7 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/showAtomLinterWarning.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/showAtomLinterWarning.js @@ -1,3 +1,32 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = showAtomLinterWarning; + +var _featureConfig; + +function _load_featureConfig() { + return _featureConfig = _interopRequireDefault(require('nuclide-commons-atom/feature-config')); +} + +var _event; + +function _load_event() { + return _event = require('nuclide-commons/event'); +} + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,76 +35,46 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import featureConfig from 'nuclide-commons-atom/feature-config'; -import {observableFromSubscribeFunction} from 'nuclide-commons/event'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; -import {Observable} from 'rxjs'; - const LINTER_PACKAGE = 'linter'; -function observePackageIsEnabled(): Observable { - return Observable.merge( - Observable.of(atom.packages.isPackageActive(LINTER_PACKAGE)), - observableFromSubscribeFunction( - atom.packages.onDidActivatePackage.bind(atom.packages), - ) - .filter(pkg => pkg.name === LINTER_PACKAGE) - .mapTo(true), - observableFromSubscribeFunction( - atom.packages.onDidDeactivatePackage.bind(atom.packages), - ) - .filter(pkg => pkg.name === LINTER_PACKAGE) - .mapTo(false), - ); +function observePackageIsEnabled() { + return _rxjsBundlesRxMinJs.Observable.merge(_rxjsBundlesRxMinJs.Observable.of(atom.packages.isPackageActive(LINTER_PACKAGE)), (0, (_event || _load_event()).observableFromSubscribeFunction)(atom.packages.onDidActivatePackage.bind(atom.packages)).filter(pkg => pkg.name === LINTER_PACKAGE).mapTo(true), (0, (_event || _load_event()).observableFromSubscribeFunction)(atom.packages.onDidDeactivatePackage.bind(atom.packages)).filter(pkg => pkg.name === LINTER_PACKAGE).mapTo(false)); } -function disableLinter(): void { +function disableLinter() { atom.packages.disablePackage(LINTER_PACKAGE); } -function disableDiagnostics(): void { - featureConfig.set('use.atom-ide-diagnostics-ui', false); +function disableDiagnostics() { + (_featureConfig || _load_featureConfig()).default.set('use.atom-ide-diagnostics-ui', false); } -export default function showAtomLinterWarning(): IDisposable { - const packageName = featureConfig.getPackageName(); - return new UniversalDisposable( - observePackageIsEnabled().filter(Boolean).subscribe(() => { - const notification = atom.notifications.addInfo('Choose a linter UI', { - description: - 'You have both `linter` and `atom-ide-diagnostics` enabled, which will both ' + - 'display lint results for Linter-based packages.\n\n' + - 'To avoid duplicate results, please disable one of the packages.' + - (packageName === 'nuclide' - ? '\n\nNote that Flow and Hack errors are not compatible with `linter`.' - : ''), - dismissable: true, - buttons: [ - { - text: 'Disable Linter', - onDidClick() { - notification.dismiss(); - disableLinter(); - }, - }, - { - text: 'Disable Diagnostics', - onDidClick() { - notification.dismiss(); - disableDiagnostics(); - atom.notifications.addInfo('Re-enabling Diagnostics', { - description: - 'To re-enable diagnostics, please enable "Diagnostics" under the "Enabled Features" ' + - `section in \`${packageName}\` settings.`, - }); - }, - }, - ], - }); - }), - ); -} +function showAtomLinterWarning() { + const packageName = (_featureConfig || _load_featureConfig()).default.getPackageName(); + return new (_UniversalDisposable || _load_UniversalDisposable()).default(observePackageIsEnabled().filter(Boolean).subscribe(() => { + const notification = atom.notifications.addInfo('Choose a linter UI', { + description: 'You have both `linter` and `atom-ide-diagnostics` enabled, which will both ' + 'display lint results for Linter-based packages.\n\n' + 'To avoid duplicate results, please disable one of the packages.' + (packageName === 'nuclide' ? '\n\nNote that Flow and Hack errors are not compatible with `linter`.' : ''), + dismissable: true, + buttons: [{ + text: 'Disable Linter', + onDidClick() { + notification.dismiss(); + disableLinter(); + } + }, { + text: 'Disable Diagnostics', + onDidClick() { + notification.dismiss(); + disableDiagnostics(); + atom.notifications.addInfo('Re-enabling Diagnostics', { + description: 'To re-enable diagnostics, please enable "Diagnostics" under the "Enabled Features" ' + `section in \`${packageName}\` settings.` + }); + } + }] + }); + })); +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/sortDiagnostics.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/sortDiagnostics.js index 2ebc71c3..35ffea04 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/sortDiagnostics.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/sortDiagnostics.js @@ -1,3 +1,14 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = sortDiagnostics; + + +/* + * Sorts the diagnostics according to given column and sort direction + */ /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,34 +17,17 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {Row} from 'nuclide-commons-ui/Table'; -import type { - DiagnosticMessageKind, - DiagnosticMessageType, -} from '../../atom-ide-diagnostics/lib/types'; -import type {DisplayDiagnostic} from './ui/ExperimentalDiagnosticsTable'; - -import invariant from 'assert'; +function sortDiagnostics(diagnostics, sortedColumnName, sortDescending) { + const compare = SORT_FUNCTIONS[sortedColumnName]; -type DiagnosticsComparison = ( - a: Row, - b: Row, -) => number; + if (!(compare != null)) { + throw new Error('Invariant violation: "compare != null"'); + } -/* - * Sorts the diagnostics according to given column and sort direction - */ -export default function sortDiagnostics( - diagnostics: Array>, - sortedColumnName: $Keys, - sortDescending: boolean, -): Array> { - const compare = SORT_FUNCTIONS[sortedColumnName]; - invariant(compare != null); const sorted = diagnostics.sort(compare); // We can't just reverse the sign of the comparison function because that would maintain the // ordering of "equal" items with respect to eachother. @@ -41,46 +35,18 @@ export default function sortDiagnostics( } const SORT_FUNCTIONS = { - classification: compose( - compareClassification, - compareSource, - comparePath, - compareDescription, - ), - providerName: compose( - compareSource, - compareClassification, - compareDescription, - comparePath, - ), - description: compose( - compareDescription, - compareSource, - compareClassification, - comparePath, - ), - dir: compose( - comparePath, - compareSource, - compareClassification, - compareDescription, - ), - location: compose( - compareBasename, - comparePath, - compareClassification, - compareSource, - compareDescription, - ), + classification: compose(compareClassification, compareSource, comparePath, compareDescription), + providerName: compose(compareSource, compareClassification, compareDescription, comparePath), + description: compose(compareDescription, compareSource, compareClassification, comparePath), + dir: compose(comparePath, compareSource, compareClassification, compareDescription), + location: compose(compareBasename, comparePath, compareClassification, compareSource, compareDescription) }; /** * Compose comparison functions so that, when one identifies the items as equal, the subsequent * functions are used to resolve the abiguity. */ -function compose( - ...comparisons: Array -): DiagnosticsComparison { +function compose(...comparisons) { return (a, b) => { for (const compare of comparisons) { const val = compare(a, b); @@ -92,28 +58,13 @@ function compose( }; } -function compareClassification( - a: Row, - b: Row, -): number { - return ( - compareClassificationKind( - a.data.classification.kind, - b.data.classification.kind, - ) || - compareClassificationSeverity( - a.data.classification.severity, - b.data.classification.severity, - ) - ); +function compareClassification(a, b) { + return compareClassificationKind(a.data.classification.kind, b.data.classification.kind) || compareClassificationSeverity(a.data.classification.severity, b.data.classification.severity); } const KIND_ORDER = ['feedback', 'lint']; -function compareClassificationKind( - a: ?DiagnosticMessageKind, - b: ?DiagnosticMessageKind, -): number { +function compareClassificationKind(a, b) { const aKind = a || 'lint'; const bKind = b || 'lint'; return KIND_ORDER.indexOf(aKind) - KIND_ORDER.indexOf(bKind); @@ -121,31 +72,19 @@ function compareClassificationKind( const SEVERITY_ORDER = ['Info', 'Warning', 'Error']; -function compareClassificationSeverity( - a: DiagnosticMessageType, - b: DiagnosticMessageType, -): number { +function compareClassificationSeverity(a, b) { return SEVERITY_ORDER.indexOf(a) - SEVERITY_ORDER.indexOf(b); } -function compareSource( - a: Row, - b: Row, -): number { +function compareSource(a, b) { return compareStrings(a.data.providerName, b.data.providerName); } -function compareDescription( - a: Row, - b: Row, -): number { +function compareDescription(a, b) { return compareStrings(a.data.description.text, b.data.description.text); } -function comparePath( - a: Row, - b: Row, -): number { +function comparePath(a, b) { const aLocation = a.data.location; const bLocation = b.data.location; if (aLocation == null && bLocation == null) { @@ -161,17 +100,12 @@ function comparePath( if (pathComparison !== 0) { return pathComparison; } - const aLine = - aLocation.locationInFile == null ? 0 : aLocation.locationInFile.line; - const bLine = - bLocation.locationInFile == null ? 0 : bLocation.locationInFile.line; + const aLine = aLocation.locationInFile == null ? 0 : aLocation.locationInFile.line; + const bLine = bLocation.locationInFile == null ? 0 : bLocation.locationInFile.line; return compareNumbers(aLine, bLine); } -function compareBasename( - a: Row, - b: Row, -): number { +function compareBasename(a, b) { const aLocationInFile = a.data.location && a.data.location.locationInFile; const bLocationInFile = b.data.location && b.data.location.locationInFile; if (aLocationInFile == null && bLocationInFile == null) { @@ -183,16 +117,13 @@ function compareBasename( if (bLocationInFile == null) { return 1; } - return ( - compareStrings(aLocationInFile.basename, bLocationInFile.basename) || - compareNumbers(aLocationInFile.line, bLocationInFile.line) - ); + return compareStrings(aLocationInFile.basename, bLocationInFile.basename) || compareNumbers(aLocationInFile.line, bLocationInFile.line); } -function compareStrings(a: string, b: string): number { +function compareStrings(a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); } -function compareNumbers(a: number, b: number): number { +function compareNumbers(a, b) { return a - b; -} +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/types.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/types.js index 350fd978..a726efc4 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/types.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/types.js @@ -1,26 +1 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {NuclideUri} from 'nuclide-commons/nuclideUri'; -import type {DiagnosticMessage} from '../../atom-ide-diagnostics/lib/types'; - -export type FilterType = 'errors' | 'warnings' | 'feedback'; - -// State that's shared between every diagnostics panel instance. -export type GlobalViewState = { - diagnostics: Array, - pathToActiveTextEditor: ?NuclideUri, - filterByActiveTextEditor: boolean, - onFilterByActiveTextEditorChange: (isChecked: boolean) => mixed, - showTraces: boolean, - onShowTracesChange: (isChecked: boolean) => mixed, -}; +'use strict'; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsCodeActions.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsCodeActions.js index ca2c31d8..f3445fe7 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsCodeActions.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsCodeActions.js @@ -1,3 +1,27 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = DiagnosticsCodeActions; + +var _react = _interopRequireWildcard(require('react')); + +var _Button; + +function _load_Button() { + return _Button = require('nuclide-commons-ui/Button'); +} + +var _ButtonGroup; + +function _load_ButtonGroup() { + return _ButtonGroup = require('nuclide-commons-ui/ButtonGroup'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +// Maximum number of CodeActions to show for a given Diagnostic. /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,51 +30,45 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {CodeAction} from '../../../atom-ide-code-actions/lib/types'; - -import * as React from 'react'; -import {Button} from 'nuclide-commons-ui/Button'; -import {ButtonGroup} from 'nuclide-commons-ui/ButtonGroup'; - -// Maximum number of CodeActions to show for a given Diagnostic. const MAX_CODE_ACTIONS = 4; -export default function DiagnosticsCodeActions(props: { - codeActions: Map, -}): React.Element { - return ( -
- {Array.from(props.codeActions.entries()) - .splice(0, MAX_CODE_ACTIONS) - // TODO: (seansegal) T21130259 Display a "more" indicator when there are many CodeActions. - .map(([title, codeAction], i) => { - return ( - - - - ); - })} -
+function DiagnosticsCodeActions(props) { + return _react.createElement( + 'div', + { className: 'diagnostics-code-actions' }, + Array.from(props.codeActions.entries()).splice(0, MAX_CODE_ACTIONS) + // TODO: (seansegal) T21130259 Display a "more" indicator when there are many CodeActions. + .map(([title, codeAction], i) => { + return _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + { key: i }, + _react.createElement( + (_Button || _load_Button()).Button, + { + className: 'diagnostics-code-action-button', + size: 'EXTRA_SMALL', + onClick: () => { + // TODO: (seansegal) T21130332 Display CodeAction status indicators + codeAction.apply().catch(handleCodeActionFailure); + } }, + _react.createElement( + 'span', + { className: 'inline-block' }, + title + ) + ) + ); + }) ); } -function handleCodeActionFailure(error: ?Error) { +function handleCodeActionFailure(error) { atom.notifications.addWarning('Code action could not be applied', { description: error ? error.message : '', - dismissable: true, + dismissable: true }); -} +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsMessage.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsMessage.js index 2b5b2201..9dd5ccf9 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsMessage.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsMessage.js @@ -1,3 +1,38 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DiagnosticsMessageNoHeader = exports.DiagnosticsMessage = undefined; + +var _react = _interopRequireWildcard(require('react')); + +var _Button; + +function _load_Button() { + return _Button = require('nuclide-commons-ui/Button'); +} + +var _ButtonGroup; + +function _load_ButtonGroup() { + return _ButtonGroup = require('nuclide-commons-ui/ButtonGroup'); +} + +var _DiagnosticsMessageText; + +function _load_DiagnosticsMessageText() { + return _DiagnosticsMessageText = require('./DiagnosticsMessageText'); +} + +var _DiagnosticsTraceItem; + +function _load_DiagnosticsTraceItem() { + return _DiagnosticsTraceItem = require('./DiagnosticsTraceItem'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,33 +41,18 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {FileDiagnosticMessage} from '../../../atom-ide-diagnostics/lib/types'; - -import * as React from 'react'; -import {Button, ButtonTypes} from 'nuclide-commons-ui/Button'; -import {ButtonGroup} from 'nuclide-commons-ui/ButtonGroup'; -import {DiagnosticsMessageText} from './DiagnosticsMessageText'; -import {DiagnosticsTraceItem} from './DiagnosticsTraceItem'; - -type DiagnosticsMessageProps = { - message: FileDiagnosticMessage, - goToLocation: (path: string, line: number) => mixed, - fixer: (message: FileDiagnosticMessage) => void, - children?: Array>, -}; - const PROVIDER_CLASS_NAME = { Error: 'highlight-error', Warning: 'highlight-warning', - Info: 'highlight-info', + Info: 'highlight-info' }; -function diagnosticHeader(props: DiagnosticsMessageProps) { - const {message, fixer} = props; +function diagnosticHeader(props) { + const { message, fixer } = props; const providerClassName = PROVIDER_CLASS_NAME[message.type]; let fixButton = null; if (message.fix != null) { @@ -40,59 +60,63 @@ function diagnosticHeader(props: DiagnosticsMessageProps) { fixer(message); }; const speculative = message.fix.speculative === true; - const buttonType = speculative ? undefined : ButtonTypes.SUCCESS; - fixButton = ( - + const buttonType = speculative ? undefined : (_Button || _load_Button()).ButtonTypes.SUCCESS; + fixButton = _react.createElement( + (_Button || _load_Button()).Button, + { buttonType: buttonType, size: 'EXTRA_SMALL', onClick: applyFix }, + // flowlint-next-line sketchy-null-string:off + message.fix.title || 'Fix' ); } - return ( -
- - {fixButton} - - - {message.providerName} - -
+ return _react.createElement( + 'div', + { className: 'diagnostics-popup-header' }, + _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + null, + fixButton + ), + _react.createElement( + 'span', + { className: providerClassName }, + message.providerName + ) ); } -function traceElements(props: DiagnosticsMessageProps) { - const {message, goToLocation} = props; - return message.trace && message.trace.length - ?
- {message.trace.map((traceItem, i) => - , - )} -
- : null; +function traceElements(props) { + const { message, goToLocation } = props; + return message.trace && message.trace.length ? _react.createElement( + 'div', + { className: 'diagnostics-popup-trace' }, + message.trace.map((traceItem, i) => _react.createElement((_DiagnosticsTraceItem || _load_DiagnosticsTraceItem()).DiagnosticsTraceItem, { + key: i, + trace: traceItem, + goToLocation: goToLocation + })) + ) : null; } -export const DiagnosticsMessage = (props: DiagnosticsMessageProps) => { - return ( -
- {diagnosticHeader(props)} -
- -
- {traceElements(props)} - {props.children} -
+const DiagnosticsMessage = exports.DiagnosticsMessage = props => { + return _react.createElement( + 'div', + null, + diagnosticHeader(props), + _react.createElement( + 'div', + { className: 'diagnostics-popup-message' }, + _react.createElement((_DiagnosticsMessageText || _load_DiagnosticsMessageText()).DiagnosticsMessageText, { message: props.message }) + ), + traceElements(props), + props.children ); }; -export const DiagnosticsMessageNoHeader = (props: DiagnosticsMessageProps) => { - return ( -
- - {traceElements(props)} -
+const DiagnosticsMessageNoHeader = exports.DiagnosticsMessageNoHeader = props => { + return _react.createElement( + 'div', + null, + _react.createElement((_DiagnosticsMessageText || _load_DiagnosticsMessageText()).DiagnosticsMessageText, { message: props.message }), + traceElements(props) ); -}; +}; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsMessageText.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsMessageText.js index c010392d..0d10031d 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsMessageText.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsMessageText.js @@ -1,39 +1,19 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import invariant from 'assert'; -import * as React from 'react'; -import {shell} from 'electron'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DiagnosticsMessageText = undefined; +exports.separateUrls = separateUrls; -type DiagnosticsMessageTextProps = { - preserveNewlines?: boolean, // defaults to true - message: { - html?: string, - text?: string, - }, -}; +var _react = _interopRequireWildcard(require('react')); -type UrlOrText = - | { - isUrl: true, - url: string, - } - | { - isUrl: false, - text: string, - }; +var _electron = require('electron'); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } // Exported for testing. -export function separateUrls(message: string): Array { +function separateUrls(message) { // Don't match periods at the end of URLs, because those are usually just to // end the sentence and not actually part of the URL. Optionally match // parameters following a question mark. @@ -42,80 +22,86 @@ export function separateUrls(message: string): Array { const urls = message.match(urlRegex); const nonUrls = message.split(urlRegex); - const parts: Array = [ - { - isUrl: false, - text: nonUrls[0], - }, - ]; + const parts = [{ + isUrl: false, + text: nonUrls[0] + }]; for (let i = 1; i < nonUrls.length; i++) { - invariant(urls != null); + if (!(urls != null)) { + throw new Error('Invariant violation: "urls != null"'); + } + parts.push({ isUrl: true, - url: urls[i - 1], + url: urls[i - 1] }); parts.push({ isUrl: false, - text: nonUrls[i], + text: nonUrls[i] }); } return parts; -} +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ const LEADING_WHITESPACE_RE = /^\s+/; const NBSP = '\xa0'; -function renderRowWithLinks( - message: string, - rowIndex: number, -): React.Element { - const messageWithWhitespace = message.replace( - LEADING_WHITESPACE_RE, - whitespace => NBSP.repeat(whitespace.length), - ); +function renderRowWithLinks(message, rowIndex) { + const messageWithWhitespace = message.replace(LEADING_WHITESPACE_RE, whitespace => NBSP.repeat(whitespace.length)); const parts = separateUrls(messageWithWhitespace).map((part, index) => { if (!part.isUrl) { return part.text; } else { const openUrl = () => { - shell.openExternal(part.url); + _electron.shell.openExternal(part.url); }; - return ( - - {part.url} - + return _react.createElement( + 'a', + { href: '#', key: index, onClick: openUrl }, + part.url ); } }); return ( // We need to use a span here instead of a div so that `text-overflow: ellipsis` works. - - {parts} -
-
+ _react.createElement( + 'span', + { key: rowIndex }, + parts, + _react.createElement('br', null) + ) ); } -export const DiagnosticsMessageText = (props: DiagnosticsMessageTextProps) => { - const {message} = props; +const DiagnosticsMessageText = exports.DiagnosticsMessageText = props => { + const { message } = props; if (message.html != null) { - return ( - - ); + return _react.createElement('span', { + title: message.text, + dangerouslySetInnerHTML: { __html: message.html } + }); } else if (message.text != null) { - const rows = - props.preserveNewlines !== false - ? message.text.split('\n') - : [message.text]; - return ( - - {rows.map(renderRowWithLinks)} - + const rows = props.preserveNewlines !== false ? message.text.split('\n') : [message.text]; + return _react.createElement( + 'span', + { title: message.text }, + rows.map(renderRowWithLinks) ); } else { - return Diagnostic lacks message.; + return _react.createElement( + 'span', + null, + 'Diagnostic lacks message.' + ); } -}; +}; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsPopup.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsPopup.js index b7df34e4..aeb85d6c 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsPopup.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsPopup.js @@ -1,73 +1,77 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import type {NuclideUri} from 'nuclide-commons/nuclideUri'; -import type {FileDiagnosticMessage} from '../../../atom-ide-diagnostics/lib/types'; -import type {CodeAction} from '../../../atom-ide-code-actions/lib/types'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DiagnosticsPopup = undefined; -import * as React from 'react'; -import classnames from 'classnames'; -import {DiagnosticsMessage} from './DiagnosticsMessage'; -import DiagnosticsCodeActions from './DiagnosticsCodeActions'; +var _react = _interopRequireWildcard(require('react')); -type DiagnosticsPopupProps = { - messages: Array, - goToLocation: (filePath: NuclideUri, line: number) => mixed, - fixer: (message: FileDiagnosticMessage) => void, - codeActionsForMessage?: Map>, -}; +var _classnames; -function renderMessage( - fixer: (message: FileDiagnosticMessage) => void, - goToLocation: (filePath: NuclideUri, line: number) => mixed, - codeActionsForMessage: ?Map>, - message: FileDiagnosticMessage, - index: number, -): React.Element { - const className = classnames( - // native-key-bindings and tabIndex=-1 are both needed to allow copying the text in the popup. - 'native-key-bindings', - 'diagnostics-popup-diagnostic', - { - 'diagnostics-popup-error': message.type === 'Error', - 'diagnostics-popup-warning': message.type === 'Warning', - 'diagnostics-popup-info': message.type === 'Info', - }, - ); - const codeActions = - codeActionsForMessage && codeActionsForMessage.get(message); - return ( -
- {/* $FlowFixMe(>=0.53.0) Flow suppress */} - - {codeActions && codeActions.size - ? - : null} - -
+function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _DiagnosticsMessage; + +function _load_DiagnosticsMessage() { + return _DiagnosticsMessage = require('./DiagnosticsMessage'); +} + +var _DiagnosticsCodeActions; + +function _load_DiagnosticsCodeActions() { + return _DiagnosticsCodeActions = _interopRequireDefault(require('./DiagnosticsCodeActions')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +function renderMessage(fixer, goToLocation, codeActionsForMessage, message, index) { + const className = (0, (_classnames || _load_classnames()).default)( + // native-key-bindings and tabIndex=-1 are both needed to allow copying the text in the popup. + 'native-key-bindings', 'diagnostics-popup-diagnostic', { + 'diagnostics-popup-error': message.type === 'Error', + 'diagnostics-popup-warning': message.type === 'Warning', + 'diagnostics-popup-info': message.type === 'Info' + }); + const codeActions = codeActionsForMessage && codeActionsForMessage.get(message); + return _react.createElement( + 'div', + { className: className, key: index, tabIndex: -1 }, + _react.createElement( + (_DiagnosticsMessage || _load_DiagnosticsMessage()).DiagnosticsMessage, + { + fixer: fixer, + goToLocation: goToLocation, + message: message }, + codeActions && codeActions.size ? _react.createElement((_DiagnosticsCodeActions || _load_DiagnosticsCodeActions()).default, { codeActions: codeActions }) : null + ) ); } // TODO move LESS styles to nuclide-ui -export const DiagnosticsPopup = (props: DiagnosticsPopupProps) => { - const {fixer, goToLocation, codeActionsForMessage, messages, ...rest} = props; - return ( -
- {messages.map( - renderMessage.bind(null, fixer, goToLocation, codeActionsForMessage), - )} -
+const DiagnosticsPopup = props => { + const { fixer, goToLocation, codeActionsForMessage, messages } = props, + rest = _objectWithoutProperties(props, ['fixer', 'goToLocation', 'codeActionsForMessage', 'messages']); + return _react.createElement( + 'div', + Object.assign({ className: 'diagnostics-popup' }, rest), + messages.map(renderMessage.bind(null, fixer, goToLocation, codeActionsForMessage)) ); }; +exports.DiagnosticsPopup = DiagnosticsPopup; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsTable.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsTable.js index 7009977e..9ddcea39 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsTable.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsTable.js @@ -1,3 +1,71 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _analytics; + +function _load_analytics() { + return _analytics = _interopRequireDefault(require('nuclide-commons-atom/analytics')); +} + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +var _goToLocation; + +function _load_goToLocation() { + return _goToLocation = require('nuclide-commons-atom/go-to-location'); +} + +var _Table; + +function _load_Table() { + return _Table = require('nuclide-commons-ui/Table'); +} + +var _Highlight; + +function _load_Highlight() { + return _Highlight = require('nuclide-commons-ui/Highlight'); +} + +var _DiagnosticsSorter; + +function _load_DiagnosticsSorter() { + return _DiagnosticsSorter = require('../DiagnosticsSorter'); +} + +var _paneUtils; + +function _load_paneUtils() { + return _paneUtils = require('../paneUtils'); +} + +var _DiagnosticsMessage; + +function _load_DiagnosticsMessage() { + return _DiagnosticsMessage = require('./DiagnosticsMessage'); +} + +var _DiagnosticsMessageText; + +function _load_DiagnosticsMessageText() { + return _DiagnosticsMessageText = require('./DiagnosticsMessageText'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Maximum number of results to render in the table before truncating and displaying a "Max results +// reached" message. /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,85 +74,39 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {DiagnosticMessage} from '../../../atom-ide-diagnostics/lib/types'; -import type {Column} from 'nuclide-commons-ui/Table'; -import type {DiagnosticMessageType} from '../../../atom-ide-diagnostics/lib/types'; -import type {NuclideUri} from 'nuclide-commons/nuclideUri'; - -import analytics from 'nuclide-commons-atom/analytics'; -import classnames from 'classnames'; -import * as React from 'react'; -import {goToLocation} from 'nuclide-commons-atom/go-to-location'; -import {Table} from 'nuclide-commons-ui/Table'; -import {Highlight, HighlightColors} from 'nuclide-commons-ui/Highlight'; -import {sortDiagnostics} from '../DiagnosticsSorter'; -import {getProjectRelativePathOfDiagnostic} from '../paneUtils'; -import {DiagnosticsMessageNoHeader} from './DiagnosticsMessage'; -import {DiagnosticsMessageText} from './DiagnosticsMessageText'; - -type DescriptionField = { - diagnostic: DiagnosticMessage, - showTraces: boolean, - text: string, - isPlainText: boolean, -}; - -export type DisplayDiagnostic = { - +type: DiagnosticMessageType, - +providerName: string, - +filePath: NuclideUri, - +range: number, - +description: { - showTraces: boolean, - diagnostic: DiagnosticMessage, - text: string, - isPlainText: boolean, - }, - +diagnostic: DiagnosticMessage, -}; - -type ColumnName = $Keys; - -// Maximum number of results to render in the table before truncating and displaying a "Max results -// reached" message. const MAX_RESULTS_COUNT = 1000; -const EmptyComponent = () => -
No diagnostic messages
; +const EmptyComponent = () => _react.createElement( + 'div', + { className: 'diagnostics-ui-empty-component' }, + 'No diagnostic messages' +); const TypeToHighlightColor = Object.freeze({ - ERROR: HighlightColors.error, - WARNING: HighlightColors.warning, - INFO: HighlightColors.info, + ERROR: (_Highlight || _load_Highlight()).HighlightColors.error, + WARNING: (_Highlight || _load_Highlight()).HighlightColors.warning, + INFO: (_Highlight || _load_Highlight()).HighlightColors.info }); -function TypeComponent(props: { - data: 'Warning' | 'Error' | 'Info', -}): React.Element { +function TypeComponent(props) { const text = props.data; const highlightColor = TypeToHighlightColor[text.toUpperCase()]; - return ( - - {text} - + return _react.createElement( + (_Highlight || _load_Highlight()).Highlight, + { color: highlightColor }, + text ); } -function getMessageContent( - diagnostic: DiagnosticMessage, - showTraces: boolean, -): {text: string, isPlainText: boolean} { +function getMessageContent(diagnostic, showTraces) { let text = ''; let isPlainText = true; const traces = diagnostic.trace || []; - const allMessages: Array<{html?: string, text?: string}> = [ - diagnostic, - ...traces, - ]; + const allMessages = [diagnostic, ...traces]; for (const message of allMessages) { // TODO: A mix of html and text diagnostics will yield a wonky sort ordering. if (message.html != null) { @@ -96,175 +118,141 @@ function getMessageContent( throw new Error('Neither text nor html property defined on message'); } } - return {text: text.trim(), isPlainText}; + return { text: text.trim(), isPlainText }; } -function DescriptionComponent(props: { - data: DescriptionField, -}): React.Element { - const {showTraces, diagnostic, text, isPlainText} = props.data; - return showTraces && diagnostic.scope === 'file' - ? DiagnosticsMessageNoHeader({ - message: diagnostic, - goToLocation, - fixer: () => {}, - }) - : DiagnosticsMessageText({ - preserveNewlines: showTraces, - message: {text, html: isPlainText ? undefined : text}, - }); +function DescriptionComponent(props) { + const { showTraces, diagnostic, text, isPlainText } = props.data; + return showTraces && diagnostic.scope === 'file' ? (0, (_DiagnosticsMessage || _load_DiagnosticsMessage()).DiagnosticsMessageNoHeader)({ + message: diagnostic, + goToLocation: (_goToLocation || _load_goToLocation()).goToLocation, + fixer: () => {} + }) : (0, (_DiagnosticsMessageText || _load_DiagnosticsMessageText()).DiagnosticsMessageText)({ + preserveNewlines: showTraces, + message: { text, html: isPlainText ? undefined : text } + }); } -function goToDiagnosticLocation(rowData: DiagnosticMessage): void { +function goToDiagnosticLocation(rowData) { if (rowData.scope !== 'file' || rowData.filePath == null) { return; } - analytics.track('diagnostics-panel-goto-location'); + (_analytics || _load_analytics()).default.track('diagnostics-panel-goto-location'); const uri = rowData.filePath; // If initialLine is N, Atom will navigate to line N+1. // Flow sometimes reports a row of -1, so this ensures the line is at least one. const line = Math.max(rowData.range ? rowData.range.start.row : 0, 0); const column = 0; - goToLocation(uri, line, column); + (0, (_goToLocation || _load_goToLocation()).goToLocation)(uri, line, column); } -type DiagnosticsTableProps = { - diagnostics: Array, - showFileName: ?boolean, - showTraces: boolean, -}; - -type State = { - sortDescending: boolean, - sortedColumn: ?ColumnName, -}; - -export default class DiagnosticsTable extends React.Component< - DiagnosticsTableProps, - State, -> { - constructor(props: DiagnosticsTableProps) { +class DiagnosticsTable extends _react.Component { + constructor(props) { super(props); - (this: any)._handleSort = this._handleSort.bind(this); - (this: any)._handleSelectTableRow = this._handleSelectTableRow.bind(this); + this._handleSort = this._handleSort.bind(this); + this._handleSelectTableRow = this._handleSelectTableRow.bind(this); this.state = { sortDescending: false, - sortedColumn: null, + sortedColumn: null }; } - _handleSort(sortedColumn: ?ColumnName, sortDescending: boolean): void { + _handleSort(sortedColumn, sortDescending) { this.setState({ sortedColumn, - sortDescending, + sortDescending }); } - _handleSelectTableRow( - item: {diagnostic: DiagnosticMessage}, - selectedIndex: number, - ): void { + _handleSelectTableRow(item, selectedIndex) { goToDiagnosticLocation(item.diagnostic); } - _getColumns(): Array> { - const {showFileName} = this.props; + _getColumns() { + const { showFileName } = this.props; const filePathColumnWidth = 0.2; - const filePathColumn = showFileName - ? [ - { - key: 'filePath', - title: 'File', - width: filePathColumnWidth, - }, - ] - : []; - return [ - { - component: TypeComponent, - key: 'type', - title: 'Type', - width: 0.05, - }, - { - key: 'providerName', - title: 'Source', - width: 0.1, - }, - ...filePathColumn, - { - key: 'range', - title: 'Line', - width: 0.05, - shouldRightAlign: true, - }, - { - component: DescriptionComponent, - key: 'description', - title: 'Description', - width: showFileName ? 0.6 : 0.6 + filePathColumnWidth, - }, - ]; + const filePathColumn = showFileName ? [{ + key: 'filePath', + title: 'File', + width: filePathColumnWidth + }] : []; + return [{ + component: TypeComponent, + key: 'type', + title: 'Type', + width: 0.05 + }, { + key: 'providerName', + title: 'Source', + width: 0.1 + }, ...filePathColumn, { + key: 'range', + title: 'Line', + width: 0.05, + shouldRightAlign: true + }, { + component: DescriptionComponent, + key: 'description', + title: 'Description', + width: showFileName ? 0.6 : 0.6 + filePathColumnWidth + }]; } - render(): React.Node { - const {diagnostics, showTraces} = this.props; - const {sortedColumn, sortDescending} = this.state; + render() { + const { diagnostics, showTraces } = this.props; + const { sortedColumn, sortDescending } = this.state; const diagnosticRows = diagnostics.map(diagnostic => { return { data: { type: diagnostic.type, providerName: diagnostic.providerName, - filePath: getProjectRelativePathOfDiagnostic(diagnostic), + filePath: (0, (_paneUtils || _load_paneUtils()).getProjectRelativePathOfDiagnostic)(diagnostic), range: diagnostic.range ? diagnostic.range.start.row + 1 : 0, - description: { + description: Object.assign({ showTraces, - diagnostic, - ...getMessageContent(diagnostic, showTraces), - }, - diagnostic, - }, + diagnostic + }, getMessageContent(diagnostic, showTraces)), + diagnostic + } }; }); - let sortedRows = sortDiagnostics( - diagnosticRows, - sortedColumn, - sortDescending, - ); + let sortedRows = (0, (_DiagnosticsSorter || _load_DiagnosticsSorter()).sortDiagnostics)(diagnosticRows, sortedColumn, sortDescending); let maxResultsMessage; if (sortedRows.length > MAX_RESULTS_COUNT) { sortedRows = sortedRows.slice(0, MAX_RESULTS_COUNT); - maxResultsMessage = ( -
- Max results ({MAX_RESULTS_COUNT}) reached. Fix diagnostics or show - only diagnostics for the current file to view more. -
+ maxResultsMessage = _react.createElement( + 'div', + { className: 'highlight-warning diagnostics-ui-table-message' }, + 'Max results (', + MAX_RESULTS_COUNT, + ') reached. Fix diagnostics or show only diagnostics for the current file to view more.' ); } - return ( -
- - {maxResultsMessage} - + 'diagnostics-ui-table-container-empty': sortedRows.length === 0 + }) }, + _react.createElement((_Table || _load_Table()).Table, { + collapsable: true, + columns: this._getColumns(), + emptyComponent: EmptyComponent, + fixedHeader: true, + maxBodyHeight: '99999px', + rows: sortedRows, + sortable: true, + onSort: this._handleSort, + sortedColumn: sortedColumn, + sortDescending: sortDescending, + selectable: true, + onSelect: this._handleSelectTableRow + }), + maxResultsMessage ); } } +exports.default = DiagnosticsTable; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsTraceItem.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsTraceItem.js index 7087e3aa..dc8fa9c5 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsTraceItem.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsTraceItem.js @@ -1,28 +1,23 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import type {DiagnosticTrace} from '../../../atom-ide-diagnostics/lib/types'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DiagnosticsTraceItem = undefined; -import * as React from 'react'; -import {DiagnosticsMessageText} from './DiagnosticsMessageText'; +var _react = _interopRequireWildcard(require('react')); -type DiagnosticsTraceItemProps = { - trace: DiagnosticTrace, - goToLocation: (path: string, line: number) => mixed, -}; +var _DiagnosticsMessageText; + +function _load_DiagnosticsMessageText() { + return _DiagnosticsMessageText = require('./DiagnosticsMessageText'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } // TODO move LESS styles to nuclide-ui -export const DiagnosticsTraceItem = (props: DiagnosticsTraceItemProps) => { - const {trace, goToLocation} = props; +const DiagnosticsTraceItem = exports.DiagnosticsTraceItem = props => { + const { trace, goToLocation } = props; let locSpan = null; // Local variable so that the type refinement holds in the onClick handler. const path = trace.filePath; @@ -33,23 +28,36 @@ export const DiagnosticsTraceItem = (props: DiagnosticsTraceItemProps) => { if (trace.range) { locString += `:${trace.range.start.row + 1}`; } - const onClick = (event: SyntheticMouseEvent<>) => { + const onClick = event => { event.stopPropagation(); goToLocation(path, Math.max(trace.range ? trace.range.start.row : 0, 0)); }; - locSpan = ( - - :{' '} - - {locString} - - + locSpan = _react.createElement( + 'span', + null, + ':', + ' ', + _react.createElement( + 'a', + { href: '#', onClick: onClick }, + locString + ) ); } - return ( -
- - {locSpan} -
+ return _react.createElement( + 'div', + null, + _react.createElement((_DiagnosticsMessageText || _load_DiagnosticsMessageText()).DiagnosticsMessageText, { message: trace }), + locSpan ); -}; +}; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsUi.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsUi.js index 042af035..b939fc34 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsUi.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsUi.js @@ -1,56 +1,69 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {Props} from './ExperimentalDiagnosticsView'; - -import * as React from 'react'; -import featureConfig from 'nuclide-commons-atom/feature-config'; -import DiagnosticsView from './DiagnosticsView'; -import ExperimentalDiagnosticsView from './ExperimentalDiagnosticsView'; - -type UI_OPTION = 'CLASSIC' | 'EXPERIMENTAL'; - -type State = { - uiToShow: ?UI_OPTION, -}; - -export default class DiagnosticsUi extends React.Component { - _configSubscription: rxjs$ISubscription; +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = _interopRequireWildcard(require('react')); + +var _featureConfig; + +function _load_featureConfig() { + return _featureConfig = _interopRequireDefault(require('nuclide-commons-atom/feature-config')); +} + +var _DiagnosticsView; + +function _load_DiagnosticsView() { + return _DiagnosticsView = _interopRequireDefault(require('./DiagnosticsView')); +} + +var _ExperimentalDiagnosticsView; + +function _load_ExperimentalDiagnosticsView() { + return _ExperimentalDiagnosticsView = _interopRequireDefault(require('./ExperimentalDiagnosticsView')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +class DiagnosticsUi extends _react.Component { constructor() { super(); this.state = { - uiToShow: null, + uiToShow: null }; } - componentDidMount(): void { - this._configSubscription = featureConfig - .observeAsStream('atom-ide-diagnostics-ui.useExperimentalUi') - .subscribe(useExperimentalUi => { - this.setState({ - uiToShow: Boolean(useExperimentalUi) ? 'EXPERIMENTAL' : 'CLASSIC', - }); + componentDidMount() { + this._configSubscription = (_featureConfig || _load_featureConfig()).default.observeAsStream('atom-ide-diagnostics-ui.useExperimentalUi').subscribe(useExperimentalUi => { + this.setState({ + uiToShow: Boolean(useExperimentalUi) ? 'EXPERIMENTAL' : 'CLASSIC' }); + }); } - render(): ?React.Node { + render() { switch (this.state.uiToShow) { case null: return null; case 'CLASSIC': - return ; + return _react.createElement((_DiagnosticsView || _load_DiagnosticsView()).default, this.props); case 'EXPERIMENTAL': - return ; + return _react.createElement((_ExperimentalDiagnosticsView || _load_ExperimentalDiagnosticsView()).default, this.props); } } } +exports.default = DiagnosticsUi; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsView.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsView.js index e6ce8743..7bac0f0d 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsView.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/DiagnosticsView.js @@ -1,3 +1,60 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _analytics; + +function _load_analytics() { + return _analytics = _interopRequireDefault(require('nuclide-commons-atom/analytics')); +} + +var _DiagnosticsTable; + +function _load_DiagnosticsTable() { + return _DiagnosticsTable = _interopRequireDefault(require('./DiagnosticsTable')); +} + +var _Checkbox; + +function _load_Checkbox() { + return _Checkbox = require('nuclide-commons-ui/Checkbox'); +} + +var _Toolbar; + +function _load_Toolbar() { + return _Toolbar = require('nuclide-commons-ui/Toolbar'); +} + +var _ToolbarLeft; + +function _load_ToolbarLeft() { + return _ToolbarLeft = require('nuclide-commons-ui/ToolbarLeft'); +} + +var _ToolbarRight; + +function _load_ToolbarRight() { + return _ToolbarRight = require('nuclide-commons-ui/ToolbarRight'); +} + +var _react = _interopRequireWildcard(require('react')); + +var _Button; + +function _load_Button() { + return _Button = require('nuclide-commons-ui/Button'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Dismissable panel that displays the diagnostics from diagnostics-store. + */ /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,59 +63,27 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {NuclideUri} from 'nuclide-commons/nuclideUri'; -import type {DiagnosticMessage} from '../../../atom-ide-diagnostics/lib/types'; - -import analytics from 'nuclide-commons-atom/analytics'; -import DiagnosticsTable from './DiagnosticsTable'; -import {Checkbox} from 'nuclide-commons-ui/Checkbox'; -import {Toolbar} from 'nuclide-commons-ui/Toolbar'; -import {ToolbarLeft} from 'nuclide-commons-ui/ToolbarLeft'; -import {ToolbarRight} from 'nuclide-commons-ui/ToolbarRight'; -import * as React from 'react'; -import {Button, ButtonSizes} from 'nuclide-commons-ui/Button'; - -export type Props = { - diagnostics: Array, - pathToActiveTextEditor: ?NuclideUri, - filterByActiveTextEditor: boolean, - onFilterByActiveTextEditorChange: (isChecked: boolean) => mixed, - showTraces: boolean, - onShowTracesChange: (isChecked: boolean) => mixed, -}; - -/** - * Dismissable panel that displays the diagnostics from diagnostics-store. - */ -export default class DiagnosticsView extends React.Component { - constructor(props: Props) { +class DiagnosticsView extends _react.Component { + constructor(props) { super(props); - (this: any)._onShowTracesChange = this._onShowTracesChange.bind(this); - (this: any)._onFilterByActiveTextEditorChange = this._onFilterByActiveTextEditorChange.bind( - this, - ); - (this: any)._openAllFilesWithErrors = this._openAllFilesWithErrors.bind( - this, - ); + this._onShowTracesChange = this._onShowTracesChange.bind(this); + this._onFilterByActiveTextEditorChange = this._onFilterByActiveTextEditorChange.bind(this); + this._openAllFilesWithErrors = this._openAllFilesWithErrors.bind(this); } - render(): React.Node { - let warningCount: number = 0; + render() { + let warningCount = 0; let errorCount = 0; - let {diagnostics} = this.props; - const {showTraces} = this.props; + let { diagnostics } = this.props; + const { showTraces } = this.props; if (this.props.filterByActiveTextEditor) { const pathToFilterBy = this.props.pathToActiveTextEditor; if (pathToFilterBy !== null) { - diagnostics = diagnostics.filter( - diagnostic => - diagnostic.scope === 'file' && - diagnostic.filePath === pathToFilterBy, - ); + diagnostics = diagnostics.filter(diagnostic => diagnostic.scope === 'file' && diagnostic.filePath === pathToFilterBy); } else { // Current pane is not a text editor; do not show diagnostics. diagnostics = []; @@ -72,90 +97,98 @@ export default class DiagnosticsView extends React.Component { ++warningCount; } }); - const isExpandable = diagnostics.find( - diagnostic => - // flowlint-next-line sketchy-null-string:off - diagnostic.trace || (diagnostic.text && diagnostic.text.includes('\n')), - ); + const isExpandable = diagnostics.find(diagnostic => + // flowlint-next-line sketchy-null-string:off + diagnostic.trace || diagnostic.text && diagnostic.text.includes('\n')); - const errorSpanClassName = `inline-block ${errorCount > 0 - ? 'text-error' - : ''}`; - const warningSpanClassName = `inline-block ${warningCount > 0 - ? 'text-warning' - : ''}`; + const errorSpanClassName = `inline-block ${errorCount > 0 ? 'text-error' : ''}`; + const warningSpanClassName = `inline-block ${warningCount > 0 ? 'text-warning' : ''}`; - return ( -
- - - - Errors: {errorCount} - - - Warnings: {warningCount} - - - - {isExpandable - ? - - - : null} - - - - - - - -
+ width: '100%' + } }, + _react.createElement( + (_Toolbar || _load_Toolbar()).Toolbar, + { location: 'top' }, + _react.createElement( + (_ToolbarLeft || _load_ToolbarLeft()).ToolbarLeft, + null, + _react.createElement( + 'span', + { className: errorSpanClassName }, + 'Errors: ', + errorCount + ), + _react.createElement( + 'span', + { className: warningSpanClassName }, + 'Warnings: ', + warningCount + ) + ), + _react.createElement( + (_ToolbarRight || _load_ToolbarRight()).ToolbarRight, + null, + isExpandable ? _react.createElement( + 'span', + { className: 'inline-block' }, + _react.createElement((_Checkbox || _load_Checkbox()).Checkbox, { + checked: this.props.showTraces, + label: 'Full description', + onChange: this._onShowTracesChange + }) + ) : null, + _react.createElement( + 'span', + { className: 'inline-block' }, + _react.createElement((_Checkbox || _load_Checkbox()).Checkbox, { + checked: this.props.filterByActiveTextEditor, + label: 'Current file only', + onChange: this._onFilterByActiveTextEditorChange + }) + ), + _react.createElement( + (_Button || _load_Button()).Button, + { + onClick: this._openAllFilesWithErrors, + size: (_Button || _load_Button()).ButtonSizes.SMALL, + disabled: diagnostics.length === 0, + className: 'inline-block', + title: 'Open All' }, + 'Open All' + ) + ) + ), + _react.createElement((_DiagnosticsTable || _load_DiagnosticsTable()).default, { + showFileName: !this.props.filterByActiveTextEditor, + diagnostics: diagnostics, + showTraces: showTraces + }) ); } - _onShowTracesChange(isChecked: boolean) { - analytics.track('diagnostics-panel-toggle-show-traces', { - isChecked: isChecked.toString(), + _onShowTracesChange(isChecked) { + (_analytics || _load_analytics()).default.track('diagnostics-panel-toggle-show-traces', { + isChecked: isChecked.toString() }); this.props.onShowTracesChange.call(null, isChecked); } - _onFilterByActiveTextEditorChange(isChecked: boolean) { - analytics.track('diagnostics-panel-toggle-current-file', { - isChecked: isChecked.toString(), + _onFilterByActiveTextEditorChange(isChecked) { + (_analytics || _load_analytics()).default.track('diagnostics-panel-toggle-current-file', { + isChecked: isChecked.toString() }); this.props.onFilterByActiveTextEditorChange.call(null, isChecked); } _openAllFilesWithErrors() { - atom.commands.dispatch( - atom.views.getView(atom.workspace), - 'diagnostics:open-all-files-with-errors', - ); + atom.commands.dispatch(atom.views.getView(atom.workspace), 'diagnostics:open-all-files-with-errors'); } } +exports.default = DiagnosticsView; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/ExperimentalDiagnosticsTable.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/ExperimentalDiagnosticsTable.js index 8bdbe8de..4e119e22 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/ExperimentalDiagnosticsTable.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/ExperimentalDiagnosticsTable.js @@ -1,3 +1,74 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _humanizePath; + +function _load_humanizePath() { + return _humanizePath = _interopRequireDefault(require('nuclide-commons-atom/humanizePath')); +} + +var _react = _interopRequireWildcard(require('react')); + +var _nuclideUri; + +function _load_nuclideUri() { + return _nuclideUri = _interopRequireDefault(require('nuclide-commons/nuclideUri')); +} + +var _goToLocation; + +function _load_goToLocation() { + return _goToLocation = require('nuclide-commons-atom/go-to-location'); +} + +var _Table; + +function _load_Table() { + return _Table = require('nuclide-commons-ui/Table'); +} + +var _sortDiagnostics; + +function _load_sortDiagnostics() { + return _sortDiagnostics = _interopRequireDefault(require('../sortDiagnostics')); +} + +var _DiagnosticsMessage; + +function _load_DiagnosticsMessage() { + return _DiagnosticsMessage = require('./DiagnosticsMessage'); +} + +var _DiagnosticsMessageText; + +function _load_DiagnosticsMessageText() { + return _DiagnosticsMessageText = require('./DiagnosticsMessageText'); +} + +var _Icon; + +function _load_Icon() { + return _Icon = require('nuclide-commons-ui/Icon'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Maximum number of results to render in the table before truncating and displaying a "Max results +// reached" message. + + +// text is always used for sorting, while we render the element. /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,108 +77,36 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type { - DiagnosticMessage, - DiagnosticMessageKind, - DiagnosticMessageType, -} from '../../../atom-ide-diagnostics/lib/types'; -import type {NuclideUri} from 'nuclide-commons/nuclideUri'; -import type {Column, Row} from 'nuclide-commons-ui/Table'; -import type {IconName} from 'nuclide-commons-ui/Icon'; - -import classnames from 'classnames'; -import humanizePath from 'nuclide-commons-atom/humanizePath'; -import * as React from 'react'; -import nuclideUri from 'nuclide-commons/nuclideUri'; -import {goToLocation} from 'nuclide-commons-atom/go-to-location'; -import {Table} from 'nuclide-commons-ui/Table'; -import sortDiagnostics from '../sortDiagnostics'; -import {DiagnosticsMessageNoHeader} from './DiagnosticsMessage'; -import {DiagnosticsMessageText} from './DiagnosticsMessageText'; -import {Icon} from 'nuclide-commons-ui/Icon'; - -// text is always used for sorting, while we render the element. -type DescriptionField = { - diagnostic: DiagnosticMessage, - showTraces: boolean, - text: string, - isPlainText: boolean, -}; - -type Location = {| - fullPath: NuclideUri, - locationInFile: ?{| - basename: string, - line: number, - |}, -|}; - -export type DisplayDiagnostic = { - +classification: { - kind: DiagnosticMessageKind, - severity: DiagnosticMessageType, - }, - +providerName: string, - +description: { - showTraces: boolean, - diagnostic: DiagnosticMessage, - text: string, - isPlainText: boolean, - }, - +dir: string, - +location: ?Location, -}; - -type ColumnName = $Keys; - -// Maximum number of results to render in the table before truncating and displaying a "Max results -// reached" message. const MAX_RESULTS_COUNT = 1000; -type Props = { - diagnostics: Array, - selectedMessage: ?DiagnosticMessage, - gotoMessageLocation: (message: DiagnosticMessage) => void, - showFileName: ?boolean, - showTraces: boolean, -}; - -type State = { - sortDescending: boolean, - sortedColumn: ColumnName, -}; - -export default class ExperimentalDiagnosticsTable extends React.Component< - Props, - State, -> { - constructor(props: Props) { +class ExperimentalDiagnosticsTable extends _react.Component { + constructor(props) { super(props); - (this: any)._handleSort = this._handleSort.bind(this); - (this: any)._handleSelectTableRow = this._handleSelectTableRow.bind(this); + this._handleSort = this._handleSort.bind(this); + this._handleSelectTableRow = this._handleSelectTableRow.bind(this); this.state = { sortDescending: true, - sortedColumn: 'classification', + sortedColumn: 'classification' }; } - _handleSort(sortedColumn: ColumnName, sortDescending: boolean): void { + _handleSort(sortedColumn, sortDescending) { this.setState({ sortedColumn, - sortDescending, + sortDescending }); } - _handleSelectTableRow(item: {diagnostic: DiagnosticMessage}): void { + _handleSelectTableRow(item) { this.props.gotoMessageLocation(item.diagnostic); } - _getColumns(): Array> { - const {showFileName} = this.props; + _getColumns() { + const { showFileName } = this.props; // These need to add up to 1. // TODO: Update the Table component so that we can have more control over this (and provide @@ -116,153 +115,127 @@ export default class ExperimentalDiagnosticsTable extends React.Component< const SOURCE_WIDTH = 0.1; const FILENAME_WIDTH = 0.3; const DIR_WIDTH = 0.15; - const DESCRIPTION_WIDTH = showFileName - ? 1 - (TYPE_WIDTH + SOURCE_WIDTH + FILENAME_WIDTH + DIR_WIDTH) - : 1 - (TYPE_WIDTH + SOURCE_WIDTH); - - const filePathColumns = showFileName - ? [ - { - component: DirComponent, - key: 'dir', - title: 'Path', - width: DIR_WIDTH, - shouldRightAlign: true, - cellClassName: 'nuclide-diagnostics-ui-cell-dir', - }, - { - component: FilenameComponent, - key: 'location', - title: 'File Name', - width: FILENAME_WIDTH, - cellClassName: 'nuclide-diagnostics-ui-cell-filename', - }, - ] - : []; - return [ - { - component: TypeComponent, - key: 'classification', - title: 'Type', - width: TYPE_WIDTH, - cellClassName: 'nuclide-diagnostics-ui-cell-classification', - }, - { - key: 'providerName', - title: 'Source', - width: SOURCE_WIDTH, - }, - { - component: DescriptionComponent, - key: 'description', - title: 'Description', - width: DESCRIPTION_WIDTH, - }, - ...filePathColumns, - ]; + const DESCRIPTION_WIDTH = showFileName ? 1 - (TYPE_WIDTH + SOURCE_WIDTH + FILENAME_WIDTH + DIR_WIDTH) : 1 - (TYPE_WIDTH + SOURCE_WIDTH); + + const filePathColumns = showFileName ? [{ + component: DirComponent, + key: 'dir', + title: 'Path', + width: DIR_WIDTH, + shouldRightAlign: true, + cellClassName: 'nuclide-diagnostics-ui-cell-dir' + }, { + component: FilenameComponent, + key: 'location', + title: 'File Name', + width: FILENAME_WIDTH, + cellClassName: 'nuclide-diagnostics-ui-cell-filename' + }] : []; + return [{ + component: TypeComponent, + key: 'classification', + title: 'Type', + width: TYPE_WIDTH, + cellClassName: 'nuclide-diagnostics-ui-cell-classification' + }, { + key: 'providerName', + title: 'Source', + width: SOURCE_WIDTH + }, { + component: DescriptionComponent, + key: 'description', + title: 'Description', + width: DESCRIPTION_WIDTH + }, ...filePathColumns]; } - render(): React.Node { - const {diagnostics, selectedMessage, showTraces} = this.props; - const {sortedColumn, sortDescending} = this.state; + render() { + const { diagnostics, selectedMessage, showTraces } = this.props; + const { sortedColumn, sortDescending } = this.state; const diagnosticRows = this._getRows(diagnostics, showTraces); - let sortedRows = this._sortRows( - diagnosticRows, - sortedColumn, - sortDescending, - ); + let sortedRows = this._sortRows(diagnosticRows, sortedColumn, sortDescending); let maxResultsMessage; if (sortedRows.length > MAX_RESULTS_COUNT) { sortedRows = sortedRows.slice(0, MAX_RESULTS_COUNT); - maxResultsMessage = ( -
- Max results ({MAX_RESULTS_COUNT}) reached. Fix diagnostics or show - only diagnostics for the current file to view more. -
+ maxResultsMessage = _react.createElement( + 'div', + { className: 'highlight-warning diagnostics-ui-table-message' }, + 'Max results (', + MAX_RESULTS_COUNT, + ') reached. Fix diagnostics or show only diagnostics for the current file to view more.' ); } - const selectedIndex = sortedRows.findIndex( - row => row.data.description.diagnostic === selectedMessage, - ); - return ( -
row.data.description.diagnostic === selectedMessage); + return _react.createElement( + 'div', + { + className: (0, (_classnames || _load_classnames()).default)({ 'diagnostics-ui-table-container': true, - 'diagnostics-ui-table-container-empty': sortedRows.length === 0, - })}> -
- {maxResultsMessage} - + 'diagnostics-ui-table-container-empty': sortedRows.length === 0 + }) }, + _react.createElement((_Table || _load_Table()).Table, { + collapsable: true, + columns: this._getColumns(), + emptyComponent: EmptyComponent, + fixedHeader: true, + maxBodyHeight: '99999px', + rows: sortedRows, + sortable: true, + onSort: this._handleSort, + sortedColumn: sortedColumn, + sortDescending: sortDescending, + selectable: true, + selectedIndex: selectedIndex, + onSelect: this._handleSelectTableRow + }), + maxResultsMessage ); } // TODO: Memoize this so we don't recompute unnecessarily. - _getRows( - diagnostics: Array, - showTraces: boolean, - ): Array> { + _getRows(diagnostics, showTraces) { return diagnostics.map(diagnostic => { - const {dir, location} = getLocation(diagnostic); + const { dir, location } = getLocation(diagnostic); return { data: { classification: { kind: diagnostic.kind || 'lint', - severity: diagnostic.type, + severity: diagnostic.type }, providerName: diagnostic.providerName, - description: { + description: Object.assign({ showTraces, - diagnostic, - ...getMessageContent(diagnostic, showTraces), - }, + diagnostic + }, getMessageContent(diagnostic, showTraces)), dir, location, - diagnostic, - }, + diagnostic + } }; }); } // TODO: Memoize this so we don't recompute unnecessarily. - _sortRows( - rows: Array>, - sortedColumn: $Keys, - descending: boolean, - ): Array> { - return sortDiagnostics(rows, sortedColumn, descending); + _sortRows(rows, sortedColumn, descending) { + return (0, (_sortDiagnostics || _load_sortDiagnostics()).default)(rows, sortedColumn, descending); } } -const EmptyComponent = () => -
No diagnostic messages
; +exports.default = ExperimentalDiagnosticsTable; +const EmptyComponent = () => _react.createElement( + 'div', + { className: 'diagnostics-ui-empty-component' }, + 'No diagnostic messages' +); -type Classification = { - kind: DiagnosticMessageKind, - severity: DiagnosticMessageType, -}; - -function TypeComponent(props: {data: Classification}): React.Element { +function TypeComponent(props) { const classification = props.data; const iconName = getIconName(classification); - return ; + return _react.createElement((_Icon || _load_Icon()).Icon, { icon: iconName }); } -function getIconName(classification: Classification): IconName { - const {kind, severity} = classification; +function getIconName(classification) { + const { kind, severity } = classification; if (kind === 'feedback') { return 'nuclicon-comment-discussion'; } @@ -278,17 +251,11 @@ function getIconName(classification: Classification): IconName { } } -function getMessageContent( - diagnostic: DiagnosticMessage, - showTraces: boolean, -): {text: string, isPlainText: boolean} { +function getMessageContent(diagnostic, showTraces) { let text = ''; let isPlainText = true; const traces = diagnostic.trace || []; - const allMessages: Array<{html?: string, text?: string}> = [ - diagnostic, - ...traces, - ]; + const allMessages = [diagnostic, ...traces]; for (const message of allMessages) { // TODO: A mix of html and text diagnostics will yield a wonky sort ordering. if (message.html != null) { @@ -300,83 +267,87 @@ function getMessageContent( throw new Error('Neither text nor html property defined on message'); } } - return {text: text.trim(), isPlainText}; + return { text: text.trim(), isPlainText }; } -function DescriptionComponent(props: { - data: DescriptionField, -}): React.Element { - const {showTraces, diagnostic, text, isPlainText} = props.data; - return showTraces && diagnostic.scope === 'file' - ? DiagnosticsMessageNoHeader({ - message: diagnostic, - goToLocation, - fixer: () => {}, - }) - : DiagnosticsMessageText({ - preserveNewlines: showTraces, - message: {text, html: isPlainText ? undefined : text}, - }); +function DescriptionComponent(props) { + const { showTraces, diagnostic, text, isPlainText } = props.data; + return showTraces && diagnostic.scope === 'file' ? (0, (_DiagnosticsMessage || _load_DiagnosticsMessage()).DiagnosticsMessageNoHeader)({ + message: diagnostic, + goToLocation: (_goToLocation || _load_goToLocation()).goToLocation, + fixer: () => {} + }) : (0, (_DiagnosticsMessageText || _load_DiagnosticsMessageText()).DiagnosticsMessageText)({ + preserveNewlines: showTraces, + message: { text, html: isPlainText ? undefined : text } + }); } -function DirComponent(props: {data: string}): React.Element { +function DirComponent(props) { return ( // We're abusing `direction: rtl` here so we need the LRM to keep the slash on the right. -
- ‎{humanizePath(props.data, {isDirectory: true})}‎ -
+ _react.createElement( + 'div', + { className: 'nuclide-diagnostics-ui-path-cell' }, + '\u200E', + (0, (_humanizePath || _load_humanizePath()).default)(props.data, { isDirectory: true }), + '\u200E' + ) ); } -function FilenameComponent(props: {data: ?Location}): React.Element { +function FilenameComponent(props) { const locationInFile = props.data && props.data.locationInFile; if (locationInFile == null) { // This is a project diagnostic. - return ; + return _react.createElement( + 'span', + null, + '\u2014' + ); } - const {basename, line} = locationInFile; - return ( - - {basename} - - :{line} - - + const { basename, line } = locationInFile; + return _react.createElement( + 'span', + null, + basename, + _react.createElement( + 'span', + { className: 'nuclide-diagnostics-ui-line-number' }, + ':', + line + ) ); } -function getLocation( - diagnostic: DiagnosticMessage, -): {dir: string, location: ?Location} { - const filePath = - typeof diagnostic.filePath === 'string' ? diagnostic.filePath : null; +function getLocation(diagnostic) { + const filePath = typeof diagnostic.filePath === 'string' ? diagnostic.filePath : null; const line = diagnostic.range ? diagnostic.range.start.row + 1 : 0; if (filePath == null) { return { dir: '', // TODO: Use current working root? - location: null, + location: null }; } - const humanized = humanizePath(filePath); + const humanized = (0, (_humanizePath || _load_humanizePath()).default)(filePath); if (humanized.endsWith('/')) { // It's a directory. return { dir: humanized, location: { fullPath: filePath, - locationInFile: null, - }, + locationInFile: null + } }; } - const {dir, base: basename} = nuclideUri.parsePath(humanized); + const { dir, base: basename } = (_nuclideUri || _load_nuclideUri()).default.parsePath(humanized); return { dir, location: { fullPath: filePath, - locationInFile: {basename, line}, - }, + locationInFile: { basename, line } + } }; -} +} \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/ExperimentalDiagnosticsView.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/ExperimentalDiagnosticsView.js index 5d62a279..751072f7 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/ExperimentalDiagnosticsView.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/ExperimentalDiagnosticsView.js @@ -1,3 +1,72 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _analytics; + +function _load_analytics() { + return _analytics = _interopRequireDefault(require('nuclide-commons-atom/analytics')); +} + +var _ExperimentalDiagnosticsTable; + +function _load_ExperimentalDiagnosticsTable() { + return _ExperimentalDiagnosticsTable = _interopRequireDefault(require('./ExperimentalDiagnosticsTable')); +} + +var _Toolbar; + +function _load_Toolbar() { + return _Toolbar = require('nuclide-commons-ui/Toolbar'); +} + +var _ToolbarLeft; + +function _load_ToolbarLeft() { + return _ToolbarLeft = require('nuclide-commons-ui/ToolbarLeft'); +} + +var _ToolbarRight; + +function _load_ToolbarRight() { + return _ToolbarRight = require('nuclide-commons-ui/ToolbarRight'); +} + +var _react = _interopRequireWildcard(require('react')); + +var _Button; + +function _load_Button() { + return _Button = require('nuclide-commons-ui/Button'); +} + +var _ButtonGroup; + +function _load_ButtonGroup() { + return _ButtonGroup = require('nuclide-commons-ui/ButtonGroup'); +} + +var _FilterButton; + +function _load_FilterButton() { + return _FilterButton = _interopRequireDefault(require('./FilterButton')); +} + +var _RegExpFilter; + +function _load_RegExpFilter() { + return _RegExpFilter = _interopRequireDefault(require('nuclide-commons-ui/RegExpFilter')); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Dismissable panel that displays the diagnostics from nuclide-diagnostics-store. + */ /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,146 +75,104 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {NuclideUri} from 'nuclide-commons/nuclideUri'; -import type {DiagnosticMessage} from '../../../atom-ide-diagnostics/lib/types'; -import type {FilterType} from '../types'; -import type { - RegExpFilterChange, - RegExpFilterValue, -} from 'nuclide-commons-ui/RegExpFilter'; - -import analytics from 'nuclide-commons-atom/analytics'; -import ExperimentalDiagnosticsTable from './ExperimentalDiagnosticsTable'; -import {Toolbar} from 'nuclide-commons-ui/Toolbar'; -import {ToolbarLeft} from 'nuclide-commons-ui/ToolbarLeft'; -import {ToolbarRight} from 'nuclide-commons-ui/ToolbarRight'; -import * as React from 'react'; -import {Button, ButtonSizes} from 'nuclide-commons-ui/Button'; -import {ButtonGroup} from 'nuclide-commons-ui/ButtonGroup'; -import FilterButton from './FilterButton'; -import RegExpFilter from 'nuclide-commons-ui/RegExpFilter'; - -export type Props = { - diagnostics: Array, - pathToActiveTextEditor: ?NuclideUri, - filterByActiveTextEditor: boolean, - onFilterByActiveTextEditorChange: (isChecked: boolean) => mixed, - showTraces: boolean, - onShowTracesChange: (isChecked: boolean) => mixed, - gotoMessageLocation: (message: DiagnosticMessage) => void, - selectedMessage: ?DiagnosticMessage, - - hiddenTypes: Set, - onTypeFilterChange: (type: FilterType) => mixed, - textFilter: RegExpFilterValue, - onTextFilterChange: (change: RegExpFilterChange) => mixed, -}; - -/** - * Dismissable panel that displays the diagnostics from nuclide-diagnostics-store. - */ -export default class ExperimentalDiagnosticsView extends React.Component< - Props, -> { - constructor(props: Props) { +class ExperimentalDiagnosticsView extends _react.Component { + constructor(props) { super(props); - (this: any)._onShowTracesChange = this._onShowTracesChange.bind(this); - (this: any)._onFilterByActiveTextEditorChange = this._onFilterByActiveTextEditorChange.bind( - this, - ); - (this: any)._openAllFilesWithErrors = this._openAllFilesWithErrors.bind( - this, - ); + this._onShowTracesChange = this._onShowTracesChange.bind(this); + this._onFilterByActiveTextEditorChange = this._onFilterByActiveTextEditorChange.bind(this); + this._openAllFilesWithErrors = this._openAllFilesWithErrors.bind(this); } - render(): React.Element { - let {diagnostics} = this.props; - const {showTraces} = this.props; + render() { + let { diagnostics } = this.props; + const { showTraces } = this.props; if (this.props.filterByActiveTextEditor) { const pathToFilterBy = this.props.pathToActiveTextEditor; if (pathToFilterBy !== null) { - diagnostics = diagnostics.filter( - diagnostic => - diagnostic.scope === 'file' && - diagnostic.filePath === pathToFilterBy, - ); + diagnostics = diagnostics.filter(diagnostic => diagnostic.scope === 'file' && diagnostic.filePath === pathToFilterBy); } else { // Current pane is not a text editor; do not show diagnostics. diagnostics = []; } } - return ( -
- - - - {['errors', 'warnings', 'feedback'].map(type => - { - this.props.onTypeFilterChange(type); - }} - />, - )} - - - - - - - - -
+ width: '100%' + } }, + _react.createElement( + (_Toolbar || _load_Toolbar()).Toolbar, + { location: 'top' }, + _react.createElement( + (_ToolbarLeft || _load_ToolbarLeft()).ToolbarLeft, + null, + _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + null, + ['errors', 'warnings', 'feedback'].map(type => _react.createElement((_FilterButton || _load_FilterButton()).default, { + key: type, + type: type, + selected: !this.props.hiddenTypes.has(type), + onClick: () => { + this.props.onTypeFilterChange(type); + } + })) + ) + ), + _react.createElement( + (_ToolbarRight || _load_ToolbarRight()).ToolbarRight, + null, + _react.createElement((_RegExpFilter || _load_RegExpFilter()).default, { + value: this.props.textFilter, + onChange: this.props.onTextFilterChange + }), + _react.createElement( + (_Button || _load_Button()).Button, + { + onClick: this._openAllFilesWithErrors, + size: (_Button || _load_Button()).ButtonSizes.SMALL, + disabled: diagnostics.length === 0, + className: 'inline-block', + title: 'Open All' }, + 'Open All' + ) + ) + ), + _react.createElement((_ExperimentalDiagnosticsTable || _load_ExperimentalDiagnosticsTable()).default, { + showFileName: !this.props.filterByActiveTextEditor, + diagnostics: diagnostics, + showTraces: showTraces, + selectedMessage: this.props.selectedMessage, + gotoMessageLocation: this.props.gotoMessageLocation + }) ); } - _onShowTracesChange(isChecked: boolean) { - analytics.track('diagnostics-panel-toggle-show-traces', { - isChecked: isChecked.toString(), + _onShowTracesChange(isChecked) { + (_analytics || _load_analytics()).default.track('diagnostics-panel-toggle-show-traces', { + isChecked: isChecked.toString() }); this.props.onShowTracesChange.call(null, isChecked); } - _onFilterByActiveTextEditorChange(isChecked: boolean) { - analytics.track('diagnostics-panel-toggle-current-file', { - isChecked: isChecked.toString(), + _onFilterByActiveTextEditorChange(isChecked) { + (_analytics || _load_analytics()).default.track('diagnostics-panel-toggle-current-file', { + isChecked: isChecked.toString() }); this.props.onFilterByActiveTextEditorChange.call(null, isChecked); } _openAllFilesWithErrors() { - atom.commands.dispatch( - atom.views.getView(atom.workspace), - 'diagnostics:open-all-files-with-errors', - ); + atom.commands.dispatch(atom.views.getView(atom.workspace), 'diagnostics:open-all-files-with-errors'); } } +exports.default = ExperimentalDiagnosticsView; \ No newline at end of file diff --git a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/FilterButton.js b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/FilterButton.js index 7ebdf3d8..6639ec94 100644 --- a/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/FilterButton.js +++ b/modules/atom-ide-ui/pkg/atom-ide-diagnostics-ui/lib/ui/FilterButton.js @@ -1,3 +1,20 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = FilterButton; + +var _Button; + +function _load_Button() { + return _Button = require('nuclide-commons-ui/Button'); +} + +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,38 +23,24 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {IconName} from 'nuclide-commons-ui/Icon'; -import type {FilterType} from '../types'; - -import {Button, ButtonSizes} from 'nuclide-commons-ui/Button'; -import * as React from 'react'; - -type Props = {| - type: FilterType, - selected: boolean, - onClick: () => mixed, -|}; - -export default function FilterButton(props: Props): React.Node { - const {selected, type} = props; +function FilterButton(props) { + const { selected, type } = props; const typeName = getFilterTypeDisplayName(type); const title = props.selected ? `Hide ${typeName}` : `Show ${typeName}`; - return ( - - - - - ; - -const ButtonDisabledExample = (): React.Element => - - - - ; - -const ButtonColorExample = (): React.Element => -
- - - - - - - - - - -

selected:

- - - - - - - -
-
; - -const ButtonIconExample = (): React.Element => - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; - -const ButtonToolbarExample = (): React.Element => -
- - - - - - - - - - - -
; - -export const ButtonExamples = { +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ButtonExamples = undefined; + +var _react = _interopRequireWildcard(require('react')); + +var _Button; + +function _load_Button() { + return _Button = require('./Button'); +} + +var _ButtonGroup; + +function _load_ButtonGroup() { + return _ButtonGroup = require('./ButtonGroup'); +} + +var _ButtonToolbar; + +function _load_ButtonToolbar() { + return _ButtonToolbar = require('./ButtonToolbar'); +} + +var _Block; + +function _load_Block() { + return _Block = require('./Block'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const ButtonSizeExample = () => _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Button || _load_Button()).Button, + { className: 'inline-block', size: 'EXTRA_SMALL' }, + 'extra_small' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { className: 'inline-block', size: 'SMALL' }, + 'small' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { className: 'inline-block' }, + 'regular' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { className: 'inline-block', size: 'LARGE' }, + 'large' + ) +); /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const ButtonDisabledExample = () => _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Button || _load_Button()).Button, + { className: 'inline-block' }, + 'enabled' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { className: 'inline-block', disabled: true }, + 'disabled' + ) +); + +const ButtonColorExample = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + null, + _react.createElement( + (_Button || _load_Button()).Button, + { buttonType: 'PRIMARY' }, + 'primary' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { buttonType: 'INFO' }, + 'info' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { buttonType: 'SUCCESS' }, + 'success' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { buttonType: 'WARNING' }, + 'warning' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { buttonType: 'ERROR' }, + 'error' + ) + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + 'p', + null, + 'selected:' + ), + _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + null, + _react.createElement( + (_Button || _load_Button()).Button, + { selected: true, buttonType: 'PRIMARY' }, + 'primary' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { selected: true, buttonType: 'INFO' }, + 'info' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { selected: true, buttonType: 'SUCCESS' }, + 'success' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { selected: true, buttonType: 'WARNING' }, + 'warning' + ), + _react.createElement( + (_Button || _load_Button()).Button, + { selected: true, buttonType: 'ERROR' }, + 'error' + ) + ) + ) +); + +const ButtonIconExample = () => _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + null, + _react.createElement((_Button || _load_Button()).Button, { icon: 'gear' }), + _react.createElement((_Button || _load_Button()).Button, { icon: 'cloud-download' }), + _react.createElement((_Button || _load_Button()).Button, { icon: 'code' }), + _react.createElement((_Button || _load_Button()).Button, { icon: 'check' }), + _react.createElement((_Button || _load_Button()).Button, { icon: 'device-mobile' }), + _react.createElement((_Button || _load_Button()).Button, { icon: 'alert' }) + ) +); + +const ButtonGroupExample = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + { size: 'EXTRA_SMALL' }, + _react.createElement( + (_Button || _load_Button()).Button, + { buttonType: 'SUCCESS' }, + 'extra small' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'button' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'group' + ) + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + { size: 'SMALL' }, + _react.createElement( + (_Button || _load_Button()).Button, + { buttonType: 'SUCCESS' }, + 'small' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'button' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'group' + ) + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + null, + _react.createElement( + (_Button || _load_Button()).Button, + { buttonType: 'SUCCESS' }, + 'regular' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'button' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'group' + ) + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + { size: 'LARGE' }, + _react.createElement( + (_Button || _load_Button()).Button, + { buttonType: 'SUCCESS' }, + 'large' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'button' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'group' + ) + ) + ) +); + +const ButtonToolbarExample = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_ButtonToolbar || _load_ButtonToolbar()).ButtonToolbar, + null, + _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + null, + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'ButtonGroup' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'in a' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'toolbar' + ) + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'single buttons' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'in toolbar' + ) + ) + ) +); + +const ButtonExamples = exports.ButtonExamples = { sectionName: 'Buttons', description: 'For clicking things.', - examples: [ - { - title: 'Button sizes', - component: ButtonSizeExample, - }, - { - title: 'Disabled/enabled', - component: ButtonDisabledExample, - }, - { - title: 'Button colors', - component: ButtonColorExample, - }, - { - title: 'Buttons with icons', - component: ButtonIconExample, - }, - { - title: 'Button Group', - component: ButtonGroupExample, - }, - { - title: 'Button Toolbar', - component: ButtonToolbarExample, - }, - ], -}; + examples: [{ + title: 'Button sizes', + component: ButtonSizeExample + }, { + title: 'Disabled/enabled', + component: ButtonDisabledExample + }, { + title: 'Button colors', + component: ButtonColorExample + }, { + title: 'Buttons with icons', + component: ButtonIconExample + }, { + title: 'Button Group', + component: ButtonGroupExample + }, { + title: 'Button Toolbar', + component: ButtonToolbarExample + }] +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Button.js b/modules/nuclide-commons-ui/Button.js index ac2e37de..f0bb7753 100644 --- a/modules/nuclide-commons-ui/Button.js +++ b/modules/nuclide-commons-ui/Button.js @@ -1,61 +1,66 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Button = exports.ButtonTypes = exports.ButtonSizes = undefined; + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +var _reactDom = _interopRequireDefault(require('react-dom')); + +var _string; + +function _load_string() { + return _string = require('nuclide-commons/string'); +} + +var _addTooltip; + +function _load_addTooltip() { + return _addTooltip = _interopRequireDefault(require('./addTooltip')); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ -import type {IconName} from './Icon'; - -import classnames from 'classnames'; -import * as React from 'react'; -import ReactDOM from 'react-dom'; -import {maybeToString} from 'nuclide-commons/string'; -import addTooltip from './addTooltip'; - -export type ButtonType = 'PRIMARY' | 'INFO' | 'SUCCESS' | 'WARNING' | 'ERROR'; -export type ButtonSize = 'EXTRA_SMALL' | 'SMALL' | 'LARGE'; -type ButtonNodeName = 'button' | 'a'; - -type Props = { - /** Icon name, without the `icon-` prefix. E.g. `'arrow-up'` */ - icon?: IconName, - /** Optional specifier for special buttons, e.g. primary, info, success or error buttons. */ - buttonType?: ButtonType, - selected?: boolean, - /** */ - size?: ButtonSize, - className?: string, - /** The button's content; generally a string. */ - children?: mixed, - /** Allows specifying an element other than `button` to be used as the wrapper node. */ - wrapperElement?: ButtonNodeName, - tooltip?: atom$TooltipsAddOptions, -}; - -export const ButtonSizes = Object.freeze({ +const ButtonSizes = exports.ButtonSizes = Object.freeze({ EXTRA_SMALL: 'EXTRA_SMALL', SMALL: 'SMALL', - LARGE: 'LARGE', + LARGE: 'LARGE' }); -export const ButtonTypes = Object.freeze({ +const ButtonTypes = exports.ButtonTypes = Object.freeze({ PRIMARY: 'PRIMARY', INFO: 'INFO', SUCCESS: 'SUCCESS', WARNING: 'WARNING', - ERROR: 'ERROR', + ERROR: 'ERROR' }); const ButtonSizeClassnames = Object.freeze({ EXTRA_SMALL: 'btn-xs', SMALL: 'btn-sm', - LARGE: 'btn-lg', + LARGE: 'btn-lg' }); const ButtonTypeClassnames = Object.freeze({ @@ -63,15 +68,15 @@ const ButtonTypeClassnames = Object.freeze({ INFO: 'btn-info', SUCCESS: 'btn-success', WARNING: 'btn-warning', - ERROR: 'btn-error', + ERROR: 'btn-error' }); /** * Generic Button wrapper. */ -export class Button extends React.Component { - focus(): void { - const node = ReactDOM.findDOMNode(this); +class Button extends _react.Component { + focus() { + const node = _reactDom.default.findDOMNode(this); if (node == null) { return; } @@ -79,8 +84,9 @@ export class Button extends React.Component { node.focus(); } - render(): React.Node { - const { + render() { + const _props = this.props, + { icon, buttonType, selected, @@ -88,25 +94,27 @@ export class Button extends React.Component { children, className, wrapperElement, - tooltip, - ...remainingProps - } = this.props; + tooltip + } = _props, + remainingProps = _objectWithoutProperties(_props, ['icon', 'buttonType', 'selected', 'size', 'children', 'className', 'wrapperElement', 'tooltip']); const sizeClassname = size == null ? '' : ButtonSizeClassnames[size] || ''; - const buttonTypeClassname = - buttonType == null ? '' : ButtonTypeClassnames[buttonType] || ''; - const ref = tooltip ? addTooltip(tooltip) : null; - const newClassName = classnames(className, 'btn', { - [`icon icon-${maybeToString(icon)}`]: icon != null, + const buttonTypeClassname = buttonType == null ? '' : ButtonTypeClassnames[buttonType] || ''; + const ref = tooltip ? (0, (_addTooltip || _load_addTooltip()).default)(tooltip) : null; + const newClassName = (0, (_classnames || _load_classnames()).default)(className, 'btn', { + [`icon icon-${(0, (_string || _load_string()).maybeToString)(icon)}`]: icon != null, [sizeClassname]: size != null, selected, - [buttonTypeClassname]: buttonType != null, + [buttonTypeClassname]: buttonType != null }); const Wrapper = wrapperElement == null ? 'button' : wrapperElement; return ( // $FlowFixMe(>=0.53.0) Flow suppress - - {children} - + _react.createElement( + Wrapper, + Object.assign({ className: newClassName, ref: ref }, remainingProps), + children + ) ); } } +exports.Button = Button; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/ButtonGroup.js b/modules/nuclide-commons-ui/ButtonGroup.js index 6bc61488..9aca6a04 100644 --- a/modules/nuclide-commons-ui/ButtonGroup.js +++ b/modules/nuclide-commons-ui/ButtonGroup.js @@ -1,3 +1,22 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ButtonGroup = exports.ButtonGroupSizes = undefined; + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,49 +25,37 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import classnames from 'classnames'; -import * as React from 'react'; - -type ButtonGroupSize = 'EXTRA_SMALL' | 'SMALL' | 'LARGE'; - -type Props = { - /** The size of the buttons within the group. Overrides any `size` props on child buttons. */ - size?: ButtonGroupSize, - /** The contents of the ButtonGroup; Generally, an instance of `Button`. */ - children?: mixed, - className?: string, -}; - -export const ButtonGroupSizes = Object.freeze({ +const ButtonGroupSizes = exports.ButtonGroupSizes = Object.freeze({ EXTRA_SMALL: 'EXTRA_SMALL', SMALL: 'SMALL', - LARGE: 'LARGE', + LARGE: 'LARGE' }); const ButtonGroupSizeClassnames = Object.freeze({ EXTRA_SMALL: 'btn-group-xs', SMALL: 'btn-group-sm', - LARGE: 'btn-group-lg', + LARGE: 'btn-group-lg' }); /** * Visually groups Buttons passed in as children. */ -export const ButtonGroup = (props: Props) => { - const {size, children, className} = props; - const sizeClassName = - size == null ? '' : ButtonGroupSizeClassnames[size] || ''; - const newClassName = classnames(className, 'btn-group', 'nuclide-btn-group', { - [sizeClassName]: size != null, +const ButtonGroup = exports.ButtonGroup = props => { + const { size, children, className } = props; + const sizeClassName = size == null ? '' : ButtonGroupSizeClassnames[size] || ''; + const newClassName = (0, (_classnames || _load_classnames()).default)(className, 'btn-group', 'nuclide-btn-group', { + [sizeClassName]: size != null }); return ( // $FlowFixMe(>=0.53.0) Flow suppress -
- {children} -
+ _react.createElement( + 'div', + { className: newClassName }, + children + ) ); -}; +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/ButtonToolbar.js b/modules/nuclide-commons-ui/ButtonToolbar.js index aa1eb706..cc2c1f11 100644 --- a/modules/nuclide-commons-ui/ButtonToolbar.js +++ b/modules/nuclide-commons-ui/ButtonToolbar.js @@ -1,3 +1,25 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ButtonToolbar = undefined; + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Visually groups Buttons passed in as children. + */ /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,27 +28,18 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import classnames from 'classnames'; -import * as React from 'react'; - -type Props = { - className?: string, - children?: mixed, -}; - -/** - * Visually groups Buttons passed in as children. - */ -export const ButtonToolbar = (props: Props) => { - const {children, className} = props; +const ButtonToolbar = exports.ButtonToolbar = props => { + const { children, className } = props; return ( // $FlowFixMe(>=0.53.0) Flow suppress -
- {children} -
+ _react.createElement( + 'div', + { className: (0, (_classnames || _load_classnames()).default)('btn-toolbar', className) }, + children + ) ); -}; +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Checkbox.example.js b/modules/nuclide-commons-ui/Checkbox.example.js index a2e65d1d..680a9471 100644 --- a/modules/nuclide-commons-ui/Checkbox.example.js +++ b/modules/nuclide-commons-ui/Checkbox.example.js @@ -1,75 +1,101 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import * as React from 'react'; -import {Block} from './Block'; -import {Checkbox} from './Checkbox'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.CheckboxExamples = undefined; -const NOOP = () => {}; +var _react = _interopRequireWildcard(require('react')); -const CheckboxExample = (): React.Element => -
- - - - - - - - - - - - - - - -
; +var _Block; -export const CheckboxExamples = { +function _load_Block() { + return _Block = require('./Block'); +} + +var _Checkbox; + +function _load_Checkbox() { + return _Checkbox = require('./Checkbox'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const NOOP = () => {}; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const CheckboxExample = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_Checkbox || _load_Checkbox()).Checkbox, { + checked: false, + onClick: NOOP, + onChange: NOOP, + label: 'A Checkbox.' + }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_Checkbox || _load_Checkbox()).Checkbox, { + onClick: NOOP, + onChange: NOOP, + checked: true, + label: 'A checked Checkbox.' + }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_Checkbox || _load_Checkbox()).Checkbox, { + onClick: NOOP, + onChange: NOOP, + disabled: true, + checked: false, + label: 'A disabled Checkbox.' + }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_Checkbox || _load_Checkbox()).Checkbox, { + onClick: NOOP, + onChange: NOOP, + checked: true, + disabled: true, + label: 'A disabled, checked Checkbox.' + }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_Checkbox || _load_Checkbox()).Checkbox, { + onClick: NOOP, + onChange: NOOP, + indeterminate: true, + checked: false, + label: 'An indeterminate Checkbox.' + }) + ) +); + +const CheckboxExamples = exports.CheckboxExamples = { sectionName: 'Checkbox', description: '', - examples: [ - { - title: '', - component: CheckboxExample, - }, - ], -}; + examples: [{ + title: '', + component: CheckboxExample + }] +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Checkbox.js b/modules/nuclide-commons-ui/Checkbox.js index d39c3dd5..4fd17c04 100644 --- a/modules/nuclide-commons-ui/Checkbox.js +++ b/modules/nuclide-commons-ui/Checkbox.js @@ -1,59 +1,45 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Checkbox = undefined; + +var _react = _interopRequireWildcard(require('react')); + +var _reactDom = _interopRequireDefault(require('react-dom')); + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _addTooltip; -import * as React from 'react'; -import ReactDOM from 'react-dom'; -import classnames from 'classnames'; -import addTooltip from './addTooltip'; - -import ignoreTextSelectionEvents from './ignoreTextSelectionEvents'; - -type DefaultProps = { - disabled: boolean, - indeterminate: boolean, - label: string, - onClick: (event: SyntheticMouseEvent<>) => mixed, - onMouseDown: (event: SyntheticMouseEvent<>) => mixed, -}; - -type Props = { - className?: string, - checked: boolean, - disabled: boolean, - indeterminate: boolean, - label: string, - onChange: (isChecked: boolean) => mixed, - onClick: (event: SyntheticMouseEvent<>) => mixed, - tooltip?: atom$TooltipsAddOptions, - title?: ?string, - onMouseDown: (event: SyntheticMouseEvent<>) => mixed, -}; +function _load_addTooltip() { + return _addTooltip = _interopRequireDefault(require('./addTooltip')); +} + +var _ignoreTextSelectionEvents; + +function _load_ignoreTextSelectionEvents() { + return _ignoreTextSelectionEvents = _interopRequireDefault(require('./ignoreTextSelectionEvents')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } /** * A checkbox component with an input checkbox and a label. We restrict the label to a string * to ensure this component is pure. */ -export class Checkbox extends React.PureComponent { - static defaultProps: DefaultProps = { - disabled: false, - indeterminate: false, - label: '', - onClick(event) {}, - onMouseDown(event) {}, - }; - - constructor(props: Props) { +class Checkbox extends _react.PureComponent { + + constructor(props) { super(props); - (this: any)._onChange = this._onChange.bind(this); + this._onChange = this._onChange.bind(this); } componentDidMount() { @@ -64,8 +50,8 @@ export class Checkbox extends React.PureComponent { this._setIndeterminate(); } - _onChange(event: SyntheticEvent<>) { - const isChecked = ((event.target: any): HTMLInputElement).checked; + _onChange(event) { + const isChecked = event.target.checked; this.props.onChange.call(null, isChecked); } @@ -75,14 +61,12 @@ export class Checkbox extends React.PureComponent { * * @see https://www.w3.org/TR/html5/forms.html#the-input-element */ - _setIndeterminate(): void { + _setIndeterminate() { // $FlowFixMe - ReactDOM.findDOMNode( - this.refs.input, - ).indeterminate = this.props.indeterminate; + _reactDom.default.findDOMNode(this.refs.input).indeterminate = this.props.indeterminate; } - render(): React.Node { + render() { const { checked, className, @@ -93,35 +77,54 @@ export class Checkbox extends React.PureComponent { onClick, tooltip, title, - onMouseDown, + onMouseDown } = this.props; - const ref = tooltip ? addTooltip(tooltip) : null; - const text = - label === '' - ? null - : - {' '}{label} - ; - return ( - + const ref = tooltip ? (0, (_addTooltip || _load_addTooltip()).default)(tooltip) : null; + const text = label === '' ? null : _react.createElement( + 'span', + { className: 'nuclide-ui-checkbox-label-text' }, + ' ', + label + ); + return _react.createElement( + 'label', + { + className: (0, (_classnames || _load_classnames()).default)(className, 'nuclide-ui-checkbox-label', { + 'nuclide-ui-checkbox-disabled': disabled + }), + ref: ref, + onClick: onClick && (0, (_ignoreTextSelectionEvents || _load_ignoreTextSelectionEvents()).default)(onClick), + title: title }, + _react.createElement('input', { + checked: checked, + className: 'input-checkbox nuclide-ui-checkbox', + disabled: disabled, + onChange: this._onChange, + onMouseDown: onMouseDown, + ref: 'input', + type: 'checkbox' + }), + text ); } } +exports.Checkbox = Checkbox; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +Checkbox.defaultProps = { + disabled: false, + indeterminate: false, + label: '', + onClick(event) {}, + onMouseDown(event) {} +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/ClickOutsideBoundary.js b/modules/nuclide-commons-ui/ClickOutsideBoundary.js index ee0c0f72..1dca4a6a 100644 --- a/modules/nuclide-commons-ui/ClickOutsideBoundary.js +++ b/modules/nuclide-commons-ui/ClickOutsideBoundary.js @@ -1,35 +1,58 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import * as React from 'react'; -import {findDOMNode} from 'react-dom'; +Object.defineProperty(exports, "__esModule", { + value: true +}); -type Props = { - onClickOutside: ?() => void, - children: ?React.Element, -}; +var _react = _interopRequireWildcard(require('react')); -export default class ClickOutsideBoundary extends React.Component { - _lastInternalEvent: ?MouseEvent; - _node: null | Element | Text; +var _reactDom = require('react-dom'); - constructor(props: Props) { +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +class ClickOutsideBoundary extends _react.Component { + + constructor(props) { super(props); + + this._handleDocumentClick = e => { + // A more straight-forward approach would be to use + // `this._node.contains(e.target)`, however that fails in the edge case were + // some other event handler causes the target to be removed from the DOM + // before the event reaches the document root. So instead, we use this + // reference comparison approach which works for all cases where an event + // passed trough the boundary node, and makes it all the way to the document + // root. + if (e !== this._lastInternalEvent) { + if (this.props.onClickOutside != null) { + this.props.onClickOutside(); + } + } + this._lastInternalEvent = null; + }; + + this._handleInternalClick = e => { + this._lastInternalEvent = e; + }; + this._lastInternalEvent = null; this._node = null; } componentDidMount() { - const node = (this._node = findDOMNode(this)); + const node = this._node = (0, _reactDom.findDOMNode)(this); if (node == null) { return; } @@ -41,26 +64,6 @@ export default class ClickOutsideBoundary extends React.Component { node.addEventListener('click', this._handleInternalClick); } - _handleDocumentClick = (e: MouseEvent) => { - // A more straight-forward approach would be to use - // `this._node.contains(e.target)`, however that fails in the edge case were - // some other event handler causes the target to be removed from the DOM - // before the event reaches the document root. So instead, we use this - // reference comparison approach which works for all cases where an event - // passed trough the boundary node, and makes it all the way to the document - // root. - if (e !== this._lastInternalEvent) { - if (this.props.onClickOutside != null) { - this.props.onClickOutside(); - } - } - this._lastInternalEvent = null; - }; - - _handleInternalClick = (e: MouseEvent) => { - this._lastInternalEvent = e; - }; - componentWillUnmount() { window.document.removeEventListener('click', this._handleDocumentClick); if (this._node != null) { @@ -69,7 +72,10 @@ export default class ClickOutsideBoundary extends React.Component { } render() { - const {onClickOutside, ...passThroughProps} = this.props; - return
; + const _props = this.props, + { onClickOutside } = _props, + passThroughProps = _objectWithoutProperties(_props, ['onClickOutside']); + return _react.createElement('div', passThroughProps); } } +exports.default = ClickOutsideBoundary; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/CodeSnippet.js b/modules/nuclide-commons-ui/CodeSnippet.js index 67129a95..15e89824 100644 --- a/modules/nuclide-commons-ui/CodeSnippet.js +++ b/modules/nuclide-commons-ui/CodeSnippet.js @@ -1,3 +1,20 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.CodeSnippet = undefined; + +var _AtomInput; + +function _load_AtomInput() { + return _AtomInput = require('./AtomInput'); +} + +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,27 +23,14 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import {AtomInput} from './AtomInput'; -import * as React from 'react'; - -type Props = { - text: string, - grammar?: atom$Grammar, - highlights?: Array, - startLine: number, - endLine: number, - onClick: (event: SyntheticMouseEvent<>) => mixed, - onLineClick: (event: SyntheticMouseEvent<>, line: number) => mixed, -}; - -export class CodeSnippet extends React.Component { +class CodeSnippet extends _react.Component { componentDidMount() { const editor = this.refs.editor.getTextEditor(); - const {grammar, highlights, startLine} = this.props; + const { grammar, highlights, startLine } = this.props; if (grammar) { editor.setGrammar(grammar); @@ -34,50 +38,47 @@ export class CodeSnippet extends React.Component { if (highlights != null) { highlights.forEach(range => { - const marker = editor.markBufferRange([ - [range.start.row - startLine, range.start.column], - [range.end.row - startLine, range.end.column], - ]); + const marker = editor.markBufferRange([[range.start.row - startLine, range.start.column], [range.end.row - startLine, range.end.column]]); editor.decorateMarker(marker, { type: 'highlight', - class: 'code-snippet-highlight', + class: 'code-snippet-highlight' }); }); // Make sure at least one highlight is visible. if (highlights.length > 0) { - editor.scrollToBufferPosition([ - highlights[0].end.row - startLine + 1, - highlights[0].end.column, - ]); + editor.scrollToBufferPosition([highlights[0].end.row - startLine + 1, highlights[0].end.column]); } } } - render(): React.Node { + render() { const lineNumbers = []; for (let i = this.props.startLine; i <= this.props.endLine; i++) { - lineNumbers.push( -
this.props.onLineClick(evt, i)}> - {i + 1} -
, - ); + lineNumbers.push(_react.createElement( + 'div', + { + key: i, + className: 'nuclide-ui-code-snippet-line-number', + onClick: evt => this.props.onLineClick(evt, i) }, + i + 1 + )); } - return ( -
-
- {lineNumbers} -
- -
+ return _react.createElement( + 'div', + { className: 'nuclide-ui-code-snippet' }, + _react.createElement( + 'div', + { className: 'nuclide-ui-code-snippet-line-number-column' }, + lineNumbers + ), + _react.createElement((_AtomInput || _load_AtomInput()).AtomInput, { + ref: 'editor', + initialValue: this.props.text, + disabled: true, + onClick: this.props.onClick + }) ); } } +exports.CodeSnippet = CodeSnippet; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/EmptyState.js b/modules/nuclide-commons-ui/EmptyState.js index a83f4777..92637f64 100644 --- a/modules/nuclide-commons-ui/EmptyState.js +++ b/modules/nuclide-commons-ui/EmptyState.js @@ -1,33 +1,40 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +"use strict"; -import * as React from 'react'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.EmptyState = undefined; -type Props = { - title: string, - message: string, -}; +var _react = _interopRequireWildcard(require("react")); -export class EmptyState extends React.Component { - render(): React.Node { - return ( -
-
-

- {this.props.title} -

- {this.props.message} -
-
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +class EmptyState extends _react.Component { + render() { + return _react.createElement( + "div", + { className: "nuclide-ui-empty-state-container" }, + _react.createElement( + "div", + { className: "nuclide-ui-empty-state-message" }, + _react.createElement( + "h1", + null, + this.props.title + ), + this.props.message + ) ); } } +exports.EmptyState = EmptyState; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Highlight.example.js b/modules/nuclide-commons-ui/Highlight.example.js index 5b91122f..f1443aef 100644 --- a/modules/nuclide-commons-ui/Highlight.example.js +++ b/modules/nuclide-commons-ui/Highlight.example.js @@ -1,46 +1,91 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import * as React from 'react'; -import {Block} from './Block'; -import {Highlight, HighlightColors} from './Highlight'; - -const HighlightExample = (): React.Element => -
- - Default - - - Info - - - Success - - - Warning - - - Error - -
; - -export const HighlightExamples = { +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.HighlightExamples = undefined; + +var _react = _interopRequireWildcard(require('react')); + +var _Block; + +function _load_Block() { + return _Block = require('./Block'); +} + +var _Highlight; + +function _load_Highlight() { + return _Highlight = require('./Highlight'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const HighlightExample = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Highlight || _load_Highlight()).Highlight, + null, + 'Default' + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Highlight || _load_Highlight()).Highlight, + { color: (_Highlight || _load_Highlight()).HighlightColors.info }, + 'Info' + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Highlight || _load_Highlight()).Highlight, + { color: (_Highlight || _load_Highlight()).HighlightColors.success }, + 'Success' + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Highlight || _load_Highlight()).Highlight, + { color: (_Highlight || _load_Highlight()).HighlightColors.warning }, + 'Warning' + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Highlight || _load_Highlight()).Highlight, + { color: (_Highlight || _load_Highlight()).HighlightColors.error }, + 'Error' + ) + ) +); /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const HighlightExamples = exports.HighlightExamples = { sectionName: 'Highlight', - description: - 'Highlights are useful for calling out inline content, such as tags.', - examples: [ - { - title: 'Highlights', - component: HighlightExample, - }, - ], -}; + description: 'Highlights are useful for calling out inline content, such as tags.', + examples: [{ + title: 'Highlights', + component: HighlightExample + }] +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Highlight.js b/modules/nuclide-commons-ui/Highlight.js index 76b9db67..9447de86 100644 --- a/modules/nuclide-commons-ui/Highlight.js +++ b/modules/nuclide-commons-ui/Highlight.js @@ -1,37 +1,40 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import classnames from 'classnames'; -import * as React from 'react'; - -export type HighlightColor = - | 'default' - | 'info' - | 'success' - | 'warning' - | 'error'; - -type Props = { - className?: string, - color?: HighlightColor, - children: React.Node, -}; +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Highlight = exports.HighlightColors = undefined; + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ -export const HighlightColors = Object.freeze({ +const HighlightColors = exports.HighlightColors = Object.freeze({ default: 'default', info: 'info', success: 'success', warning: 'warning', - error: 'error', + error: 'error' }); const HighlightColorClassNames = Object.freeze({ @@ -39,17 +42,18 @@ const HighlightColorClassNames = Object.freeze({ info: 'highlight-info', success: 'highlight-success', warning: 'highlight-warning', - error: 'highlight-error', + error: 'highlight-error' }); -export const Highlight = (props: Props) => { - const {className, color, children, ...remainingProps} = props; - const colorClassName = - HighlightColorClassNames[color == null ? 'default' : color]; - const newClassName = classnames(colorClassName, className); - return ( - - {children} - +const Highlight = props => { + const { className, color, children } = props, + remainingProps = _objectWithoutProperties(props, ['className', 'color', 'children']); + const colorClassName = HighlightColorClassNames[color == null ? 'default' : color]; + const newClassName = (0, (_classnames || _load_classnames()).default)(colorClassName, className); + return _react.createElement( + 'span', + Object.assign({ className: newClassName }, remainingProps), + children ); }; +exports.Highlight = Highlight; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Icon.example.js b/modules/nuclide-commons-ui/Icon.example.js index 9ff23526..d4b01179 100644 --- a/modules/nuclide-commons-ui/Icon.example.js +++ b/modules/nuclide-commons-ui/Icon.example.js @@ -1,54 +1,92 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import * as React from 'react'; -import {Block} from './Block'; -import {Icon} from './Icon'; - -const IconExample = (): React.Element => -
- - - - - -
; - -const IconWithTextExample = (): React.Element => -
- -
- gift -
-
- heart -
-
- info -
-
-
; - -export const IconExamples = { +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.IconExamples = undefined; + +var _react = _interopRequireWildcard(require('react')); + +var _Block; + +function _load_Block() { + return _Block = require('./Block'); +} + +var _Icon; + +function _load_Icon() { + return _Icon = require('./Icon'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const IconExample = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_Icon || _load_Icon()).Icon, { icon: 'gift' }), + _react.createElement((_Icon || _load_Icon()).Icon, { icon: 'heart' }), + _react.createElement((_Icon || _load_Icon()).Icon, { icon: 'info' }) + ) +); /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const IconWithTextExample = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + 'div', + null, + _react.createElement( + (_Icon || _load_Icon()).Icon, + { icon: 'gift' }, + 'gift' + ) + ), + _react.createElement( + 'div', + null, + _react.createElement( + (_Icon || _load_Icon()).Icon, + { icon: 'heart' }, + 'heart' + ) + ), + _react.createElement( + 'div', + null, + _react.createElement( + (_Icon || _load_Icon()).Icon, + { icon: 'info' }, + 'info' + ) + ) + ) +); + +const IconExamples = exports.IconExamples = { sectionName: 'Icons', description: 'Octicons with optional text.', - examples: [ - { - title: 'Icons', - component: IconExample, - }, - { - title: 'You can pass optional text as children.', - component: IconWithTextExample, - }, - ], -}; + examples: [{ + title: 'Icons', + component: IconExample + }, { + title: 'You can pass optional text as children.', + component: IconWithTextExample + }] +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Icon.js b/modules/nuclide-commons-ui/Icon.js index 0d9084f4..7d4a3376 100644 --- a/modules/nuclide-commons-ui/Icon.js +++ b/modules/nuclide-commons-ui/Icon.js @@ -1,62 +1,45 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import classnames from 'classnames'; -import * as React from 'react'; - -export type Nuclicon = - | 'nuclicon-nuclide' - | 'nuclicon-react' - | 'nuclicon-buck' - | 'nuclicon-hhvm' - | 'nuclicon-hack' - | 'nuclicon-relay' - | 'nuclicon-swift' - | 'nuclicon-file-directory' - | 'nuclicon-file-directory-starred' - | 'nuclicon-debugger' - | 'nuclicon-arrow-down' - | 'nuclicon-bug' - | 'nuclicon-graphql' - | 'nuclicon-comment-discussion' - | 'nuclicon-comment' - | 'nuclicon-jest-outline' - | 'nuclicon-flow' - | 'nuclicon-react-devtools' - | 'nuclicon-funnel' - | 'nuclicon-stop'; - -export type IconName = Nuclicon | atom$Octicon; - -type Props = { - /** Icon name, without the `icon-` prefix. E.g. `'arrow-up'` */ - icon: IconName, - className?: string, - /** Optional text content to render next to the icon. */ - children?: string, -}; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Icon = undefined; + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ /** * Renders an icon with optional text next to it. */ -export const Icon = (props: Props) => { - const {icon, children, className, ...remainingProps} = props; - const newClassName = classnames( - className, - icon == null ? null : `icon icon-${icon}`, - ); - return ( - - {children} - +const Icon = props => { + const { icon, children, className } = props, + remainingProps = _objectWithoutProperties(props, ['icon', 'children', 'className']); + const newClassName = (0, (_classnames || _load_classnames()).default)(className, icon == null ? null : `icon icon-${icon}`); + return _react.createElement( + 'span', + Object.assign({ className: newClassName }, remainingProps), + children ); }; +exports.Icon = Icon; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/LoadingSpinner.js b/modules/nuclide-commons-ui/LoadingSpinner.js index 7876f9c0..cd349d48 100644 --- a/modules/nuclide-commons-ui/LoadingSpinner.js +++ b/modules/nuclide-commons-ui/LoadingSpinner.js @@ -1,88 +1,85 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.LoadingSpinner = exports.LoadingSpinnerSizes = undefined; + +var _addTooltip; + +function _load_addTooltip() { + return _addTooltip = _interopRequireDefault(require('./addTooltip')); +} -import addTooltip from './addTooltip'; -import classnames from 'classnames'; -import * as React from 'react'; - -type LoadingSpinnerSize = 'EXTRA_SMALL' | 'SMALL' | 'MEDIUM' | 'LARGE'; -type Props = { - className?: string, - /** The size of the LoadingSpinner. Defaults to MEDIUM. */ - size?: LoadingSpinnerSize, - /** - * An optional delay (in milliseconds) between mounting the component and actually rendering - * the spinner to avoid UI churn. - */ - delay?: number, - tooltip?: atom$TooltipsAddOptions, -}; - -export const LoadingSpinnerSizes = Object.freeze({ +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const LoadingSpinnerSizes = exports.LoadingSpinnerSizes = Object.freeze({ EXTRA_SMALL: 'EXTRA_SMALL', SMALL: 'SMALL', MEDIUM: 'MEDIUM', - LARGE: 'LARGE', -}); + LARGE: 'LARGE' +}); /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ const LoadingSpinnerClassnames = Object.freeze({ EXTRA_SMALL: 'loading-spinner-tiny', SMALL: 'loading-spinner-small', MEDIUM: 'loading-spinner-medium', - LARGE: 'loading-spinner-large', + LARGE: 'loading-spinner-large' }); /** * Shows an indefinite, animated LoadingSpinner. */ -export class LoadingSpinner extends React.Component< - Props, - {shouldRender: boolean}, -> { - _timeout: ?number; +class LoadingSpinner extends _react.Component { - constructor(props: Props) { + constructor(props) { super(props); - this.state = {shouldRender: !this.props.delay}; + this.state = { shouldRender: !this.props.delay }; } - componentDidMount(): void { + componentDidMount() { if (!this.state.shouldRender) { - this._timeout = setTimeout( - () => this.setState({shouldRender: true}), - this.props.delay, - ); + this._timeout = setTimeout(() => this.setState({ shouldRender: true }), this.props.delay); } } - componentWillUnmount(): void { + componentWillUnmount() { if (this._timeout != null) { clearTimeout(this._timeout); } } - render(): React.Node { - const {className, size, tooltip} = this.props; + render() { + const { className, size, tooltip } = this.props; if (!this.state.shouldRender) { return null; } - const ref = tooltip ? addTooltip(tooltip) : null; - const safeSize = - size != null && LoadingSpinnerSizes.hasOwnProperty(size) - ? size - : LoadingSpinnerSizes.MEDIUM; + const ref = tooltip ? (0, (_addTooltip || _load_addTooltip()).default)(tooltip) : null; + const safeSize = size != null && LoadingSpinnerSizes.hasOwnProperty(size) ? size : LoadingSpinnerSizes.MEDIUM; const sizeClassname = LoadingSpinnerClassnames[safeSize]; - const newClassName = classnames(className, 'loading', sizeClassname); - return
; + const newClassName = (0, (_classnames || _load_classnames()).default)(className, 'loading', sizeClassname); + return _react.createElement('div', { className: newClassName, ref: ref }); } } +exports.LoadingSpinner = LoadingSpinner; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Message.example.js b/modules/nuclide-commons-ui/Message.example.js index 2aa06321..ee6b8f17 100644 --- a/modules/nuclide-commons-ui/Message.example.js +++ b/modules/nuclide-commons-ui/Message.example.js @@ -1,62 +1,120 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import * as React from 'react'; -import {Block} from './Block'; -import {Message, MessageTypes} from './Message'; - -const MessageExample = (): React.Element => -
- - {/* $FlowFixMe(>=0.53.0) Flow suppress */} - -

Message

- Hello, I'm a simple message. -
-
- - {/* $FlowFixMe(>=0.53.0) Flow suppress */} - - Hello I'm an info message. - - - - {/* $FlowFixMe(>=0.53.0) Flow suppress */} - - Hello I'm a success message. - - - - {/* $FlowFixMe(>=0.53.0) Flow suppress */} - - Hello I'm a warning message. - - - - {/* $FlowFixMe(>=0.53.0) Flow suppress */} - - Hello I'm an error message. - - -
; - -export const MessageExamples = { +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.MessageExamples = undefined; + +var _react = _interopRequireWildcard(require('react')); + +var _Block; + +function _load_Block() { + return _Block = require('./Block'); +} + +var _Message; + +function _load_Message() { + return _Message = require('./Message'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const MessageExample = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Message || _load_Message()).Message, + null, + _react.createElement( + 'h2', + null, + 'Message' + ), + 'Hello, I\'m a simple message.' + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Message || _load_Message()).Message, + { type: (_Message || _load_Message()).MessageTypes.info }, + 'Hello I\'m an ', + _react.createElement( + 'strong', + null, + 'info' + ), + ' message.' + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Message || _load_Message()).Message, + { type: (_Message || _load_Message()).MessageTypes.success }, + 'Hello I\'m a ', + _react.createElement( + 'strong', + null, + 'success' + ), + ' message.' + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Message || _load_Message()).Message, + { type: (_Message || _load_Message()).MessageTypes.warning }, + 'Hello I\'m a ', + _react.createElement( + 'strong', + null, + 'warning' + ), + ' message.' + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Message || _load_Message()).Message, + { type: (_Message || _load_Message()).MessageTypes.error }, + 'Hello I\'m an ', + _react.createElement( + 'strong', + null, + 'error' + ), + ' message.' + ) + ) +); /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const MessageExamples = exports.MessageExamples = { sectionName: 'Messages', - description: - 'Message boxes are used to surface issues, such as warnings, inline within Nuclide.', - examples: [ - { - title: 'Basic Messages', - component: MessageExample, - }, - ], -}; + description: 'Message boxes are used to surface issues, such as warnings, inline within Nuclide.', + examples: [{ + title: 'Basic Messages', + component: MessageExample + }] +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Message.js b/modules/nuclide-commons-ui/Message.js index 22c3e051..c51f8eea 100644 --- a/modules/nuclide-commons-ui/Message.js +++ b/modules/nuclide-commons-ui/Message.js @@ -1,3 +1,22 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Message = exports.MessageTypes = undefined; + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,27 +25,16 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import classnames from 'classnames'; -import * as React from 'react'; - -type MessageType = 'default' | 'info' | 'success' | 'warning' | 'error'; - -type Props = { - className?: string, - children?: ?(React.Element | Array>), - type?: MessageType, -}; - -export const MessageTypes = Object.freeze({ +const MessageTypes = exports.MessageTypes = Object.freeze({ default: 'default', info: 'info', success: 'success', warning: 'warning', - error: 'error', + error: 'error' }); const MessageTypeClassNames = Object.freeze({ @@ -34,20 +42,16 @@ const MessageTypeClassNames = Object.freeze({ error: 'nuclide-ui-message-error', info: 'nuclide-ui-message-info', success: 'nuclide-ui-message-success', - warning: 'nuclide-ui-message-warning', + warning: 'nuclide-ui-message-warning' }); -export const Message = (props: Props) => { - const {className, children, type} = props; +const Message = exports.Message = props => { + const { className, children, type } = props; const resolvedType = type == null ? MessageTypes.default : type; - const newClassName = classnames( - className, - 'nuclide-ui-message', - MessageTypeClassNames[resolvedType], - ); - return ( -
- {children} -
+ const newClassName = (0, (_classnames || _load_classnames()).default)(className, 'nuclide-ui-message', MessageTypeClassNames[resolvedType]); + return _react.createElement( + 'div', + { className: newClassName }, + children ); -}; +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/PanelComponentScroller.js b/modules/nuclide-commons-ui/PanelComponentScroller.js index c26ca0f1..889aa665 100644 --- a/modules/nuclide-commons-ui/PanelComponentScroller.js +++ b/modules/nuclide-commons-ui/PanelComponentScroller.js @@ -1,3 +1,22 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PanelComponentScroller = undefined; + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,39 +25,29 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import classnames from 'classnames'; -import * as React from 'react'; - -type Props = { - children?: mixed, - flexDirection?: 'column', - overflowX?: string, - onScroll?: (event: Event) => void, - onFocus?: (event: SyntheticEvent<>) => void, -}; - -export class PanelComponentScroller extends React.Component { - render(): React.Node { - const style = - this.props.overflowX == null ? null : {overflowX: this.props.overflowX}; - const className = classnames('nuclide-ui-panel-component-scroller', { - 'nuclide-ui-panel-component-scroller--column': - this.props.flexDirection === 'column', +class PanelComponentScroller extends _react.Component { + render() { + const style = this.props.overflowX == null ? null : { overflowX: this.props.overflowX }; + const className = (0, (_classnames || _load_classnames()).default)('nuclide-ui-panel-component-scroller', { + 'nuclide-ui-panel-component-scroller--column': this.props.flexDirection === 'column' }); return ( // $FlowFixMe(>=0.53.0) Flow suppress -
- {this.props.children} -
+ _react.createElement( + 'div', + { + className: className, + style: style, + onScroll: this.props.onScroll, + onFocus: this.props.onFocus }, + this.props.children + ) ); } } +exports.PanelComponentScroller = PanelComponentScroller; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/ProgressBar.js b/modules/nuclide-commons-ui/ProgressBar.js index daa13552..7275fb64 100644 --- a/modules/nuclide-commons-ui/ProgressBar.js +++ b/modules/nuclide-commons-ui/ProgressBar.js @@ -1,28 +1,23 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import * as React from 'react'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ProgressBar = undefined; -type Props = { - /** - * The progress value. If none is provided, the Progressbar will render in `indefinite` mode. - * Use `indefinite mode` to indicate an initializing period, - * Prefer using the `LoadingSpinner` component for surfacing non-deterministic progress. - */ - value?: number, - /** Determines the scaling of `value`. `min` is implicitly set to `0`. */ - max?: number, -}; +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } /** A Progressbar for showing deterministic progress. */ -export const ProgressBar = (props: Props) => - ; +const ProgressBar = exports.ProgressBar = props => _react.createElement('progress', Object.assign({ value: props.value, max: props.max }, props)); /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/nuclide-commons-ui/ProgressIndicators.example.js b/modules/nuclide-commons-ui/ProgressIndicators.example.js index 259206d3..950ddbb8 100644 --- a/modules/nuclide-commons-ui/ProgressIndicators.example.js +++ b/modules/nuclide-commons-ui/ProgressIndicators.example.js @@ -1,3 +1,32 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ProgressIndicatorExamples = undefined; + +var _react = _interopRequireWildcard(require('react')); + +var _Block; + +function _load_Block() { + return _Block = require('./Block'); +} + +var _ProgressBar; + +function _load_ProgressBar() { + return _ProgressBar = require('./ProgressBar'); +} + +var _LoadingSpinner; + +function _load_LoadingSpinner() { + return _LoadingSpinner = require('./LoadingSpinner'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,59 +35,68 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import * as React from 'react'; -import {Block} from './Block'; -import {ProgressBar} from './ProgressBar'; -import {LoadingSpinner} from './LoadingSpinner'; - -const ProgressBarExample = (): React.Element => -
- - - - - - - - - - - - -
; +const ProgressBarExample = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_ProgressBar || _load_ProgressBar()).ProgressBar, null) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_ProgressBar || _load_ProgressBar()).ProgressBar, { max: 100, value: 0 }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_ProgressBar || _load_ProgressBar()).ProgressBar, { max: 100, value: 50 }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_ProgressBar || _load_ProgressBar()).ProgressBar, { max: 100, value: 100 }) + ) +); -const LoadingSpinnerExample = (): React.Element => -
- - - - - - - - - - - - -
; +const LoadingSpinnerExample = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_LoadingSpinner || _load_LoadingSpinner()).LoadingSpinner, { size: 'EXTRA_SMALL' }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_LoadingSpinner || _load_LoadingSpinner()).LoadingSpinner, { size: 'SMALL' }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_LoadingSpinner || _load_LoadingSpinner()).LoadingSpinner, { size: 'MEDIUM' }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_LoadingSpinner || _load_LoadingSpinner()).LoadingSpinner, { size: 'LARGE' }) + ) +); -export const ProgressIndicatorExamples = { +const ProgressIndicatorExamples = exports.ProgressIndicatorExamples = { sectionName: 'Progress Indicators', - description: - 'Show that work is being performed. Consider using one of these for any work > 1s.', - examples: [ - { - title: 'ProgressBar', - component: ProgressBarExample, - }, - { - title: 'LoadingSpinner', - component: LoadingSpinnerExample, - }, - ], -}; + description: 'Show that work is being performed. Consider using one of these for any work > 1s.', + examples: [{ + title: 'ProgressBar', + component: ProgressBarExample + }, { + title: 'LoadingSpinner', + component: LoadingSpinnerExample + }] +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/ReactMountRootElement.js b/modules/nuclide-commons-ui/ReactMountRootElement.js index 743649ac..be9fb98e 100644 --- a/modules/nuclide-commons-ui/ReactMountRootElement.js +++ b/modules/nuclide-commons-ui/ReactMountRootElement.js @@ -1,56 +1,67 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -/* global HTMLElement */ +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = _interopRequireWildcard(require('react')); + +var _reactDom = _interopRequireDefault(require('react-dom')); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -import invariant from 'assert'; -import * as React from 'react'; -import ReactDOM from 'react-dom'; +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } /** * A custom HTMLElement we render React elements into. */ class ReactMountRootElement extends HTMLElement { - _reactElement: ?React.Element; - setReactElement(reactElement: React.Element): void { + setReactElement(reactElement) { this._reactElement = reactElement; } - attachedCallback(): mixed { + attachedCallback() { if (this._reactElement == null) { return; } - ReactDOM.render(this._reactElement, this); + _reactDom.default.render(this._reactElement, this); } - detachedCallback(): mixed { + detachedCallback() { if (this._reactElement == null) { return; } - ReactDOM.unmountComponentAtNode(this); + _reactDom.default.unmountComponentAtNode(this); } -} +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +/* global HTMLElement */ let reactMountRootElement; try { reactMountRootElement = document.registerElement('nuclide-react-mount-root', { - prototype: ReactMountRootElement.prototype, + prototype: ReactMountRootElement.prototype }); } catch (e) { // Element was already registered. Retrieve its constructor: const oldElem = document.createElement('nuclide-react-mount-root'); - invariant(oldElem.constructor.name === 'nuclide-react-mount-root'); - reactMountRootElement = (oldElem.constructor: any); + + if (!(oldElem.constructor.name === 'nuclide-react-mount-root')) { + throw new Error('Invariant violation: "oldElem.constructor.name === \'nuclide-react-mount-root\'"'); + } + + reactMountRootElement = oldElem.constructor; } -export default (reactMountRootElement: Class); +exports.default = reactMountRootElement; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/RegExpFilter.example.js b/modules/nuclide-commons-ui/RegExpFilter.example.js index adbfb62f..12ad5534 100644 --- a/modules/nuclide-commons-ui/RegExpFilter.example.js +++ b/modules/nuclide-commons-ui/RegExpFilter.example.js @@ -1,3 +1,33 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = _interopRequireWildcard(require('react')); + +var _Block; + +function _load_Block() { + return _Block = require('./Block'); +} + +var _RegExpFilter; + +function _load_RegExpFilter() { + return _RegExpFilter = _interopRequireDefault(require('./RegExpFilter')); +} + +var _RegExpFilter2; + +function _load_RegExpFilter2() { + return _RegExpFilter2 = require('./RegExpFilter'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,56 +36,45 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {RegExpFilterChange} from './RegExpFilter'; - -import * as React from 'react'; -import {Block} from './Block'; -import RegExpFilter, {getFilterPattern} from './RegExpFilter'; - -type State = { - text: string, - isRegExp: boolean, - invalid: boolean, -}; - -class Example extends React.Component<{}, State> { +class Example extends _react.Component { constructor() { super(); + + this._handleChange = change => { + const { invalid } = (0, (_RegExpFilter2 || _load_RegExpFilter2()).getFilterPattern)(change.text, change.isRegExp); + this.setState(Object.assign({}, change, { invalid })); + }; + this.state = { text: '', isRegExp: false, - invalid: false, + invalid: false }; } - render(): React.Node { - return ( -
- - - -
+ render() { + return _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_RegExpFilter || _load_RegExpFilter()).default, { value: this.state, onChange: this._handleChange }) + ) ); } - _handleChange = (change: RegExpFilterChange): void => { - const {invalid} = getFilterPattern(change.text, change.isRegExp); - this.setState({...change, invalid}); - }; } -export default { +exports.default = { sectionName: 'RegExp Filter', - description: - 'An input for filtering that allows the use of regular expressions.', - examples: [ - { - title: 'RegExpFilter', - component: Example, - }, - ], -}; + description: 'An input for filtering that allows the use of regular expressions.', + examples: [{ + title: 'RegExpFilter', + component: Example + }] +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/RegExpFilter.js b/modules/nuclide-commons-ui/RegExpFilter.js index 0e7abfee..2e16578a 100644 --- a/modules/nuclide-commons-ui/RegExpFilter.js +++ b/modules/nuclide-commons-ui/RegExpFilter.js @@ -1,162 +1,158 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {ButtonSize} from './Button'; - -import {AtomInput} from './AtomInput'; -import classnames from 'classnames'; -import {Button, ButtonSizes} from './Button'; -import {ButtonGroup} from './ButtonGroup'; -import escapeStringRegexp from 'escape-string-regexp'; -import * as React from 'react'; - -type Size = 'xs' | 'sm' | 'lg'; - -type Props = { - value: RegExpFilterValue, - inputWidth?: number, - inputClassName?: string, - onChange: (value: RegExpFilterChange) => mixed, - size?: Size, -}; - -type State = { - text: string, - isRegExp: boolean, - invalid: boolean, -}; - -export type RegExpFilterValue = { - text: string, - isRegExp: boolean, - invalid: boolean, -}; - -export type FilterPattern = { - pattern: ?RegExp, - invalid: boolean, -}; - -export type RegExpFilterChange = { - text: string, - isRegExp: boolean, -}; - -export default class RegExpFilter extends React.Component { - _currentValue: RegExpFilterValue; - _input: ?AtomInput; - - constructor(props: Props) { +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getFilterPattern = getFilterPattern; + +var _AtomInput; + +function _load_AtomInput() { + return _AtomInput = require('./AtomInput'); +} + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _Button; + +function _load_Button() { + return _Button = require('./Button'); +} + +var _ButtonGroup; + +function _load_ButtonGroup() { + return _ButtonGroup = require('./ButtonGroup'); +} + +var _escapeStringRegexp; + +function _load_escapeStringRegexp() { + return _escapeStringRegexp = _interopRequireDefault(require('escape-string-regexp')); +} + +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class RegExpFilter extends _react.Component { + + constructor(props) { super(props); + + this._handleReToggleButtonClick = () => { + this.props.onChange({ + text: this._currentValue.text, + isRegExp: !this._currentValue.isRegExp + }); + }; + + this._handleTextChange = text => { + if (text === this._currentValue.text) { + return; + } + this.props.onChange({ + text, + isRegExp: this._currentValue.isRegExp + }); + }; + this._currentValue = props.value; } - componentWillReceiveProps(props: Props): void { + componentWillReceiveProps(props) { // We need to store this so that we can use it in the event handlers. this._currentValue = props.value; } - render(): React.Node { - const {value: {text, isRegExp, invalid}} = this.props; + render() { + const { value: { text, isRegExp, invalid } } = this.props; const size = this.props.size || 'sm'; const buttonSize = getButtonSize(size); - const inputWidth = - this.props.inputWidth == null ? 200 : this.props.inputWidth; - const inputClassName = classnames( - 'nuclide-ui-regexp-filter-input', - this.props.inputClassName, - {invalid}, - ); - - return ( - - { - this._input = el; - }} - className={inputClassName} - size={size} - width={inputWidth} - placeholderText="Filter" - onDidChange={this._handleTextChange} - value={text} - /> - - + const inputWidth = this.props.inputWidth == null ? 200 : this.props.inputWidth; + const inputClassName = (0, (_classnames || _load_classnames()).default)('nuclide-ui-regexp-filter-input', this.props.inputClassName, { invalid }); + + return _react.createElement( + (_ButtonGroup || _load_ButtonGroup()).ButtonGroup, + { className: 'inline-block' }, + _react.createElement((_AtomInput || _load_AtomInput()).AtomInput, { + ref: el => { + this._input = el; + }, + className: inputClassName, + size: size, + width: inputWidth, + placeholderText: 'Filter', + onDidChange: this._handleTextChange, + value: text + }), + _react.createElement( + (_Button || _load_Button()).Button, + { + className: 'nuclide-ui-regexp-filter-button', + size: buttonSize, + selected: isRegExp, + onClick: this._handleReToggleButtonClick, + tooltip: { title: 'Use Regex' } }, + '.*' + ) ); } - focus(): void { + focus() { if (this._input == null) { return; } this._input.focus(); } - _handleReToggleButtonClick = (): void => { - this.props.onChange({ - text: this._currentValue.text, - isRegExp: !this._currentValue.isRegExp, - }); - }; - - _handleTextChange = (text: string): void => { - if (text === this._currentValue.text) { - return; - } - this.props.onChange({ - text, - isRegExp: this._currentValue.isRegExp, - }); - }; } -function getButtonSize(size: Size): ButtonSize { +exports.default = RegExpFilter; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +function getButtonSize(size) { switch (size) { case 'xs': - return ButtonSizes.EXTRA_SMALL; + return (_Button || _load_Button()).ButtonSizes.EXTRA_SMALL; case 'sm': - return ButtonSizes.SMALL; + return (_Button || _load_Button()).ButtonSizes.SMALL; case 'lg': - return ButtonSizes.LARGE; + return (_Button || _load_Button()).ButtonSizes.LARGE; default: throw new Error(`Invalid size: ${size}`); } } -export function getFilterPattern( - text: string, - isRegExp: boolean, -): FilterPattern { +function getFilterPattern(text, isRegExp) { if (text === '') { - return {pattern: null, invalid: false}; + return { pattern: null, invalid: false }; } - const source = isRegExp ? text : escapeStringRegexp(text); + const source = isRegExp ? text : (0, (_escapeStringRegexp || _load_escapeStringRegexp()).default)(text); try { return { pattern: new RegExp(source, 'i'), - invalid: false, + invalid: false }; } catch (err) { return { pattern: null, - invalid: true, + invalid: true }; } -} +} \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Table.example.js b/modules/nuclide-commons-ui/Table.example.js index 5ac45217..0e74d5cd 100644 --- a/modules/nuclide-commons-ui/Table.example.js +++ b/modules/nuclide-commons-ui/Table.example.js @@ -1,128 +1,125 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import * as React from 'react'; -import {Block} from './Block'; -import {Table} from './Table'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.TableExamples = undefined; -const Highlight42Component = (props: {data: ?number}): ?React.Element => -
- {props.data} -
; +var _react = _interopRequireWildcard(require('react')); -const TableExample = (): React.Element => { - const columns = [ - { - title: 'first column', - key: 'first', - }, - { - title: 'second column', - key: 'second', - component: Highlight42Component, - }, - { - title: 'third column', - key: 'third', - }, - { - title: 'fourth column', - key: 'fourth', - }, - { - title: 'fifth column', - key: 'fifth', - }, - ]; - const rows = [ - { - data: { - first: 1, - second: 2, - third: 3, - fourth: 33, - fifth: 123, - }, - }, - { - className: 'this-is-an-optional-classname', - data: { - first: 4, - second: 42, - third: 6, - fourth: 66, - fifth: 123, - }, - }, - { - data: { - first: 7, - second: 42, - third: undefined, - fourth: 66, - fifth: 123, - }, - }, - ]; - return ( - -
- +var _Block; + +function _load_Block() { + return _Block = require('./Block'); +} + +var _Table; + +function _load_Table() { + return _Table = require('./Table'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const Highlight42Component = props => _react.createElement( + 'div', + { style: props.data === 42 ? { fontWeight: 'bold' } : {} }, + props.data +); /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const TableExample = () => { + const columns = [{ + title: 'first column', + key: 'first' + }, { + title: 'second column', + key: 'second', + component: Highlight42Component + }, { + title: 'third column', + key: 'third' + }, { + title: 'fourth column', + key: 'fourth' + }, { + title: 'fifth column', + key: 'fifth' + }]; + const rows = [{ + data: { + first: 1, + second: 2, + third: 3, + fourth: 33, + fifth: 123 + } + }, { + className: 'this-is-an-optional-classname', + data: { + first: 4, + second: 42, + third: 6, + fourth: 66, + fifth: 123 + } + }, { + data: { + first: 7, + second: 42, + third: undefined, + fourth: 66, + fifth: 123 + } + }]; + return _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_Table || _load_Table()).Table, { columns: columns, rows: rows, selectable: true }) ); }; -class SortableTableExample extends React.Component< - mixed, - { - rows: Array, - sortDescending: boolean, - sortedColumn: ?string, - }, -> { - constructor(props: mixed) { +class SortableTableExample extends _react.Component { + constructor(props) { super(props); - const rows = [ - { - data: { - first: 1, - second: 3, - third: 300, - }, - }, - { - data: { - first: 2, - second: 5, - third: 200, - }, - }, - { - className: 'nuclide-ui-custom-classname-example', - data: { - first: 3, - second: 4, - third: 100, - }, - }, - ]; + const rows = [{ + data: { + first: 1, + second: 3, + third: 300 + } + }, { + data: { + first: 2, + second: 5, + third: 200 + } + }, { + className: 'nuclide-ui-custom-classname-example', + data: { + first: 3, + second: 4, + third: 100 + } + }]; this.state = { sortDescending: false, sortedColumn: null, - rows, + rows }; - (this: any)._handleSort = this._handleSort.bind(this); + this._handleSort = this._handleSort.bind(this); } - _handleSort(sortedColumn: ?string, sortDescending: boolean): void { + _handleSort(sortedColumn, sortDescending) { const sortedRows = this.state.rows.sort((obj1, obj2) => { const order = sortDescending ? -1 : 1; return order * (obj1.data[sortedColumn] - obj2.data[sortedColumn]); @@ -130,80 +127,71 @@ class SortableTableExample extends React.Component< this.setState({ rows: sortedRows, sortedColumn, - sortDescending, + sortDescending }); } - render(): React.Node { - const columns = [ - { - title: 'first', - key: 'first', - }, - { - title: 'second', - key: 'second', - }, - { - title: 'third', - key: 'third', - }, - ]; - return ( - -
-
An optional, custom "empty message" component.
} - columns={columns} - rows={this.state.rows} - sortable={true} - onSort={this._handleSort} - sortedColumn={this.state.sortedColumn} - sortDescending={this.state.sortDescending} - /> - + render() { + const columns = [{ + title: 'first', + key: 'first' + }, { + title: 'second', + key: 'second' + }, { + title: 'third', + key: 'third' + }]; + return _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_Table || _load_Table()).Table, { + emptyComponent: () => _react.createElement( + 'div', + null, + 'An optional, custom "empty message" component.' + ), + columns: columns, + rows: this.state.rows, + sortable: true, + onSort: this._handleSort, + sortedColumn: this.state.sortedColumn, + sortDescending: this.state.sortDescending + }) ); } } -const EmptyTableExample = (): React.Element => { - const columns = [ - { - title: 'first column', - key: 'first', - }, - { - title: 'second column', - key: 'second', - }, - { - title: 'third column', - key: 'third', - }, - ]; +const EmptyTableExample = () => { + const columns = [{ + title: 'first column', + key: 'first' + }, { + title: 'second column', + key: 'second' + }, { + title: 'third column', + key: 'third' + }]; const rows = []; - return ( - -
- + return _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_Table || _load_Table()).Table, { columns: columns, rows: rows }) ); }; -export const TableExamples = { +const TableExamples = exports.TableExamples = { sectionName: 'Table', description: '', - examples: [ - { - title: 'Simple Table', - component: TableExample, - }, - { - title: 'Sortable Table', - component: SortableTableExample, - }, - { - title: 'Empty Table', - component: EmptyTableExample, - }, - ], -}; + examples: [{ + title: 'Simple Table', + component: TableExample + }, { + title: 'Sortable Table', + component: SortableTableExample + }, { + title: 'Empty Table', + component: EmptyTableExample + }] +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Table.js b/modules/nuclide-commons-ui/Table.js index 97a48f15..3dfe183b 100644 --- a/modules/nuclide-commons-ui/Table.js +++ b/modules/nuclide-commons-ui/Table.js @@ -1,3 +1,38 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Table = undefined; + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +var _reactDom = _interopRequireDefault(require('react-dom')); + +var _atom = require('atom'); + +var _Icon; + +function _load_Icon() { + return _Icon = require('./Icon'); +} + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,141 +41,40 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import classnames from 'classnames'; -import * as React from 'react'; -import ReactDOM from 'react-dom'; -import {Disposable} from 'atom'; -import {Icon} from './Icon'; -import UniversalDisposable from 'nuclide-commons/UniversalDisposable'; +const DefaultEmptyComponent = () => _react.createElement( + 'div', + { className: 'nuclide-ui-table-empty-message' }, + 'Empty table' +); -const DefaultEmptyComponent = () => -
Empty table
; +class Table extends _react.Component { -export type Column = { - title: string, - key: $Keys, - // Percentage. The `width`s of all columns must add up to 1. - width?: number, - // Optional React component for rendering cell contents. - // The component receives the cell value via `props.data`. - component?: React.ComponentType, - shouldRightAlign?: boolean, - // A class to add to the cell. This will be added to both the header and body; you can - // differentiate between them with `.nuclide-ui-table-header-cell` and - // `.nuclide-ui-table-body-cell`. - cellClassName?: string, -}; -export type Row = { - +className?: string, - +data: T, -}; -type WidthMap = { - [key: $Keys]: number, -}; -type Props = { - /** - * Optional classname for the entire table. - */ - className?: string, - /** - * Optional max-height for the body container. - * Useful for making the table scrollable while keeping the header fixed. - */ - maxBodyHeight?: string, - columns: Array>, - rows: Array>, - /** - * Whether to shade even and odd items differently. Default behavior is `true`. - */ - alternateBackground?: number, - /** - * Whether column widths can be resized interactively via drag&drop. Default behavior is `true`. - */ - resizeable?: boolean, - children?: React.Element, - /** - * Whether columns can be sorted. - * If specified, `onSort`, `sortedColumn`, and `sortDescending` must also be specified. - */ - sortable?: boolean, - onSort?: (sortedBy: $Keys, sortDescending: boolean) => void, - sortedColumn?: ?$Keys, - sortDescending?: boolean, - /** - * Whether items can be selected. - * If specified, `onSelect` must also be specified. - */ - selectable?: boolean, - selectedIndex?: ?number, - /** - * Handler to be called upon selection. Called iff `selectable` is `true`. - */ - onSelect?: (selectedItem: any, selectedIndex: number) => mixed, - /** - * Callback to be invoked before calling onSelect. Called iff `selectable` is `true`. - * If this callback returns false, row selection is canceled. - */ - onWillSelect?: ( - selectedItem: any, - selectedIndex: number, - event: SyntheticMouseEvent<>, - ) => boolean, - /** - * Optional React Component to override the default message when zero rows are provided. - * Useful for showing loading spinners and custom messages. - */ - emptyComponent?: React.ComponentType, - /** - * Whether a table row will be collapsed if its content is too large - */ - collapsable?: boolean, - /** - * Whether there's a header title spanning all cells instead of the column titles. - * It disables the 'sortable' prop. - */ - headerTitle?: string, -}; -type State = { - columnWidthRatios: WidthMap, -}; - -export class Table extends React.Component, State> { - _globalEventsDisposable: ?Disposable; - _resizeStartX: ?number; - _tableWidth: ?number; - _columnBeingResized: ?$Keys; - _disposables: UniversalDisposable; - - constructor(props: Props) { + constructor(props) { super(props); this._globalEventsDisposable = null; this._resizeStartX = null; this._tableWidth = null; this._columnBeingResized = null; - (this: any)._handleResizerGlobalMouseUp = this._handleResizerGlobalMouseUp.bind( - this, - ); - (this: any)._handleResizerGlobalMouseMove = this._handleResizerGlobalMouseMove.bind( - this, - ); + this._handleResizerGlobalMouseUp = this._handleResizerGlobalMouseUp.bind(this); + this._handleResizerGlobalMouseMove = this._handleResizerGlobalMouseMove.bind(this); this.state = { - columnWidthRatios: this._getInitialWidthsForColumns(this.props.columns), + columnWidthRatios: this._getInitialWidthsForColumns(this.props.columns) }; - this._disposables = new UniversalDisposable(() => { + this._disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(() => { this._unsubscribeFromGlobalEvents(); }); } - _getInitialWidthsForColumns(columns: Array>): WidthMap { + _getInitialWidthsForColumns(columns) { const columnWidthRatios = {}; let assignedWidth = 0; const unresolvedColumns = []; columns.forEach(column => { - const {key, width} = column; + const { key, width } = column; if (width != null) { columnWidthRatios[key] = width; assignedWidth += width; @@ -156,44 +90,36 @@ export class Table extends React.Component, State> { } /* Applies sizing constraints, and returns whether the column width actually changed. */ - _updateWidths(resizedColumn: $Keys, newColumnSize: number): boolean { - const {columnWidthRatios} = this.state; - const {columns} = this.props; + _updateWidths(resizedColumn, newColumnSize) { + const { columnWidthRatios } = this.state; + const { columns } = this.props; const originalColumnSize = columnWidthRatios[resizedColumn]; - const columnAfterResizedColumn = - columns[columns.findIndex(column => column.key === resizedColumn) + 1] - .key; + const columnAfterResizedColumn = columns[columns.findIndex(column => column.key === resizedColumn) + 1].key; const followingColumnSize = columnWidthRatios[columnAfterResizedColumn]; - const constrainedNewColumnSize = Math.max( - 0, - Math.min(newColumnSize, followingColumnSize + originalColumnSize), - ); + const constrainedNewColumnSize = Math.max(0, Math.min(newColumnSize, followingColumnSize + originalColumnSize)); if (Math.abs(newColumnSize - constrainedNewColumnSize) > Number.EPSILON) { return false; } const updatedColumnWidths = {}; columns.forEach(column => { - const {key} = column; + const { key } = column; let width; if (column.key === resizedColumn) { width = constrainedNewColumnSize; } else if (column.key === columnAfterResizedColumn) { - width = - columnWidthRatios[resizedColumn] - - constrainedNewColumnSize + - columnWidthRatios[key]; + width = columnWidthRatios[resizedColumn] - constrainedNewColumnSize + columnWidthRatios[key]; } else { width = columnWidthRatios[key]; } updatedColumnWidths[key] = width; }); this.setState({ - columnWidthRatios: updatedColumnWidths, + columnWidthRatios: updatedColumnWidths }); return true; } - _handleResizerMouseDown(key: $Keys, event: SyntheticMouseEvent<>): void { + _handleResizerMouseDown(key, event) { if (this._globalEventsDisposable != null) { this._unsubscribeFromGlobalEvents(); } @@ -206,15 +132,10 @@ export class Table extends React.Component, State> { document.addEventListener('mouseup', this._handleResizerGlobalMouseUp); this._resizeStartX = event.pageX; // $FlowFixMe - this._tableWidth = ReactDOM.findDOMNode( - this.refs.table, - ).getBoundingClientRect().width; + this._tableWidth = _reactDom.default.findDOMNode(this.refs.table).getBoundingClientRect().width; this._columnBeingResized = key; - this._globalEventsDisposable = new Disposable(() => { - document.removeEventListener( - 'mousemove', - this._handleResizerGlobalMouseMove, - ); + this._globalEventsDisposable = new _atom.Disposable(() => { + document.removeEventListener('mousemove', this._handleResizerGlobalMouseMove); document.removeEventListener('mouseup', this._handleResizerGlobalMouseUp); this._resizeStartX = null; this._tableWidth = null; @@ -222,7 +143,7 @@ export class Table extends React.Component, State> { }); } - _unsubscribeFromGlobalEvents(): void { + _unsubscribeFromGlobalEvents() { if (this._globalEventsDisposable == null) { return; } @@ -230,51 +151,37 @@ export class Table extends React.Component, State> { this._globalEventsDisposable = null; } - _handleResizerGlobalMouseUp(event: MouseEvent): void { + _handleResizerGlobalMouseUp(event) { this._unsubscribeFromGlobalEvents(); } - _handleResizerGlobalMouseMove(event: MouseEvent): void { - if ( - this._resizeStartX == null || - this._tableWidth == null || - this._columnBeingResized == null - ) { + _handleResizerGlobalMouseMove(event) { + if (this._resizeStartX == null || this._tableWidth == null || this._columnBeingResized == null) { return; } - const {pageX} = ((event: any): MouseEvent); + const { pageX } = event; const deltaX = pageX - this._resizeStartX; - const currentColumnSize = this.state.columnWidthRatios[ - this._columnBeingResized - ]; - const didUpdate = this._updateWidths( - this._columnBeingResized, - (this._tableWidth * currentColumnSize + deltaX) / this._tableWidth, - ); + const currentColumnSize = this.state.columnWidthRatios[this._columnBeingResized]; + const didUpdate = this._updateWidths(this._columnBeingResized, (this._tableWidth * currentColumnSize + deltaX) / this._tableWidth); if (didUpdate) { this._resizeStartX = pageX; } } - componentWillUnmount(): void { + componentWillUnmount() { this._disposables.dispose(); } - _handleSortByColumn(sortedBy: $Keys): void { - const {onSort, sortDescending, sortedColumn} = this.props; + _handleSortByColumn(sortedBy) { + const { onSort, sortDescending, sortedColumn } = this.props; if (onSort == null) { return; } - onSort( - sortedBy, - sortDescending == null || sortedBy !== sortedColumn - ? false - : !sortDescending, - ); + onSort(sortedBy, sortDescending == null || sortedBy !== sortedColumn ? false : !sortDescending); } - _handleRowClick(selectedIndex: number, event: SyntheticMouseEvent<>): void { - const {onSelect, onWillSelect, rows} = this.props; + _handleRowClick(selectedIndex, event) { + const { onSelect, onWillSelect, rows } = this.props; if (onSelect == null) { return; } @@ -287,11 +194,11 @@ export class Table extends React.Component, State> { onSelect(selectedItem.data, selectedIndex); } - _renderEmptyCellContent(): React.Element { - return
; + _renderEmptyCellContent() { + return _react.createElement('div', null); } - render(): React.Node { + render() { const { alternateBackground, className, @@ -303,79 +210,72 @@ export class Table extends React.Component, State> { selectedIndex, sortable, sortedColumn, - sortDescending, + sortDescending } = this.props; - const header = - headerTitle != null - ?
- {headerTitle} -
- : columns.map((column, i) => { - const {title, key, shouldRightAlign, cellClassName} = column; - const resizeHandle = - i === columns.length - 1 - ? null - :
) => { - // Prevent sortable column header click event from firing. - e.stopPropagation(); - }} - />; - const width = this.state.columnWidthRatios[key]; - const optionalHeaderCellProps = {}; - if (width != null) { - optionalHeaderCellProps.style = { - width: width * 100 + '%', - }; - } - let sortIndicator; - let titleOverlay = title; - if (sortable) { - optionalHeaderCellProps.onClick = this._handleSortByColumn.bind( - this, - key, - ); - titleOverlay += ' – click to sort'; - if (sortedColumn === key) { - sortIndicator = ( - - - - ); - } - } - return ( -
- {title} - {sortIndicator} - {resizeHandle} -
- ); - }); + const header = headerTitle != null ? _react.createElement( + 'div', + { className: 'nuclide-ui-table-header-cell nuclide-ui-table-full-header' }, + headerTitle + ) : columns.map((column, i) => { + const { title, key, shouldRightAlign, cellClassName } = column; + const resizeHandle = i === columns.length - 1 ? null : _react.createElement('div', { + className: 'nuclide-ui-table-header-resize-handle', + onMouseDown: this._handleResizerMouseDown.bind(this, key), + onClick: e => { + // Prevent sortable column header click event from firing. + e.stopPropagation(); + } + }); + const width = this.state.columnWidthRatios[key]; + const optionalHeaderCellProps = {}; + if (width != null) { + optionalHeaderCellProps.style = { + width: width * 100 + '%' + }; + } + let sortIndicator; + let titleOverlay = title; + if (sortable) { + optionalHeaderCellProps.onClick = this._handleSortByColumn.bind(this, key); + titleOverlay += ' – click to sort'; + if (sortedColumn === key) { + sortIndicator = _react.createElement( + 'span', + { className: 'nuclide-ui-table-sort-indicator' }, + _react.createElement((_Icon || _load_Icon()).Icon, { + icon: sortDescending ? 'triangle-down' : 'triangle-up' + }) + ); + } + } + return _react.createElement( + 'div', + Object.assign({ + className: (0, (_classnames || _load_classnames()).default)(cellClassName, { + 'nuclide-ui-table-cell-text-align-right': shouldRightAlign, + 'nuclide-ui-table-header-cell': true, + 'nuclide-ui-table-header-cell-sortable': sortable + }), + title: titleOverlay, + key: key + }, optionalHeaderCellProps), + title, + sortIndicator, + resizeHandle + ); + }); let body = rows.map((row, i) => { - const {className: rowClassName, data} = row; + const { className: rowClassName, data } = row; const renderedRow = columns.map((column, j) => { const { key, cellClassName, component: Component, - shouldRightAlign, + shouldRightAlign } = column; let datum = data[key]; if (Component != null) { - datum = ; + datum = _react.createElement(Component, { data: datum }); } else if (datum == null) { datum = this._renderEmptyCellContent(); } @@ -384,17 +284,17 @@ export class Table extends React.Component, State> { if (width != null) { cellStyle.width = width * 100 + '%'; } - return ( -
- {datum} -
+ 'nuclide-ui-table-cell-text-align-right': shouldRightAlign + }), + key: j, + style: cellStyle, + title: typeof datum !== 'object' ? String(datum) : null }, + datum ); }); const rowProps = {}; @@ -402,47 +302,54 @@ export class Table extends React.Component, State> { rowProps.onClick = this._handleRowClick.bind(this, i); } const isSelectedRow = selectedIndex != null && i === selectedIndex; - return ( -
- {renderedRow} -
+ 'nuclide-ui-table-row-alternate': alternateBackground !== false && i % 2 === 1, + 'nuclide-ui-table-collapsed-row': this.props.collapsable && !isSelectedRow + }), + key: i + }, rowProps), + renderedRow ); }); if (rows.length === 0) { const EmptyComponent = this.props.emptyComponent || DefaultEmptyComponent; - body = ; + body = _react.createElement(EmptyComponent, null); } const scrollableBodyStyle = {}; if (maxBodyHeight != null) { scrollableBodyStyle.maxHeight = maxBodyHeight; scrollableBodyStyle.overflowY = 'auto'; } - return ( -
-
-
- {header} -
-
-
-
- {body} -
-
-
+ return _react.createElement( + 'div', + { className: className }, + _react.createElement( + 'div', + { className: 'nuclide-ui-table', ref: 'table' }, + _react.createElement( + 'div', + { className: 'nuclide-ui-table-header' }, + header + ) + ), + _react.createElement( + 'div', + { style: scrollableBodyStyle }, + _react.createElement( + 'div', + { + className: 'nuclide-ui-table nuclide-ui-table-body native-key-bindings', + tabIndex: '-1' }, + body + ) + ) ); } } +exports.Table = Table; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/TextInputs.example.js b/modules/nuclide-commons-ui/TextInputs.example.js index 587beead..600251c7 100644 --- a/modules/nuclide-commons-ui/TextInputs.example.js +++ b/modules/nuclide-commons-ui/TextInputs.example.js @@ -1,123 +1,162 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import {TextBuffer} from 'atom'; -import * as React from 'react'; -import {Block} from './Block'; -import {AtomInput} from './AtomInput'; -import {AtomTextEditor} from './AtomTextEditor'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.TextInputExamples = undefined; + +var _atom = require('atom'); + +var _react = _interopRequireWildcard(require('react')); + +var _Block; + +function _load_Block() { + return _Block = require('./Block'); +} + +var _AtomInput; -const AtomInputExample = (): React.Element => -
- - - - - - - - - - - - - - - - - - - - - -
; +function _load_AtomInput() { + return _AtomInput = require('./AtomInput'); +} -const buffer1 = new TextBuffer({ - text: '/**\n * Hi!\n */\n\n// I am a TextBuffer.\nconst a = 42;', +var _AtomTextEditor; + +function _load_AtomTextEditor() { + return _AtomTextEditor = require('./AtomTextEditor'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const AtomInputExample = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_AtomInput || _load_AtomInput()).AtomInput, { + disabled: false, + initialValue: 'atom input', + placeholderText: 'placeholder text' + }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_AtomInput || _load_AtomInput()).AtomInput, { + disabled: true, + initialValue: 'disabled atom input', + placeholderText: 'placeholder text' + }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_AtomInput || _load_AtomInput()).AtomInput, { + initialValue: 'xs atom input', + placeholderText: 'placeholder text', + size: 'xs' + }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_AtomInput || _load_AtomInput()).AtomInput, { + initialValue: 'sm atom input', + placeholderText: 'placeholder text', + size: 'sm' + }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_AtomInput || _load_AtomInput()).AtomInput, { + initialValue: 'lg atom input', + placeholderText: 'placeholder text', + size: 'lg' + }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_AtomInput || _load_AtomInput()).AtomInput, { + initialValue: 'unstyled atom input', + placeholderText: 'placeholder text', + unstyled: true + }) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement((_AtomInput || _load_AtomInput()).AtomInput, { + initialValue: 'atom input with custom width', + placeholderText: 'placeholder text', + width: 200 + }) + ) +); /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const buffer1 = new _atom.TextBuffer({ + text: '/**\n * Hi!\n */\n\n// I am a TextBuffer.\nconst a = 42;' }); -const buffer2 = new TextBuffer({ - text: - '/**\n * Hi!\n */\n\n// I am a read-only, gutter-less TextBuffer.\nconst a = 42;', +const buffer2 = new _atom.TextBuffer({ + text: '/**\n * Hi!\n */\n\n// I am a read-only, gutter-less TextBuffer.\nconst a = 42;' }); const editorWrapperStyle = { display: 'flex', flexGrow: 1, height: '12em', - boxShadow: '0 0 20px 0 rgba(0, 0, 0, 0.3)', + boxShadow: '0 0 20px 0 rgba(0, 0, 0, 0.3)' }; -const AtomTextEditorExample = (): React.Element => - -
- -
-
- -
-
; +const AtomTextEditorExample = () => _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + 'div', + { style: editorWrapperStyle }, + _react.createElement((_AtomTextEditor || _load_AtomTextEditor()).AtomTextEditor, { + gutterHidden: false, + readOnly: false, + syncTextContents: false, + autoGrow: false, + path: 'aJavaScriptFile.js', + textBuffer: buffer1 + }) + ), + _react.createElement( + 'div', + { style: Object.assign({}, editorWrapperStyle, { marginTop: '2em' }) }, + _react.createElement((_AtomTextEditor || _load_AtomTextEditor()).AtomTextEditor, { + gutterHidden: true, + readOnly: true, + syncTextContents: false, + autoGrow: false, + path: 'aJavaScriptFile.js', + textBuffer: buffer2 + }) + ) +); -export const TextInputExamples = { +const TextInputExamples = exports.TextInputExamples = { sectionName: 'Text Inputs', description: '', - examples: [ - { - title: 'AtomInput', - component: AtomInputExample, - }, - { - title: 'AtomTextEditor', - component: AtomTextEditorExample, - }, - ], -}; + examples: [{ + title: 'AtomInput', + component: AtomInputExample + }, { + title: 'AtomTextEditor', + component: AtomTextEditorExample + }] +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Toolbar.example.js b/modules/nuclide-commons-ui/Toolbar.example.js index 313be00d..e6f25057 100644 --- a/modules/nuclide-commons-ui/Toolbar.example.js +++ b/modules/nuclide-commons-ui/Toolbar.example.js @@ -1,97 +1,187 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import * as React from 'react'; -import {Block} from './Block'; -import {Toolbar} from './Toolbar'; -import {ToolbarCenter} from './ToolbarCenter'; -import {ToolbarLeft} from './ToolbarLeft'; -import {ToolbarRight} from './ToolbarRight'; -import {Button} from './Button'; - -const ToolbarExampleLeft = (): React.Element => -
- - - -
a toolbar can have multiple children,
- -
-
-
- -
- Be sure to use {', , and '} as - children. -
-
-
; - -const ToolbarExampleCenter = (): React.Element => - - - -
- Example of {''}. -
-
-
-
; - -const ToolbarExampleRight = (): React.Element => - - - -
- Example of {''} -
-
-
-
; - -const ToolbarExampleMultiple = (): React.Element => - - - -
You can combine
-
- -
the various kinds
-
- -
of aligners.
-
-
-
; - -export const ToolbarExamples = { +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ToolbarExamples = undefined; + +var _react = _interopRequireWildcard(require('react')); + +var _Block; + +function _load_Block() { + return _Block = require('./Block'); +} + +var _Toolbar; + +function _load_Toolbar() { + return _Toolbar = require('./Toolbar'); +} + +var _ToolbarCenter; + +function _load_ToolbarCenter() { + return _ToolbarCenter = require('./ToolbarCenter'); +} + +var _ToolbarLeft; + +function _load_ToolbarLeft() { + return _ToolbarLeft = require('./ToolbarLeft'); +} + +var _ToolbarRight; + +function _load_ToolbarRight() { + return _ToolbarRight = require('./ToolbarRight'); +} + +var _Button; + +function _load_Button() { + return _Button = require('./Button'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const ToolbarExampleLeft = () => _react.createElement( + 'div', + null, + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Toolbar || _load_Toolbar()).Toolbar, + { location: 'top' }, + _react.createElement( + (_ToolbarLeft || _load_ToolbarLeft()).ToolbarLeft, + null, + _react.createElement( + 'div', + null, + 'a toolbar can have multiple children,' + ), + _react.createElement( + (_Button || _load_Button()).Button, + null, + 'such as this button.' + ) + ) + ) + ), + _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + 'div', + null, + 'Be sure to use ', + ', , and ', + ' as children.' + ) + ) +); /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const ToolbarExampleCenter = () => _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Toolbar || _load_Toolbar()).Toolbar, + { location: 'top' }, + _react.createElement( + (_ToolbarCenter || _load_ToolbarCenter()).ToolbarCenter, + null, + _react.createElement( + 'div', + null, + 'Example of ', + '', + '.' + ) + ) + ) +); + +const ToolbarExampleRight = () => _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Toolbar || _load_Toolbar()).Toolbar, + { location: 'top' }, + _react.createElement( + (_ToolbarRight || _load_ToolbarRight()).ToolbarRight, + null, + _react.createElement( + 'div', + null, + 'Example of ', + '' + ) + ) + ) +); + +const ToolbarExampleMultiple = () => _react.createElement( + (_Block || _load_Block()).Block, + null, + _react.createElement( + (_Toolbar || _load_Toolbar()).Toolbar, + { location: 'top' }, + _react.createElement( + (_ToolbarLeft || _load_ToolbarLeft()).ToolbarLeft, + null, + _react.createElement( + 'div', + null, + 'You can combine' + ) + ), + _react.createElement( + (_ToolbarCenter || _load_ToolbarCenter()).ToolbarCenter, + null, + _react.createElement( + 'div', + null, + 'the various kinds' + ) + ), + _react.createElement( + (_ToolbarRight || _load_ToolbarRight()).ToolbarRight, + null, + _react.createElement( + 'div', + null, + 'of aligners.' + ) + ) + ) +); + +const ToolbarExamples = exports.ToolbarExamples = { sectionName: 'Toolbar', description: '', - examples: [ - { - title: 'Left Toolbar', - component: ToolbarExampleLeft, - }, - { - title: 'Center Toolbar', - component: ToolbarExampleCenter, - }, - { - title: 'Right Toolbar', - component: ToolbarExampleRight, - }, - { - title: 'Combining Toolbar aligners', - component: ToolbarExampleMultiple, - }, - ], -}; + examples: [{ + title: 'Left Toolbar', + component: ToolbarExampleLeft + }, { + title: 'Center Toolbar', + component: ToolbarExampleCenter + }, { + title: 'Right Toolbar', + component: ToolbarExampleRight + }, { + title: 'Combining Toolbar aligners', + component: ToolbarExampleMultiple + }] +}; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/Toolbar.js b/modules/nuclide-commons-ui/Toolbar.js index 27c21188..b885d3e0 100644 --- a/modules/nuclide-commons-ui/Toolbar.js +++ b/modules/nuclide-commons-ui/Toolbar.js @@ -1,39 +1,49 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import classnames from 'classnames'; -import * as React from 'react'; -import {maybeToString} from 'nuclide-commons/string'; - -type Props = { - children?: mixed, - className?: string, - location?: 'top' | 'bottom', -}; - -export const Toolbar = (props: Props) => { - const className = classnames( - 'nuclide-ui-toolbar', - { - [`nuclide-ui-toolbar--${maybeToString(props.location)}`]: - props.location != null, - }, - props.className, - ); +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Toolbar = undefined; + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +var _string; + +function _load_string() { + return _string = require('nuclide-commons/string'); +} + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const Toolbar = exports.Toolbar = props => { + const className = (0, (_classnames || _load_classnames()).default)('nuclide-ui-toolbar', { + [`nuclide-ui-toolbar--${(0, (_string || _load_string()).maybeToString)(props.location)}`]: props.location != null + }, props.className); return ( // $FlowFixMe(>=0.53.0) Flow suppress -
- {props.children} -
+ _react.createElement( + 'div', + { className: className }, + props.children + ) ); -}; +}; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/nuclide-commons-ui/ToolbarCenter.js b/modules/nuclide-commons-ui/ToolbarCenter.js index e6ee7330..5ee7932b 100644 --- a/modules/nuclide-commons-ui/ToolbarCenter.js +++ b/modules/nuclide-commons-ui/ToolbarCenter.js @@ -1,26 +1,31 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +"use strict"; -import * as React from 'react'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ToolbarCenter = undefined; -type Props = { - children?: mixed, -}; +var _react = _interopRequireWildcard(require("react")); -export const ToolbarCenter = (props: Props) => { +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const ToolbarCenter = exports.ToolbarCenter = props => { return ( // $FlowFixMe(>=0.53.0) Flow suppress -
- {props.children} -
+ _react.createElement( + "div", + { className: "nuclide-ui-toolbar__center" }, + props.children + ) ); -}; +}; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/nuclide-commons-ui/ToolbarLeft.js b/modules/nuclide-commons-ui/ToolbarLeft.js index 9f0ab2b1..79e4808b 100644 --- a/modules/nuclide-commons-ui/ToolbarLeft.js +++ b/modules/nuclide-commons-ui/ToolbarLeft.js @@ -1,26 +1,31 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +"use strict"; -import * as React from 'react'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ToolbarLeft = undefined; -type Props = { - children?: mixed, -}; +var _react = _interopRequireWildcard(require("react")); -export const ToolbarLeft = (props: Props) => { +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const ToolbarLeft = exports.ToolbarLeft = props => { return ( // $FlowFixMe(>=0.53.0) Flow suppress -
- {props.children} -
+ _react.createElement( + "div", + { className: "nuclide-ui-toolbar__left" }, + props.children + ) ); -}; +}; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/nuclide-commons-ui/ToolbarRight.js b/modules/nuclide-commons-ui/ToolbarRight.js index 567745ce..6152cdf6 100644 --- a/modules/nuclide-commons-ui/ToolbarRight.js +++ b/modules/nuclide-commons-ui/ToolbarRight.js @@ -1,26 +1,31 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +"use strict"; -import * as React from 'react'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ToolbarRight = undefined; -type Props = { - children?: mixed, -}; +var _react = _interopRequireWildcard(require("react")); -export const ToolbarRight = (props: Props) => { +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const ToolbarRight = exports.ToolbarRight = props => { return ( // $FlowFixMe(>=0.53.0) Flow suppress -
- {props.children} -
+ _react.createElement( + "div", + { className: "nuclide-ui-toolbar__right" }, + props.children + ) ); -}; +}; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/nuclide-commons-ui/TruncatedButton.js b/modules/nuclide-commons-ui/TruncatedButton.js index 1f0e7a23..cae1cd51 100644 --- a/modules/nuclide-commons-ui/TruncatedButton.js +++ b/modules/nuclide-commons-ui/TruncatedButton.js @@ -1,40 +1,52 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import {Button} from './Button'; -import classnames from 'classnames'; -import * as React from 'react'; - -type Props = { - className?: string, - // $FlowFixMe(>=0.53.0) Flow suppress - children?: React.Children, - label?: string, -}; - -export default class TruncatedButton extends React.Component { - render(): React.Node { - const {children, className, label, ...props} = this.props; - return ( - +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _Button; + +function _load_Button() { + return _Button = require('./Button'); +} + +var _classnames; + +function _load_classnames() { + return _classnames = _interopRequireDefault(require('classnames')); +} + +var _react = _interopRequireWildcard(require('react')); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +class TruncatedButton extends _react.Component { + render() { + const _props = this.props, + { children, className, label } = _props, + props = _objectWithoutProperties(_props, ['children', 'className', 'label']); + return _react.createElement( + (_Button || _load_Button()).Button, + Object.assign({ + className: (0, (_classnames || _load_classnames()).default)('btn-block', 'nuclide-ui-truncated-button', className), + title: label + }, props), + children || label ); } } +exports.default = TruncatedButton; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/addTooltip.js b/modules/nuclide-commons-ui/addTooltip.js index ec2a7d07..91c8dc5d 100644 --- a/modules/nuclide-commons-ui/addTooltip.js +++ b/modules/nuclide-commons-ui/addTooltip.js @@ -1,17 +1,17 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = addTooltip; + +var _react = _interopRequireWildcard(require('react')); + +var _reactDom = _interopRequireDefault(require('react-dom')); -import * as React from 'react'; -import ReactDOM from 'react-dom'; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } /** * Adds a self-disposing Atom's tooltip to a react element. @@ -24,9 +24,19 @@ import ReactDOM from 'react-dom'; * this._myDiv = c; * }} /> */ -export default function addTooltip( - options: atom$TooltipsAddOptions, -): (elementRef: React.ElementRef) => void { +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +function addTooltip(options) { let prevRefDisposable; let immediate = null; @@ -38,18 +48,16 @@ export default function addTooltip( } if (elementRef != null) { - const node = ReactDOM.findDOMNode(elementRef); + const node = _reactDom.default.findDOMNode(elementRef); const initializeTooltip = () => { prevRefDisposable = atom.tooltips.add( - // $FlowFixMe - node, - // $FlowFixMe - { - keyBindingTarget: node, - ...options, - }, - ); + // $FlowFixMe + node, + // $FlowFixMe + Object.assign({ + keyBindingTarget: node + }, options)); }; if (options.keyBindingTarget) { @@ -69,4 +77,4 @@ export default function addTooltip( } } }; -} +} \ No newline at end of file diff --git a/modules/nuclide-commons-ui/bindObservableAsProps.js b/modules/nuclide-commons-ui/bindObservableAsProps.js index 1d29b4e8..b50bae69 100644 --- a/modules/nuclide-commons-ui/bindObservableAsProps.js +++ b/modules/nuclide-commons-ui/bindObservableAsProps.js @@ -1,18 +1,13 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.bindObservableAsProps = bindObservableAsProps; -import type {Observable} from 'rxjs'; +var _react = _interopRequireWildcard(require('react')); -import * as React from 'react'; +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } /** * Injects any key/value pairs from the given Observable value into the component as named props. @@ -23,15 +18,21 @@ import * as React from 'react'; * The wrapped component is guaranteed to render only if the observable has resolved; * otherwise, the wrapper component renders `null`. */ -export function bindObservableAsProps, U: T>( - stream: Observable<{+[key: string]: any}>, - ComposedComponent: T, -): U { +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +function bindObservableAsProps(stream, ComposedComponent) { // $FlowIssue The return type is guaranteed to be the same as the type of ComposedComponent. - return class extends React.Component<$FlowFixMeProps, {[key: string]: any}> { - _subscription: ?rxjs$ISubscription; - _resolved: boolean; - _wrappedComponent: ?T; + return class extends _react.Component { constructor(props) { super(props); @@ -40,37 +41,31 @@ export function bindObservableAsProps, U: T>( this._resolved = false; } - getWrappedComponent(): ?T { + getWrappedComponent() { return this._wrappedComponent; } - componentDidMount(): void { + componentDidMount() { this._subscription = stream.subscribe(newState => { this._resolved = true; this.setState(newState); }); } - componentWillUnmount(): void { + componentWillUnmount() { if (this._subscription != null) { this._subscription.unsubscribe(); } } - render(): React.Node { + render() { if (!this._resolved) { return null; } - const props = { - ...this.props, - ...this.state, - }; - return ( - (this._wrappedComponent = component)} - {...props} - /> - ); + const props = Object.assign({}, this.props, this.state); + return _react.createElement(ComposedComponent, Object.assign({ + ref: component => this._wrappedComponent = component + }, props)); } }; -} +} \ No newline at end of file diff --git a/modules/nuclide-commons-ui/ignoreTextSelectionEvents.js b/modules/nuclide-commons-ui/ignoreTextSelectionEvents.js index a2fcafbe..1af3ed75 100644 --- a/modules/nuclide-commons-ui/ignoreTextSelectionEvents.js +++ b/modules/nuclide-commons-ui/ignoreTextSelectionEvents.js @@ -1,3 +1,8 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,7 +11,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ @@ -29,10 +34,8 @@ * onClick={ignoreTextSelectionEvents(this._onClick)} */ -const ignoreTextSelectionEvents = ( - cb?: (e: SyntheticMouseEvent<>) => mixed, -) => { - return (e: SyntheticMouseEvent<>) => { +const ignoreTextSelectionEvents = cb => { + return e => { // Ignore text selection const selection = getSelection(); if (selection != null && selection.type === 'Range') { @@ -44,4 +47,4 @@ const ignoreTextSelectionEvents = ( }; }; -export default ignoreTextSelectionEvents; +exports.default = ignoreTextSelectionEvents; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/index.js b/modules/nuclide-commons-ui/index.js index 70ac6942..9539f96b 100644 --- a/modules/nuclide-commons-ui/index.js +++ b/modules/nuclide-commons-ui/index.js @@ -1,3 +1,15 @@ +'use strict'; + +var _atom = require('atom'); + +var _fs = _interopRequireDefault(require('fs')); + +var _path = _interopRequireDefault(require('path')); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const styleDir = _path.default.join(__dirname, 'styles'); +// eslint-disable-next-line rulesdir/prefer-nuclide-uri /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,24 +18,13 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ // Requiring this module will load all stylesheets in styles/. // The exported value can be disposed to remove the stylesheets. -import {CompositeDisposable} from 'atom'; -import fs from 'fs'; -// eslint-disable-next-line rulesdir/prefer-nuclide-uri -import path from 'path'; - -const styleDir = path.join(__dirname, 'styles'); -const styleDisposables = new CompositeDisposable( - ...fs - .readdirSync(styleDir) - .filter(file => path.extname(file) === '.less') - .map(file => atom.themes.requireStylesheet(path.join(styleDir, file))), -); +const styleDisposables = new _atom.CompositeDisposable(..._fs.default.readdirSync(styleDir).filter(file => _path.default.extname(file) === '.less').map(file => atom.themes.requireStylesheet(_path.default.join(styleDir, file)))); -module.exports = styleDisposables; // eslint-disable-line rulesdir/no-commonjs +module.exports = styleDisposables; // eslint-disable-line rulesdir/no-commonjs \ No newline at end of file diff --git a/modules/nuclide-commons-ui/observable-dom.js b/modules/nuclide-commons-ui/observable-dom.js index 242977a5..8e21d070 100644 --- a/modules/nuclide-commons-ui/observable-dom.js +++ b/modules/nuclide-commons-ui/observable-dom.js @@ -1,24 +1,25 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -/* eslint-env browser */ -/* global IntersectionObserver, PerformanceObserver, ResizeObserver */ +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ResizeObservable = exports.PerformanceObservable = exports.MutationObservable = exports.IntersectionObservable = exports._DOMObserverObservable = undefined; + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); -import type {Subscriber} from 'rxjs/Subscriber'; +var _shallowequal; -import invariant from 'invariant'; -import {Observable, Subscription} from 'rxjs'; -import shallowEqual from 'shallowequal'; -import {isIterable} from 'nuclide-commons/collection'; +function _load_shallowequal() { + return _shallowequal = _interopRequireDefault(require('shallowequal')); +} + +var _collection; + +function _load_collection() { + return _collection = require('nuclide-commons/collection'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Creates an observable sequence from a DOM-style Observer. @@ -74,49 +75,27 @@ import {isIterable} from 'nuclide-commons/collection'; * mutations.subscribe(record => console.log(record)); */ -type RecordCallback = (records: any, ...rest: Array) => mixed; -interface DOMObserver { - constructor(callback: RecordCallback, ...rest: Array): DOMObserver, - observe(...observeArgs: Array): void, - disconnect(): void, - +unobserve?: (...unobserveArgs: Array) => void, -} +class DOMObserverObservable extends _rxjsBundlesRxMinJs.Observable { -class DOMObserverObservable< - TNext, // what does this observable `next()`? - TEntry, // what is an individual entry? - TObserveArgs: $ReadOnlyArray, // what are the arguments to `observe()` and `unobserve`()? -> extends Observable { - _DOMObserverCtor: Class; - _observations: Array = []; - _domObserver: ?DOMObserver; - _refs: number = 0; - - constructor( - DOMObserverCtor: Class, - ...observeArgs: TObserveArgs - ): void { + constructor(DOMObserverCtor, ...observeArgs) { super(); + this._observations = []; + this._refs = 0; this._DOMObserverCtor = DOMObserverCtor; if (observeArgs.length > 0) { this.observe(...observeArgs); } } - lift( - operator: rxjs$Operator, - ): DOMObserverObservable { - const obs = new DOMObserverObservable( - this._DOMObserverCtor, - ...this._observations[0], - ); + lift(operator) { + const obs = new DOMObserverObservable(this._DOMObserverCtor, ...this._observations[0]); obs._observations = this._observations.slice(); obs.source = this; obs.operator = operator; return obs; } - observe(...observeArgs: TObserveArgs): void { + observe(...observeArgs) { this._observations.push(observeArgs); if (this._domObserver != null) { @@ -124,16 +103,13 @@ class DOMObserverObservable< } } - unobserve(...unobserveArgs: TObserveArgs): void { + unobserve(...unobserveArgs) { if (this._domObserver != null && this._domObserver.unobserve == null) { - throw new Error( - `Cannot unobserve: This observable has an active ${this._DOMObserverCtor - .name} and it does not support unobserve`, - ); + throw new Error(`Cannot unobserve: This observable has an active ${this._DOMObserverCtor.name} and it does not support unobserve`); } for (let i = 0; i < this._observations.length; i++) { - if (shallowEqual(this._observations[i], unobserveArgs)) { + if ((0, (_shallowequal || _load_shallowequal()).default)(this._observations[i], unobserveArgs)) { this._observations.splice(i, 1); break; } @@ -144,27 +120,26 @@ class DOMObserverObservable< } } - flattenEntries(): Observable { + flattenEntries() { return this.mergeMap(records => { - if (isIterable(records)) { + if ((0, (_collection || _load_collection()).isIterable)(records)) { // $FlowFixMe - return Observable.from(records); + return _rxjsBundlesRxMinJs.Observable.from(records); // $FlowFixMe } else if (typeof records.getEntries === 'function') { - return Observable.from(records.getEntries()); + return _rxjsBundlesRxMinJs.Observable.from(records.getEntries()); } - return Observable.throw( - new Error( - 'Tried to merge DOM Observer entries, but they were not iterable nor were they an EntryList.', - ), - ); + return _rxjsBundlesRxMinJs.Observable.throw(new Error('Tried to merge DOM Observer entries, but they were not iterable nor were they an EntryList.')); }); } - _subscribe(subscriber: Subscriber): rxjs$Subscription { + _subscribe(subscriber) { if (this._refs === 0) { - invariant(this._domObserver == null); + if (!(this._domObserver == null)) { + throw new Error('Invariant violation: "this._domObserver == null"'); + } + this._domObserver = new this._DOMObserverCtor(records => { subscriber.next(records); }); @@ -174,7 +149,7 @@ class DOMObserverObservable< } } - const subscription = new Subscription(); + const subscription = new _rxjsBundlesRxMinJs.Subscription(); this._refs++; subscription.add(() => { this._refs--; @@ -182,7 +157,10 @@ class DOMObserverObservable< // the underlying observer should only disconnect when all subscribers have // unsubscribed if (this._refs === 0) { - invariant(this._domObserver != null); + if (!(this._domObserver != null)) { + throw new Error('Invariant violation: "this._domObserver != null"'); + } + this._domObserver.disconnect(); this._domObserver = null; } @@ -190,75 +168,75 @@ class DOMObserverObservable< return subscription; } -} +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ -export const _DOMObserverObservable = DOMObserverObservable; +/* eslint-env browser */ +/* global IntersectionObserver, PerformanceObserver, ResizeObserver */ + +const _DOMObserverObservable = exports._DOMObserverObservable = DOMObserverObservable; /** * Returns an RxJS Observable that wraps an IntersectionObserver */ -export class IntersectionObservable extends DOMObserverObservable< - Array, - IntersectionObserverEntry, - [HTMLElement], -> { - constructor(target: HTMLElement) { - invariant( - global.IntersectionObserver !== null, - 'environment must contain IntersectionObserver', - ); +class IntersectionObservable extends DOMObserverObservable { + constructor(target) { + if (!(global.IntersectionObserver !== null)) { + throw new Error('environment must contain IntersectionObserver'); + } + super(IntersectionObserver, target); } } -/** - * Returns an RxJS Observable that wraps a MutationObserver - */ -export class MutationObservable extends DOMObserverObservable< - Array, - MutationRecord, - // $FlowFixMe - [Node, MutationObserverInit], -> { - constructor(target: Node, options?: MutationObserverInit) { - invariant( - global.MutationObserver !== null, - 'environment must contain MutationObserver', - ); +exports.IntersectionObservable = IntersectionObservable; /** + * Returns an RxJS Observable that wraps a MutationObserver + */ + +class MutationObservable extends DOMObserverObservable { + constructor(target, options) { + if (!(global.MutationObserver !== null)) { + throw new Error('environment must contain MutationObserver'); + } + super(MutationObserver, target); } } -/** - * Returns an RxJS Observable that wraps a PerformanceObserver - */ -export class PerformanceObservable extends DOMObserverObservable< - PerformanceObserverEntryList, - PerformanceEntry, - [PerformanceObserverInit], -> { - constructor(options: PerformanceObserverInit) { - invariant( - global.PerformanceObserver !== null, - 'environment must contain PerformanceObserver', - ); +exports.MutationObservable = MutationObservable; /** + * Returns an RxJS Observable that wraps a PerformanceObserver + */ + +class PerformanceObservable extends DOMObserverObservable { + constructor(options) { + if (!(global.PerformanceObserver !== null)) { + throw new Error('environment must contain PerformanceObserver'); + } + super(PerformanceObserver, options); } } -/** - * Returns an RxJS Observable that wraps a ResizeObserver - */ -export class ResizeObservable extends DOMObserverObservable< - Array, - ResizeObserverEntry, - [HTMLElement], -> { - constructor(target: HTMLElement) { - invariant( - global.ResizeObserver !== null, - 'environment must contain ResizeObserver', - ); +exports.PerformanceObservable = PerformanceObservable; /** + * Returns an RxJS Observable that wraps a ResizeObserver + */ + +class ResizeObservable extends DOMObserverObservable { + constructor(target) { + if (!(global.ResizeObserver !== null)) { + throw new Error('environment must contain ResizeObserver'); + } + super(ResizeObserver, target); } } +exports.ResizeObservable = ResizeObservable; \ No newline at end of file diff --git a/modules/nuclide-commons-ui/renderReactRoot.js b/modules/nuclide-commons-ui/renderReactRoot.js index a50e6a29..3b2da052 100644 --- a/modules/nuclide-commons-ui/renderReactRoot.js +++ b/modules/nuclide-commons-ui/renderReactRoot.js @@ -1,3 +1,26 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.renderReactRoot = renderReactRoot; + +var _react = _interopRequireWildcard(require('react')); + +var _ReactMountRootElement; + +function _load_ReactMountRootElement() { + return _ReactMountRootElement = _interopRequireDefault(require('./ReactMountRootElement')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +/** + * Create a DOM element and mount the React element in it. It will be unmounted when the node is + * detached. + */ /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,19 +29,12 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import * as React from 'react'; -import ReactMountRootElement from './ReactMountRootElement'; - -/** - * Create a DOM element and mount the React element in it. It will be unmounted when the node is - * detached. - */ -export function renderReactRoot(reactElement: React.Element): HTMLElement { - const element = new ReactMountRootElement(); +function renderReactRoot(reactElement) { + const element = new (_ReactMountRootElement || _load_ReactMountRootElement()).default(); element.setReactElement(reactElement); return element; -} +} \ No newline at end of file diff --git a/modules/nuclide-commons-ui/scrollIntoView.js b/modules/nuclide-commons-ui/scrollIntoView.js index 9a4f6a0f..13975e4a 100644 --- a/modules/nuclide-commons-ui/scrollIntoView.js +++ b/modules/nuclide-commons-ui/scrollIntoView.js @@ -1,3 +1,10 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.scrollIntoView = scrollIntoView; +exports.scrollIntoViewIfNeeded = scrollIntoViewIfNeeded; /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,7 +13,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ @@ -41,20 +48,20 @@ * [2]: https://drafts.csswg.org/cssom-view/#scrolling-box */ -export function scrollIntoView(el: Element, alignToTop?: boolean): void { +function scrollIntoView(el, alignToTop) { const scrollTops = getOverflowHiddenScrollTops(el); el.scrollIntoView(alignToTop); // eslint-disable-line rulesdir/dom-apis restoreScrollTops(scrollTops); } -export function scrollIntoViewIfNeeded(el: Element, center?: boolean): void { +function scrollIntoViewIfNeeded(el, center) { const scrollTops = getOverflowHiddenScrollTops(el); // $FlowIgnore: This should be added to the element type. el.scrollIntoViewIfNeeded(center); // eslint-disable-line rulesdir/dom-apis restoreScrollTops(scrollTops); } -function getOverflowHiddenScrollTops(el_: Element): Map { +function getOverflowHiddenScrollTops(el_) { let el = el_; const scrollTops = new Map(); while (el != null) { @@ -66,8 +73,8 @@ function getOverflowHiddenScrollTops(el_: Element): Map { return scrollTops; } -function restoreScrollTops(scrollTops: Map): void { +function restoreScrollTops(scrollTops) { scrollTops.forEach((scrollTop, el) => { el.scrollTop = scrollTop; }); -} +} \ No newline at end of file diff --git a/modules/nuclide-commons-ui/spec/AtomInput-spec.js b/modules/nuclide-commons-ui/spec/AtomInput-spec.js deleted file mode 100644 index bdf4a534..00000000 --- a/modules/nuclide-commons-ui/spec/AtomInput-spec.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import {AtomInput} from '../AtomInput'; -import * as React from 'react'; -import ReactDOM from 'react-dom'; - -let reactElement: any; - -function createWithProps(props: any): any { - const hostEl = document.createElement('div'); - return ReactDOM.render(, hostEl); -} - -describe('AtomInput', () => { - afterEach(() => { - if (reactElement) { - ReactDOM.unmountComponentAtNode( - // $FlowFixMe - ReactDOM.findDOMNode(reactElement).parentNode, - ); - } - reactElement = null; - }); - - it('honors the initialValue param', () => { - reactElement = createWithProps({initialValue: 'some text'}); - expect(reactElement.getText()).toBe('some text'); - expect(reactElement.getTextEditor().getText()).toBe('some text'); - }); - - it('focus() focuses the end of the line', () => { - const initialValue = 'some text'; - reactElement = createWithProps({initialValue}); - expect(reactElement.getTextEditor().getCursorBufferPosition()).toEqual([ - 0, - 0, - ]); - reactElement.focus(); - expect(reactElement.getTextEditor().getCursorBufferPosition()).toEqual([ - 0, - initialValue.length, - ]); - }); - - it('onDidChange() does not fire initially', () => { - const initialValue = 'some text'; - const onDidChange = jasmine.createSpy('onDidChange'); - reactElement = createWithProps({ - initialValue, - onDidChange, - }); - - expect(onDidChange).not.toHaveBeenCalled(); - }); - - it('onDidChange() is fired when the text changes', () => { - const initialValue = 'some text'; - reactElement = createWithProps({initialValue}); - const onDidChange = jasmine.createSpy('onDidChange'); - const disposable = reactElement.onDidChange(onDidChange); - - reactElement.setText('the new text'); - expect(onDidChange.calls.length).toBe(1); - - reactElement.setText('even more new text'); - expect(onDidChange.calls.length).toBe(2); - - disposable.dispose(); - reactElement.setText('the last update'); - expect(onDidChange.calls.length).toBe(2); - }); - - it('updates will stop firing when the component is unmounted', () => { - const initialValue = 'some text'; - reactElement = createWithProps({initialValue}); - const onDidChange = jasmine.createSpy('onDidChange'); - reactElement.onDidChange(onDidChange); - - const textEditor = reactElement.getTextEditor(); - textEditor.setText('the new text'); - expect(onDidChange.calls.length).toBe(1); - - ReactDOM.unmountComponentAtNode( - // $FlowFixMe - ReactDOM.findDOMNode(reactElement).parentNode, - ); - reactElement = null; - - textEditor.setText('even more new text'); - expect(onDidChange.calls.length).toBe(1); - }); -}); diff --git a/modules/nuclide-commons-ui/spec/AtomTextEditor-spec.js b/modules/nuclide-commons-ui/spec/AtomTextEditor-spec.js deleted file mode 100644 index f7ae2040..00000000 --- a/modules/nuclide-commons-ui/spec/AtomTextEditor-spec.js +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import {AtomTextEditor} from '../AtomTextEditor'; -import * as React from 'react'; -import TestUtils from 'react-addons-test-utils'; -import invariant from 'assert'; - -describe('nuclide-ui-atom-text-editor', () => { - describe('when its `path` is set', () => { - let grammar; - - beforeEach(() => { - // Path is relative to the root of this package (where "package.json" lives). - grammar = atom.grammars.loadGrammarSync('spec/grammars/test1.cson'); - }); - - afterEach(() => { - if (grammar) { - atom.grammars.removeGrammarForScopeName(grammar.scopeName); - } - }); - - it('loads the desired `Grammar`', () => { - const element = TestUtils.renderIntoDocument( - , - ); - expect(element.getModel().getGrammar().scopeName).toEqual('text.test'); - }); - }); - - describe('providing a grammar', () => { - let grammar1; - let grammar2; - - beforeEach(() => { - grammar1 = atom.grammars.loadGrammarSync('spec/grammars/test1.cson'); - grammar2 = atom.grammars.loadGrammarSync('spec/grammars/test2.cson'); - }); - - afterEach(() => { - invariant(grammar1 != null); - atom.grammars.removeGrammarForScopeName(grammar1.scopeName); - invariant(grammar2 != null); - atom.grammars.removeGrammarForScopeName(grammar2.scopeName); - }); - - it('updates the underlying models grammar', () => { - const element = TestUtils.renderIntoDocument( - , - ); - expect(element.getModel().getGrammar().scopeName).toEqual('text.test2'); - }); - }); - - describe('when `readOnly`', () => { - let element; - - describe('is true', () => { - beforeEach(() => { - element = TestUtils.renderIntoDocument( - , - ); - }); - - it('allows copying', () => { - invariant(element); - const model = element.getModel(); - model.setText('fraggle'); - model.selectAll(); - model.copySelectedText(); - expect(atom.clipboard.read()).toEqual('fraggle'); - }); - - it('disallows inserting', () => { - invariant(element); - const model = element.getModel(); - model.setText('foobar'); - model.insertNewline(); - expect(model.getText()).toEqual('foobar'); - }); - - it('disallows pasting', () => { - invariant(element); - const model = element.getModel(); - atom.clipboard.write('foo bar baz'); - model.pasteText(); - expect(model.getText()).toEqual(''); - }); - - it('disallows deleting text', () => { - invariant(element); - const model = element.getModel(); - model.setText('balloon'); - model.selectAll(); - model.delete(); - expect(model.getText()).toEqual('balloon'); - }); - - it('disallows backspace', () => { - invariant(element); - const model = element.getModel(); - model.setText('foobar'); - model.moveToEndOfLine(); - model.backspace(); - expect(model.getText()).toEqual('foobar'); - }); - }); - - describe('is undefined', () => { - beforeEach(() => { - element = TestUtils.renderIntoDocument(); - }); - - it('allows copying', () => { - invariant(element); - const model = element.getModel(); - model.setText('fraggle'); - model.selectAll(); - model.copySelectedText(); - expect(atom.clipboard.read()).toEqual('fraggle'); - }); - - it('allows inserting', () => { - invariant(element); - const model = element.getModel(); - model.setText('foobar'); - model.insertNewline(); - expect(model.getText()).toEqual('foobar\n'); - }); - - it('allows pasting', () => { - invariant(element); - const model = element.getModel(); - atom.clipboard.write('foo bar baz'); - model.pasteText(); - expect(model.getText()).toEqual('foo bar baz'); - }); - - it('allows deleting text', () => { - invariant(element); - const model = element.getModel(); - model.setText('balloon'); - model.selectAll(); - model.delete(); - expect(model.getText()).toEqual(''); - }); - - it('allows backspace', () => { - invariant(element); - const model = element.getModel(); - model.setText('foobar'); - model.moveToEndOfLine(); - model.backspace(); - expect(model.getText()).toEqual('fooba'); - }); - }); - }); -}); diff --git a/modules/nuclide-commons-ui/spec/Checkbox-spec.js b/modules/nuclide-commons-ui/spec/Checkbox-spec.js deleted file mode 100644 index cf31f76c..00000000 --- a/modules/nuclide-commons-ui/spec/Checkbox-spec.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import {Checkbox} from '../Checkbox'; -import nullthrows from 'nullthrows'; -import * as React from 'react'; -import ReactDOM from 'react-dom'; -import TestUtils from 'react-addons-test-utils'; - -let hostEl; - -function createWithProps(props) { - return ReactDOM.render(, hostEl); -} - -describe('Checkbox', () => { - beforeEach(() => { - hostEl = document.createElement('div'); - }); - - afterEach(() => { - ReactDOM.unmountComponentAtNode(hostEl); - hostEl = null; - }); - - it('onChange handler fires when change event dispatched from checkbox', () => { - const onChange = jasmine.createSpy(); - const reactElement = createWithProps({ - checked: false, - label: 'click me!', - onChange, - }); - - const inputEl = nullthrows( - TestUtils.findRenderedDOMComponentWithTag(reactElement, 'input'), - ); - // Unfortunately, TestUtils does not seem to turn a click into a change event for a checkbox. - TestUtils.Simulate.change(inputEl); - expect(onChange.callCount).toBe(1); - - // Nor does it seem to change the state of the checkbox, as the following fails: - // expect(inputEl.checked).toBe(true); - // Presumably this is because TestUtils deals only with synthetic events, not native ones. - }); - - it('sets `indeterminate` on the element instance', () => { - const reactElement = createWithProps({ - checked: false, - indeterminate: true, - label: 'click me!', - onChange() {}, - }); - - const inputEl = nullthrows( - TestUtils.findRenderedDOMComponentWithTag(reactElement, 'input'), - ); - // $FlowFixMe - expect(inputEl.indeterminate).toBe(true); - }); -}); diff --git a/modules/nuclide-commons-ui/spec/ClickOutsideBoundry-spec.js b/modules/nuclide-commons-ui/spec/ClickOutsideBoundry-spec.js deleted file mode 100644 index 108f40c7..00000000 --- a/modules/nuclide-commons-ui/spec/ClickOutsideBoundry-spec.js +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import * as React from 'react'; -import invariant from 'assert'; -import {render} from 'react-dom'; -import ClickOutsideBoundary from '../ClickOutsideBoundary'; - -const clickId = (id: string) => { - const node = document.getElementById(id); - invariant(node != null, `node ${id} should be present in the DOM`); - node.click(); -}; - -// A component which removes itself from the DOM when clicked. -// $FlowFixMe(>=0.53.0) Flow suppress -class ClickAway extends React.Component<$FlowFixMeProps, $FlowFixMeState> { - constructor(props) { - super(props); - this.state = {visible: true}; - } - - handleClick = () => { - this.setState({visible: false}); - }; - - render() { - return this.state.visible - ? - Click to dismiss - - : null; - } -} - -describe('ClickOutsideBoundary - onClickOutside handler', () => { - let app; - let onClickOutside; - - beforeEach(() => { - app = document.createElement('div'); - window.document.body.appendChild(app); - onClickOutside = jasmine.createSpy('onClickOutside'); - }); - - afterEach(() => { - window.document.body.removeChild(app); - }); - - describe('_is_ called for an external click', () => { - it('on a parent', () => { - render( -
- -
- -
, - app, - ); - clickId('container'); - expect(onClickOutside).toHaveBeenCalled(); - }); - - it('on a sibling', () => { - render( -
- -
- -
-
, - app, - ); - clickId('sibling'); - expect(onClickOutside).toHaveBeenCalled(); - }); - - it('on a sibling that dissapears after render', () => { - // This would fail if we tool the approach of ignoring all - // clicks on elements that were not in the DOM. - render( -
- -
- - -
, - app, - ); - clickId('click-away'); - expect(onClickOutside).toHaveBeenCalled(); - }); - }); - - describe('is _not_ called for an internal click', () => { - it('under normal conditions', () => { - render( - -
- , - app, - ); - clickId('target'); - expect(onClickOutside).not.toHaveBeenCalled(); - }); - - it('when the target leaves the DOM before the event reaches window.document', () => { - // A simple approach: `this.rootNode.contains(e.target)` would fail this test. - const onClickInside = jasmine.createSpy('onClickInside'); - render( - -
- -
-
, - app, - ); - clickId('click-away'); - expect(onClickInside).toHaveBeenCalled(); - expect(onClickOutside).not.toHaveBeenCalled(); - }); - }); -}); diff --git a/modules/nuclide-commons-ui/spec/ReactMountRootElement-spec.js b/modules/nuclide-commons-ui/spec/ReactMountRootElement-spec.js deleted file mode 100644 index 028c9b94..00000000 --- a/modules/nuclide-commons-ui/spec/ReactMountRootElement-spec.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -const modulePath = require.resolve('../ReactMountRootElement'); - -describe('ReactMountRootElement', () => { - it('works when required twice', () => { - const element1 = require(modulePath).default; - delete require.cache[modulePath]; - const element2 = require(modulePath).default; - expect(element1).toBe(element2); - // Make sure this doesn't throw. - const createdElement = new element2(); - expect(createdElement.constructor.name).toBe('nuclide-react-mount-root'); - }); -}); diff --git a/modules/nuclide-commons-ui/spec/grammars/test1.cson b/modules/nuclide-commons-ui/spec/grammars/test1.cson deleted file mode 100644 index 863c2f5c..00000000 --- a/modules/nuclide-commons-ui/spec/grammars/test1.cson +++ /dev/null @@ -1,5 +0,0 @@ -'name': 'Test Grammar' -'scopeName': 'text.test' -'fileTypes': [ - 'test' -] diff --git a/modules/nuclide-commons-ui/spec/grammars/test2.cson b/modules/nuclide-commons-ui/spec/grammars/test2.cson deleted file mode 100644 index 8a4965f1..00000000 --- a/modules/nuclide-commons-ui/spec/grammars/test2.cson +++ /dev/null @@ -1,5 +0,0 @@ -'name': 'Test Grammar 2' -'scopeName': 'text.test2' -'fileTypes': [ - 'test' -] diff --git a/modules/nuclide-commons-ui/spec/observable-dom-spec.js b/modules/nuclide-commons-ui/spec/observable-dom-spec.js deleted file mode 100644 index 39b23cfa..00000000 --- a/modules/nuclide-commons-ui/spec/observable-dom-spec.js +++ /dev/null @@ -1,261 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import invariant from 'invariant'; -import {Observable} from 'rxjs'; - -import {_DOMObserverObservable as DOMObserverObservable} from '../observable-dom'; - -describe('new DOMObserverObservable', () => { - let observerInstance; - - beforeEach(() => { - observerInstance = null; - }); - - class MockDOMObserver { - _args: Array; - _callback: Function; - _connected: boolean; - - constructor(callback) { - this._callback = callback; - observerInstance = this; - } - observe(...args: any[]) { - this._args = args; - this._connected = true; - } - disconnect() { - this._connected = false; - } - } - - it('does not construct a DOM Observer until the Rx Observable is subscribed to', () => { - const o = new DOMObserverObservable(MockDOMObserver, 'some', 'additional', { - args: true, - }); - expect(observerInstance).toBe(null); - - const subscription = o.subscribe(() => {}); - invariant(observerInstance != null); - expect(observerInstance._args).toEqual([ - 'some', - 'additional', - {args: true}, - ]); - expect(observerInstance._connected).toBe(true); - subscription.unsubscribe(); - }); - - it('calls disconnect on the underlying DOM Observer when unsubscribe is called', () => { - const o = new DOMObserverObservable(MockDOMObserver, 'some', 'additional', { - args: true, - }); - const subscription = o.subscribe(() => {}); - - invariant(observerInstance != null); - expect(observerInstance._connected).toBe(true); - - subscription.unsubscribe(); - expect(observerInstance._connected).toBe(false); - }); - - it( - 'by default (without a call to .flattenEntries()) creates an observable of ' + - 'the elements emitted from the DOM Observer', - () => { - class MockDOMObserverEmitsArray extends MockDOMObserver { - observe(...args: Array) { - super.observe(...args); - Observable.interval(1) - .mapTo(['foo', 'bar', 'baz']) - .take(2) - .subscribe(this._callback); - } - } - - waitsForPromise(async () => { - const output = await new DOMObserverObservable( - MockDOMObserverEmitsArray, - 'arg', - ) - .take(2) - .toArray() - .toPromise(); - expect(output).toEqual([['foo', 'bar', 'baz'], ['foo', 'bar', 'baz']]); - }); - }, - ); - - describe('multiple subscribers', () => { - it('only disconnects the underlying observer when all subscribers have unsubscribed', () => { - const o = new DOMObserverObservable( - MockDOMObserver, - 'some', - 'additional', - { - args: true, - }, - ); - const subscription = o.subscribe(() => {}); - const subscription2 = o.subscribe(() => {}); - - invariant(observerInstance != null); - expect(observerInstance._connected).toBe(true); - - subscription.unsubscribe(); - // the underlying observer is still connected when only one of the two - // subscribers unsubscribes - expect(observerInstance._connected).toBe(true); - - expect(() => { - subscription2.unsubscribe(); - }).not.toThrow(); - // and finally disconnect when all subscribers have unsubscribed - expect(observerInstance._connected).toBe(false); - }); - - it( - 'creates a new underlying observable and connects it for new' + - 'subscriptions that happen after a disconnect', - () => { - const o = new DOMObserverObservable( - MockDOMObserver, - 'some', - 'additional', - { - args: true, - }, - ); - const subscription = o.subscribe(() => {}); - const subscription2 = o.subscribe(() => {}); - - invariant(observerInstance != null); - const oldObserver = observerInstance; - - subscription.unsubscribe(); - subscription2.unsubscribe(); - - expect(observerInstance._connected).toBe(false); - const newSubscription = o.subscribe(() => {}); - // creates a new underlying observer - expect(observerInstance).not.toBe(oldObserver); - expect(observerInstance._connected).toBe(true); - newSubscription.unsubscribe(); - }, - ); - }); - - describe('flattenEntries operator', () => { - it('implements lift to cause subsequent operators to return DOMObserverObservables', () => { - class MockDOMObserverEmitsArray extends MockDOMObserver { - observe(...args: Array) { - super.observe(...args); - Observable.interval(1) - .mapTo(['foo', 'bar', 'baz']) - .take(2) - .subscribe(this._callback); - } - } - - expect( - new DOMObserverObservable(MockDOMObserverEmitsArray, 'arg') - .flattenEntries() - .map(x => x) instanceof DOMObserverObservable, - ).toBe(true); - }); - - it('creates an observable of the individual elements of the array emitted from the DOM Observer', () => { - class MockDOMObserverEmitsArray extends MockDOMObserver { - observe(...args: Array) { - super.observe(...args); - Observable.interval(1) - .mapTo(['foo', 'bar', 'baz']) - .take(2) - .subscribe(this._callback); - } - } - - waitsForPromise(async () => { - const output = await new DOMObserverObservable( - MockDOMObserverEmitsArray, - 'arg', - ) - .flattenEntries() - .take(6) - .toArray() - .toPromise(); - expect(output).toEqual(['foo', 'bar', 'baz', 'foo', 'bar', 'baz']); - }); - }); - - it( - 'creates an observable of the individual elements of the array returned ' + - 'from the getEntries method of the entrylist emitted from the DOM Observer', - () => { - class MockDOMObserverEmitsEntryList extends MockDOMObserver { - observe(...args: Array) { - super.observe(...args); - Observable.interval(1) - .mapTo({ - getEntries: () => ['foo', 'bar', 'baz'], - }) - .take(2) - .subscribe(this._callback); - } - } - - waitsForPromise(async () => { - const output = await new DOMObserverObservable( - MockDOMObserverEmitsEntryList, - 'arg', - ) - .flattenEntries() - .take(6) - .toArray() - .toPromise(); - expect(output).toEqual(['foo', 'bar', 'baz', 'foo', 'bar', 'baz']); - }); - }, - ); - - it('throws if neither an iterable nor an EntryList is emitted from the DOM Observer', () => { - class MockDOMObserverEmitsNonStandard extends MockDOMObserver { - observe(...args: Array) { - super.observe(...args); - Observable.interval(1).take(2).subscribe(this._callback); - } - } - - waitsForPromise(async () => { - let error; - try { - await new DOMObserverObservable( - MockDOMObserverEmitsNonStandard, - 'arg', - ) - .flattenEntries() - .take(2) - .toArray() - .toPromise(); - } catch (e) { - error = e; - } - invariant(error != null); - expect(error.message).toEqual( - 'Tried to merge DOM Observer entries, but they were not iterable nor were they an EntryList.', - ); - }); - }); - }); -}); diff --git a/modules/nuclide-commons/BatchProcessedQueue.js b/modules/nuclide-commons/BatchProcessedQueue.js index af881faf..9bd095b5 100644 --- a/modules/nuclide-commons/BatchProcessedQueue.js +++ b/modules/nuclide-commons/BatchProcessedQueue.js @@ -1,33 +1,22 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); -export type BatchHandler = (batch: Array) => void; // A Queue which will process elements at intervals, only if the // queue contains any elements. -export default class BatchProcessedQueue { - _batchPeriod: number; - _handler: BatchHandler; - _timeoutId: ?number; - _items: Array; +class BatchProcessedQueue { - constructor(batchPeriod: number, handler: BatchHandler) { + constructor(batchPeriod, handler) { this._batchPeriod = batchPeriod; this._handler = handler; this._timeoutId = null; this._items = []; } - add(item: T): void { + add(item) { this._items.push(item); if (this._timeoutId === null) { this._timeoutId = setTimeout(() => { @@ -43,10 +32,21 @@ export default class BatchProcessedQueue { this._handler(batch); } - dispose(): void { + dispose() { if (this._timeoutId !== null) { clearTimeout(this._timeoutId); this._handleBatch(); } } } +exports.default = BatchProcessedQueue; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/nuclide-commons/ConfigCache.js b/modules/nuclide-commons/ConfigCache.js index d956839c..d09470e7 100644 --- a/modules/nuclide-commons/ConfigCache.js +++ b/modules/nuclide-commons/ConfigCache.js @@ -1,3 +1,26 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ConfigCache = undefined; + +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + +var _lruCache; + +function _load_lruCache() { + return _lruCache = _interopRequireDefault(require('lru-cache')); +} + +var _fsPromise; + +function _load_fsPromise() { + return _fsPromise = _interopRequireDefault(require('./fsPromise')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,29 +29,20 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import type {LRUCache} from 'lru-cache'; -import type {NuclideUri} from './nuclideUri'; +class ConfigCache { -import LRU from 'lru-cache'; -import fsPromise from './fsPromise'; - -export class ConfigCache { - _configFileNames: Array; - _configCache: LRUCache>; - - constructor(configFileNames: Array) { + constructor(configFileNames) { this._configFileNames = configFileNames; - this._configCache = LRU({ + this._configCache = (0, (_lruCache || _load_lruCache()).default)({ max: 200, // Want this to exceed the maximum expected number of open files + dirs. - maxAge: 1000 * 30, // 30 seconds - }); + maxAge: 1000 * 30 }); } - getConfigDir(path: NuclideUri): Promise { + getConfigDir(path) { let result = this._configCache.get(path); if (result == null) { result = this._findConfigDir(path); @@ -37,22 +51,25 @@ export class ConfigCache { return result; } - async _findConfigDir(path: NuclideUri): Promise { - const configDirs = await Promise.all( - this._configFileNames.map(configFile => - fsPromise.findNearestFile(configFile, path), - ), - ); - // Find the result with the greatest length (the closest match). - return configDirs.filter(Boolean).reduce((previous, configDir) => { - if (previous == null || configDir.length > previous.length) { - return configDir; - } - return previous; - }, null); + _findConfigDir(path) { + var _this = this; + + return (0, _asyncToGenerator.default)(function* () { + const configDirs = yield Promise.all(_this._configFileNames.map(function (configFile) { + return (_fsPromise || _load_fsPromise()).default.findNearestFile(configFile, path); + })); + // Find the result with the greatest length (the closest match). + return configDirs.filter(Boolean).reduce(function (previous, configDir) { + if (previous == null || configDir.length > previous.length) { + return configDir; + } + return previous; + }, null); + })(); } - dispose(): void { + dispose() { this._configCache.reset(); } } +exports.ConfigCache = ConfigCache; \ No newline at end of file diff --git a/modules/nuclide-commons/Hasher.js b/modules/nuclide-commons/Hasher.js index bf32cceb..549acb00 100644 --- a/modules/nuclide-commons/Hasher.js +++ b/modules/nuclide-commons/Hasher.js @@ -1,3 +1,8 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,7 +11,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ @@ -29,33 +34,29 @@ * } * } */ -export default class Hasher { - _hashes: WeakMap; - _objectCount: number; +class Hasher { constructor() { this._hashes = new WeakMap(); this._objectCount = 0; } - getHash(item: K): string | number { + getHash(item) { if (item === null) { return 'null'; } const type = typeof item; switch (typeof item) { - case 'object': { - let hash = this._hashes.get(item); - if (hash == null) { - hash = `${type}:${this._objectCount}`; - this._hashes.set(item, hash); - this._objectCount = - this._objectCount + 1 === Number.MAX_SAFE_INTEGER - ? Number.MIN_SAFE_INTEGER - : this._objectCount + 1; + case 'object': + { + let hash = this._hashes.get(item); + if (hash == null) { + hash = `${type}:${this._objectCount}`; + this._hashes.set(item, hash); + this._objectCount = this._objectCount + 1 === Number.MAX_SAFE_INTEGER ? Number.MIN_SAFE_INTEGER : this._objectCount + 1; + } + return hash; } - return hash; - } case 'undefined': return 'undefined'; case 'string': @@ -68,3 +69,4 @@ export default class Hasher { } } } +exports.default = Hasher; \ No newline at end of file diff --git a/modules/nuclide-commons/Model.js b/modules/nuclide-commons/Model.js index 6a2d0a52..4b63270e 100644 --- a/modules/nuclide-commons/Model.js +++ b/modules/nuclide-commons/Model.js @@ -1,19 +1,18 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import type {Observable} from 'rxjs'; +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('./UniversalDisposable')); +} -import {BehaviorSubject} from 'rxjs'; -import UniversalDisposable from './UniversalDisposable'; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Exposes a simple API for a stateful model. This is similar to React's `state`/`setState()` API @@ -52,27 +51,37 @@ import UniversalDisposable from './UniversalDisposable'; * action creators. That's awesome! It means that, should the state grow and require new * capabilities, we can always switch to full-blown Redux without having to refactor a ton of stuff. */ -export default class Model { - _states: BehaviorSubject; +class Model { - constructor(initialState: State) { - this._states = new BehaviorSubject(initialState); + constructor(initialState) { + this._states = new _rxjsBundlesRxMinJs.BehaviorSubject(initialState); } - setState(newState: $Shape): void { - const nextState = {...this.state, ...newState}; + setState(newState) { + const nextState = Object.assign({}, this.state, newState); this._states.next(nextState); } - get state(): State { + get state() { return this._states.getValue(); } - subscribe(cb: (state: State) => mixed): IDisposable { - return new UniversalDisposable(this.toObservable().subscribe({next: cb})); + subscribe(cb) { + return new (_UniversalDisposable || _load_UniversalDisposable()).default(this.toObservable().subscribe({ next: cb })); } - toObservable(): Observable { + toObservable() { return this._states.distinctUntilChanged(); } } +exports.default = Model; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/nuclide-commons/UniversalDisposable.js b/modules/nuclide-commons/UniversalDisposable.js index 65836a52..092bc561 100644 --- a/modules/nuclide-commons/UniversalDisposable.js +++ b/modules/nuclide-commons/UniversalDisposable.js @@ -1,26 +1,17 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); -export type AnyTeardown = (() => mixed) | rxjs$ISubscription | IDisposable; /** * Like a CompositeDisposable, but in addition to Disposable instances it can * also accept plain functions and Rx subscriptions. */ -export default class UniversalDisposable { - disposed: boolean; - teardowns: Set; +class UniversalDisposable { - constructor(...teardowns: Array) { + constructor(...teardowns) { this.teardowns = new Set(); this.disposed = false; if (teardowns.length) { @@ -28,7 +19,7 @@ export default class UniversalDisposable { } } - add(...teardowns: Array): void { + add(...teardowns) { if (this.disposed) { throw new Error('Cannot add to an already disposed UniversalDisposable!'); } @@ -38,13 +29,13 @@ export default class UniversalDisposable { } } - remove(teardown: AnyTeardown): void { + remove(teardown) { if (!this.disposed) { this.teardowns.delete(teardown); } } - dispose(): void { + dispose() { if (!this.disposed) { this.disposed = true; this.teardowns.forEach(teardown => { @@ -56,30 +47,36 @@ export default class UniversalDisposable { teardown(); } }); - this.teardowns = (null: any); + this.teardowns = null; } } - unsubscribe(): void { + unsubscribe() { this.dispose(); } - clear(): void { + clear() { if (!this.disposed) { this.teardowns.clear(); } } } -function assertTeardown(teardown: AnyTeardown): void { - if ( - typeof teardown.dispose === 'function' || - typeof teardown.unsubscribe === 'function' || - typeof teardown === 'function' - ) { +exports.default = UniversalDisposable; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +function assertTeardown(teardown) { + if (typeof teardown.dispose === 'function' || typeof teardown.unsubscribe === 'function' || typeof teardown === 'function') { return; } - throw new TypeError( - 'Arguments to UniversalDisposable.add must be disposable', - ); -} + throw new TypeError('Arguments to UniversalDisposable.add must be disposable'); +} \ No newline at end of file diff --git a/modules/nuclide-commons/cache.js b/modules/nuclide-commons/cache.js index 9f18c991..e5f7b60a 100644 --- a/modules/nuclide-commons/cache.js +++ b/modules/nuclide-commons/cache.js @@ -1,39 +1,27 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DISPOSE_VALUE = exports.Cache = undefined; -import {Observable, Subject} from 'rxjs'; +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); // A Cache mapping keys to values which creates entries as they are requested. -export class Cache { - _values: Map; - _factory: (key: KeyType) => ValueType; - _disposeValue: (value: ValueType) => mixed; - _entriesSubject: Subject<[KeyType, ValueType]>; - - constructor( - factory: (key: KeyType) => ValueType, - disposeValue: (value: ValueType) => mixed = value => {}, - ) { +class Cache { + + constructor(factory, disposeValue = value => {}) { this._values = new Map(); this._factory = factory; this._disposeValue = disposeValue; - this._entriesSubject = new Subject(); + this._entriesSubject = new _rxjsBundlesRxMinJs.Subject(); } - has(key: KeyType): boolean { + has(key) { return this._values.has(key); } - get(key: KeyType): ValueType { + get(key) { if (!this._values.has(key)) { const newValue = this._factory(key); this._values.set(key, newValue); @@ -41,14 +29,14 @@ export class Cache { return newValue; } else { // Cannot use invariant as ValueType may include null/undefined. - return (this._values.get(key): any); + return this._values.get(key); } } // After this method this._values.keys() === newKeys. // deletes all keys not in newKeys // gets all keys in newKeys - setKeys(newKeys: Set): void { + setKeys(newKeys) { for (const existingKey of this._values.keys()) { if (!newKeys.has(existingKey)) { this.delete(existingKey); @@ -60,30 +48,27 @@ export class Cache { } } - keys(): Iterator { + keys() { return this._values.keys(); } - values(): Iterator { + values() { return this._values.values(); } - observeValues(): Observable { + observeValues() { return this.observeEntries().map(entry => entry[1]); } - observeEntries(): Observable<[KeyType, ValueType]> { - return Observable.concat( - Observable.from(this._values.entries()), - this._entriesSubject, - ); + observeEntries() { + return _rxjsBundlesRxMinJs.Observable.concat(_rxjsBundlesRxMinJs.Observable.from(this._values.entries()), this._entriesSubject); } - observeKeys(): Observable { + observeKeys() { return this.observeEntries().map(entry => entry[0]); } - delete(key: KeyType): boolean { + delete(key) { if (this.has(key)) { const value = this.get(key); this._values.delete(key); @@ -94,7 +79,7 @@ export class Cache { } } - clear(): void { + clear() { // Defend against a dispose call removing elements from the Cache. const values = this._values; this._values = new Map(); @@ -103,13 +88,25 @@ export class Cache { } } - dispose(): void { + dispose() { this.clear(); this._entriesSubject.complete(); } } -// Useful for optional second parameter to Cache constructor. -export const DISPOSE_VALUE = (value: IDisposable) => { +exports.Cache = Cache; // Useful for optional second parameter to Cache constructor. +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const DISPOSE_VALUE = exports.DISPOSE_VALUE = value => { value.dispose(); -}; +}; \ No newline at end of file diff --git a/modules/nuclide-commons/collection.js b/modules/nuclide-commons/collection.js index cbafdd11..db863770 100644 --- a/modules/nuclide-commons/collection.js +++ b/modules/nuclide-commons/collection.js @@ -1,3 +1,42 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.arrayRemove = arrayRemove; +exports.arrayEqual = arrayEqual; +exports.arrayCompact = arrayCompact; +exports.arrayFlatten = arrayFlatten; +exports.arrayUnique = arrayUnique; +exports.arrayFindLastIndex = arrayFindLastIndex; +exports.mapUnion = mapUnion; +exports.mapCompact = mapCompact; +exports.mapFilter = mapFilter; +exports.mapTransform = mapTransform; +exports.mapEqual = mapEqual; +exports.mapGetWithDefault = mapGetWithDefault; +exports.areSetsEqual = areSetsEqual; +exports.every = every; +exports.setIntersect = setIntersect; +exports.setUnion = setUnion; +exports.setDifference = setDifference; +exports.setFilter = setFilter; +exports.isEmpty = isEmpty; +exports.keyMirror = keyMirror; +exports.collect = collect; +exports.objectValues = objectValues; +exports.objectEntries = objectEntries; +exports.objectFromMap = objectFromMap; +exports.concatIterators = concatIterators; +exports.someOfIterable = someOfIterable; +exports.findInIterable = findInIterable; +exports.filterIterable = filterIterable; +exports.mapIterable = mapIterable; +exports.firstOfIterable = firstOfIterable; +exports.iterableIsEmpty = iterableIsEmpty; +exports.iterableContains = iterableContains; +exports.count = count; +exports.isIterable = isIterable; /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,26 +45,22 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -export function arrayRemove(array: Array, element: T): void { +function arrayRemove(array, element) { const index = array.indexOf(element); if (index >= 0) { array.splice(index, 1); } } -export function arrayEqual( - array1: Array, - array2: Array, - equalComparator?: (a: T, b: T) => boolean, -): boolean { +function arrayEqual(array1, array2, equalComparator) { if (array1.length !== array2.length) { return false; } - const equalFunction = equalComparator || ((a: T, b: T) => a === b); + const equalFunction = equalComparator || ((a, b) => a === b); return array1.every((item1, i) => equalFunction(item1, array2[i])); } @@ -33,7 +68,7 @@ export function arrayEqual( * Returns a copy of the input Array with all `null` and `undefined` values filtered out. * Allows Flow to typecheck the common `filter(x => x != null)` pattern. */ -export function arrayCompact(array: Array): Array { +function arrayCompact(array) { const result = []; for (const elem of array) { if (elem != null) { @@ -46,7 +81,7 @@ export function arrayCompact(array: Array): Array { /** * Flattens an Array> into just an Array */ -export function arrayFlatten(array: Array>): Array { +function arrayFlatten(array) { const result = []; for (const subArray of array) { result.push(...subArray); @@ -59,7 +94,7 @@ export function arrayFlatten(array: Array>): Array { * Uses SameValueZero for equality purposes, which is like '===' except it deems * two NaNs equal. http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero */ -export function arrayUnique(array: Array): Array { +function arrayUnique(array) { return Array.from(new Set(array)); } @@ -67,11 +102,7 @@ export function arrayUnique(array: Array): Array { * Returns the last index in the input array that matches the predicate. * Returns -1 if no match is found. */ -export function arrayFindLastIndex( - array: Array, - predicate: (elem: T, index: number, array: Array) => boolean, - thisArg?: any, -): number { +function arrayFindLastIndex(array, predicate, thisArg) { for (let i = array.length - 1; i >= 0; i--) { if (predicate.call(thisArg, array[i], i, array)) { return i; @@ -84,7 +115,7 @@ export function arrayFindLastIndex( * Merges a given arguments of maps into one Map, with the latest maps * overriding the values of the prior maps. */ -export function mapUnion(...maps: Array>): Map { +function mapUnion(...maps) { const unionMap = new Map(); for (const map of maps) { for (const [key, value] of map) { @@ -94,7 +125,7 @@ export function mapUnion(...maps: Array>): Map { return unionMap; } -export function mapCompact(map: Map): Map { +function mapCompact(map) { const selected = new Map(); for (const [key, value] of map) { if (value != null) { @@ -104,10 +135,7 @@ export function mapCompact(map: Map): Map { return selected; } -export function mapFilter( - map: Map, - selector: (key: T, value: X) => boolean, -): Map { +function mapFilter(map, selector) { const selected = new Map(); for (const [key, value] of map) { if (selector(key, value)) { @@ -117,10 +145,7 @@ export function mapFilter( return selected; } -export function mapTransform( - src: Map, - transform: (value: V1, key: T) => V2, -): Map { +function mapTransform(src, transform) { const result = new Map(); for (const [key, value] of src) { result.set(key, transform(value, key)); @@ -128,47 +153,36 @@ export function mapTransform( return result; } -export function mapEqual( - map1: Map, - map2: Map, - equalComparator?: (val1: X, val2: X, key1?: T, key2?: T) => boolean, -) { +function mapEqual(map1, map2, equalComparator) { if (map1.size !== map2.size) { return false; } - const equalFunction = equalComparator || ((a: X, b: X) => a === b); + const equalFunction = equalComparator || ((a, b) => a === b); for (const [key1, value1] of map1) { - if (!map2.has(key1) || !equalFunction(value1, (map2.get(key1): any))) { + if (!map2.has(key1) || !equalFunction(value1, map2.get(key1))) { return false; } } return true; } -export function mapGetWithDefault( - map: Map, - key: K, - default_: V, -): V { +function mapGetWithDefault(map, key, default_) { if (map.has(key)) { // Cast through `any` since map.get's return is a maybe type. We can't just get the value and // check it against `null`, since null/undefined may inhabit V. We know this is safe since we // just checked that the map has the key. - return (map.get(key): any); + return map.get(key); } else { return default_; } } -export function areSetsEqual(a: Set, b: Set): boolean { +function areSetsEqual(a, b) { return a.size === b.size && every(a, element => b.has(element)); } // Array.every but for any iterable. -export function every( - values: Iterable, - predicate: (element: T) => boolean, -): boolean { +function every(values, predicate) { for (const element of values) { if (!predicate(element)) { return false; @@ -177,11 +191,11 @@ export function every( return true; } -export function setIntersect(a: Set, b: Set): Set { +function setIntersect(a, b) { return setFilter(a, e => b.has(e)); } -export function setUnion(a: Set, b: Set): Set { +function setUnion(a, b) { // Avoids the extra Array allocations that `new Set([...a, ...b])` would incur. Some quick tests // indicate it would be about 60% slower. const result = new Set(a); @@ -191,11 +205,7 @@ export function setUnion(a: Set, b: Set): Set { return result; } -export function setDifference( - a: Set, - b: Set, - hash_?: (v: T) => any, -): Set { +function setDifference(a, b, hash_) { if (a.size === 0) { return new Set(); } else if (b.size === 0) { @@ -212,10 +222,7 @@ export function setDifference( return result; } -export function setFilter( - set: Set, - predicate: (value: T) => boolean, -): Set { +function setFilter(set, predicate) { const out = new Set(); for (const item of set) { if (predicate(item)) { @@ -229,7 +236,7 @@ export function setFilter( /** * O(1)-check if a given object is empty (has no properties, inherited or not) */ -export function isEmpty(obj: Object): boolean { +function isEmpty(obj) { for (const key in obj) { return false; } @@ -242,7 +249,7 @@ export function isEmpty(obj: Object): boolean { * * Based off the equivalent function in www. */ -export function keyMirror(obj: T): {[key: $Enum]: $Enum} { +function keyMirror(obj) { const ret = {}; Object.keys(obj).forEach(key => { ret[key] = key; @@ -254,7 +261,7 @@ export function keyMirror(obj: T): {[key: $Enum]: $Enum} { * Given an array of [key, value] pairs, construct a map where the values for * each key are collected into an array of values, in order. */ -export function collect(pairs: Array<[K, V]>): Map> { +function collect(pairs) { const result = new Map(); for (const pair of pairs) { const [k, v] = pair; @@ -268,17 +275,8 @@ export function collect(pairs: Array<[K, V]>): Map> { return result; } -export class MultiMap { +class MultiMap { // Invariant: no empty sets. They should be removed instead. - _map: Map>; - - // TODO may be worth defining a getter but no setter, to mimic Map. But please just behave and - // don't mutate this from outside this class. - // - // Invariant: equal to the sum of the sizes of all the sets contained in this._map - /* The total number of key-value bindings contained */ - size: number; - constructor() { this._map = new Map(); this.size = 0; @@ -288,7 +286,14 @@ export class MultiMap { * Returns the set of values associated with the given key. Do not mutate the given set. Copy it * if you need to store it past the next operation on this MultiMap. */ - get(key: K): Set { + + + // TODO may be worth defining a getter but no setter, to mimic Map. But please just behave and + // don't mutate this from outside this class. + // + // Invariant: equal to the sum of the sizes of all the sets contained in this._map + /* The total number of key-value bindings contained */ + get(key) { const set = this._map.get(key); if (set == null) { return new Set(); @@ -300,7 +305,7 @@ export class MultiMap { * Mimics the Map.prototype.set interface. Deliberately did not choose "set" as the name since the * implication is that it removes the previous binding. */ - add(key: K, value: V): MultiMap { + add(key, value) { let set = this._map.get(key); if (set == null) { set = new Set(); @@ -316,7 +321,7 @@ export class MultiMap { /* * Mimics the Map.prototype.set interface. Replaces the previous binding with new values. */ - set(key: K, values: Iterable): void { + set(key, values) { this.deleteAll(key); const newSet = new Set(values); if (newSet.size !== 0) { @@ -328,7 +333,7 @@ export class MultiMap { /* * Deletes a single binding. Returns true iff the binding existed. */ - delete(key: K, value: V): boolean { + delete(key, value) { const set = this.get(key); const didRemove = set.delete(value); if (set.size === 0) { @@ -343,59 +348,55 @@ export class MultiMap { /* * Deletes all bindings associated with the given key. Returns true iff any bindings were deleted. */ - deleteAll(key: K): boolean { + deleteAll(key) { const set = this.get(key); this.size -= set.size; return this._map.delete(key); } - clear(): void { + clear() { this._map.clear(); this.size = 0; } - has(key: K, value: V): boolean { + has(key, value) { return this.get(key).has(value); } - hasAny(key: K): boolean { + hasAny(key) { return this._map.has(key); } - *values(): Iterable { + *values() { for (const set of this._map.values()) { yield* set; } } - forEach(callback: (value: V, key: K, obj: MultiMap) => void): void { - this._map.forEach((values, key) => - values.forEach(value => callback(value, key, this)), - ); + forEach(callback) { + this._map.forEach((values, key) => values.forEach(value => callback(value, key, this))); } } -export function objectValues(obj: {[key: string]: T}): Array { +exports.MultiMap = MultiMap; +function objectValues(obj) { return Object.keys(obj).map(key => obj[key]); } -export function objectEntries(obj: ?{[key: string]: T}): Array<[string, T]> { +function objectEntries(obj) { if (obj == null) { throw new TypeError(); } const entries = []; for (const key in obj) { - if ( - obj.hasOwnProperty(key) && - Object.prototype.propertyIsEnumerable.call(obj, key) - ) { + if (obj.hasOwnProperty(key) && Object.prototype.propertyIsEnumerable.call(obj, key)) { entries.push([key, obj[key]]); } } return entries; } -export function objectFromMap(map: Map): {[key: string]: T} { +function objectFromMap(map) { const obj = {}; map.forEach((v, k) => { obj[k] = v; @@ -403,9 +404,7 @@ export function objectFromMap(map: Map): {[key: string]: T} { return obj; } -export function* concatIterators( - ...iterators: Array> -): Iterator { +function* concatIterators(...iterators) { for (const iterator of iterators) { for (const element of iterator) { yield element; @@ -413,10 +412,7 @@ export function* concatIterators( } } -export function someOfIterable( - iterable: Iterable, - predicate: (element: T) => boolean, -): boolean { +function someOfIterable(iterable, predicate) { for (const element of iterable) { if (predicate(element)) { return true; @@ -425,10 +421,7 @@ export function someOfIterable( return false; } -export function findInIterable( - iterable: Iterable, - predicate: (element: T) => boolean, -): ?T { +function findInIterable(iterable, predicate) { for (const element of iterable) { if (predicate(element)) { return element; @@ -437,10 +430,7 @@ export function findInIterable( return null; } -export function* filterIterable( - iterable: Iterable, - predicate: (element: T) => boolean, -): Iterable { +function* filterIterable(iterable, predicate) { for (const element of iterable) { if (predicate(element)) { yield element; @@ -448,20 +438,17 @@ export function* filterIterable( } } -export function* mapIterable( - iterable: Iterable, - projectorFn: (element: T) => M, -): Iterable { +function* mapIterable(iterable, projectorFn) { for (const element of iterable) { yield projectorFn(element); } } -export function firstOfIterable(iterable: Iterable): ?T { +function firstOfIterable(iterable) { return findInIterable(iterable, () => true); } -export function iterableIsEmpty(iterable: Iterable): boolean { +function iterableIsEmpty(iterable) { // eslint-disable-next-line no-unused-vars for (const element of iterable) { return false; @@ -469,13 +456,11 @@ export function iterableIsEmpty(iterable: Iterable): boolean { return true; } -export function iterableContains(iterable: Iterable, value: T): boolean { - return !iterableIsEmpty( - filterIterable(iterable, element => element === value), - ); +function iterableContains(iterable, value) { + return !iterableIsEmpty(filterIterable(iterable, element => element === value)); } -export function count(iterable: Iterable): number { +function count(iterable) { let size = 0; // eslint-disable-next-line no-unused-vars for (const element of iterable) { @@ -484,6 +469,6 @@ export function count(iterable: Iterable): number { return size; } -export function isIterable(obj: any): boolean { +function isIterable(obj) { return typeof obj[Symbol.iterator] === 'function'; -} +} \ No newline at end of file diff --git a/modules/nuclide-commons/debounce.js b/modules/nuclide-commons/debounce.js index 02314171..f3bda9f2 100644 --- a/modules/nuclide-commons/debounce.js +++ b/modules/nuclide-commons/debounce.js @@ -1,38 +1,18 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import invariant from 'assert'; - -export default function debounce< - T, - TArgs: Array, - TReturn, - TFunc: (...TArgs) => TReturn, // eslint-disable-line space-before-function-paren ->( - func: TFunc, - wait: number, - immediate?: boolean = false, -): { - (...TArgs): TReturn | void, - dispose(): void, -} { +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = debounce; +function debounce(func, wait, immediate = false) { // Taken from: https://github.com/jashkenas/underscore/blob/b10b2e6d72/underscore.js#L815. - let timeout: ?number; - let args: ?TArgs; - let context: any; + let timeout; + let args; + let context; let timestamp = 0; - let result: TReturn | void; + let result; - const later = function() { + const later = function () { const last = Date.now() - timestamp; if (last < wait && last >= 0) { @@ -40,7 +20,10 @@ export default function debounce< } else { timeout = null; if (!immediate) { - invariant(args != null); + if (!(args != null)) { + throw new Error('Invariant violation: "args != null"'); + } + result = func.apply(context, args); if (!timeout) { context = args = null; @@ -49,7 +32,7 @@ export default function debounce< } }; - const debounced = function(...args_: TArgs): TReturn | void { + const debounced = function (...args_) { context = this; args = args_; timestamp = Date.now(); @@ -75,4 +58,14 @@ export default function debounce< }; return debounced; -} +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/nuclide-commons/event.js b/modules/nuclide-commons/event.js index 5d9c3a2c..dfefc7e7 100644 --- a/modules/nuclide-commons/event.js +++ b/modules/nuclide-commons/event.js @@ -1,3 +1,24 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.attachEvent = attachEvent; +exports.observableFromSubscribeFunction = observableFromSubscribeFunction; + +var _eventKit; + +function _load_eventKit() { + return _eventKit = require('event-kit'); +} + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +/** + * Add an event listener an return a disposable for removing it. Note that this function assumes + * node EventEmitter semantics: namely, that adding the same combination of eventName and callback + * adds a second listener. + */ /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,39 +27,22 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import {Disposable} from 'event-kit'; -import {Observable} from 'rxjs'; - -/** - * Add an event listener an return a disposable for removing it. Note that this function assumes - * node EventEmitter semantics: namely, that adding the same combination of eventName and callback - * adds a second listener. - */ -export function attachEvent( - emitter: events$EventEmitter, - eventName: string, - callback: Function, -): Disposable { +function attachEvent(emitter, eventName, callback) { emitter.addListener(eventName, callback); - return new Disposable(() => { + return new (_eventKit || _load_eventKit()).Disposable(() => { emitter.removeListener(eventName, callback); }); } -type SubscribeCallback = (item: T) => any; -type SubscribeFunction = (callback: SubscribeCallback) => IDisposable; - -export function observableFromSubscribeFunction( - fn: SubscribeFunction, -): Observable { - return Observable.create(observer => { +function observableFromSubscribeFunction(fn) { + return _rxjsBundlesRxMinJs.Observable.create(observer => { const disposable = fn(observer.next.bind(observer)); return () => { disposable.dispose(); }; }); -} +} \ No newline at end of file diff --git a/modules/nuclide-commons/fsPromise.js b/modules/nuclide-commons/fsPromise.js index 036c2540..313ca550 100644 --- a/modules/nuclide-commons/fsPromise.js +++ b/modules/nuclide-commons/fsPromise.js @@ -1,24 +1,205 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + /** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * Searches upward through the filesystem from pathToDirectory to find a file with + * fileName. + * @param fileName The name of the file to find. + * @param pathToDirectory Where to begin the search. Must be a path to a directory, + * not a file. + * @return directory that contains the nearest file or null. + */ +let findNearestFile = (() => { + var _ref = (0, _asyncToGenerator.default)(function* (fileName, pathToDirectory) { + // TODO(5586355): If this becomes a bottleneck, we should consider memoizing + // this function. The downside would be that if someone added a closer file + // with fileName to pathToFile (or deleted the one that was cached), then we + // would have a bug. This would probably be pretty rare, though. + let currentPath = (_nuclideUri || _load_nuclideUri()).default.resolve(pathToDirectory); + for (;;) { + const fileToFind = (_nuclideUri || _load_nuclideUri()).default.join(currentPath, fileName); + // eslint-disable-next-line no-await-in-loop + const hasFile = yield exists(fileToFind); + if (hasFile) { + return currentPath; + } + if ((_nuclideUri || _load_nuclideUri()).default.isRoot(currentPath)) { + return null; + } + currentPath = (_nuclideUri || _load_nuclideUri()).default.dirname(currentPath); + } + }); + + return function findNearestFile(_x, _x2) { + return _ref.apply(this, arguments); + }; +})(); + +/** + * Searches upward through the filesystem from pathToDirectory to find the furthest + * file with fileName. + * @param fileName The name of the file to find. + * @param pathToDirectory Where to begin the search. Must be a path to a directory, + * not a file. + * @param stopOnMissing Stop searching when we reach a directory without fileName. + * @return directory that contains the furthest file or null. + */ + + +let findFurthestFile = (() => { + var _ref2 = (0, _asyncToGenerator.default)(function* (fileName, pathToDirectory, stopOnMissing = false) { + let currentPath = (_nuclideUri || _load_nuclideUri()).default.resolve(pathToDirectory); + let result = null; + for (;;) { + const fileToFind = (_nuclideUri || _load_nuclideUri()).default.join(currentPath, fileName); + // eslint-disable-next-line no-await-in-loop + const hasFile = yield exists(fileToFind); + if (!hasFile && stopOnMissing || (_nuclideUri || _load_nuclideUri()).default.isRoot(currentPath)) { + return result; + } else if (hasFile) { + result = currentPath; + } + currentPath = (_nuclideUri || _load_nuclideUri()).default.dirname(currentPath); + } + }); + + return function findFurthestFile(_x3, _x4) { + return _ref2.apply(this, arguments); + }; +})(); + +/** + * Runs the equivalent of `mkdir -p` with the given path. * - * @flow - * @format + * Like most implementations of mkdirp, if it fails, it is possible that + * directories were created for some prefix of the given path. + * @return true if the path was created; false if it already existed. */ +let mkdirp = (() => { + var _ref3 = (0, _asyncToGenerator.default)(function* (filePath) { + const isExistingDirectory = yield exists(filePath); + if (isExistingDirectory) { + return false; + } else { + return new Promise(function (resolve, reject) { + (0, (_mkdirp || _load_mkdirp()).default)(filePath, function (err) { + if (err) { + reject(err); + } else { + resolve(true); + } + }); + }); + } + }); + + return function mkdirp(_x5) { + return _ref3.apply(this, arguments); + }; +})(); + +/** + * Removes directories even if they are non-empty. Does not fail if the directory doesn't exist. + */ + + +/** @return true only if we are sure directoryPath is on NFS. */ +let isNfs = (() => { + var _ref4 = (0, _asyncToGenerator.default)(function* (entityPath) { + if (process.platform === 'linux' || process.platform === 'darwin') { + try { + const stdout = yield (0, (_process || _load_process()).runCommand)('stat', ['-f', '-L', '-c', '%T', entityPath]).toPromise(); + return stdout.trim() === 'nfs'; + } catch (err) { + return false; + } + } else { + // TODO Handle other platforms (windows?): t9917576. + return false; + } + }); + + return function isNfs(_x6) { + return _ref4.apply(this, arguments); + }; +})(); + +let isNonNfsDirectory = (() => { + var _ref5 = (0, _asyncToGenerator.default)(function* (directoryPath) { + try { + const stats = yield stat(directoryPath); + if (stats.isDirectory()) { + return !(yield isNfs(directoryPath)); + } else { + return false; + } + } catch (e) { + // If the directory cannot be probed for whatever reason, just + // indicate that this is not a valid candidate directory. + // Typically this is ENOENT for missing directory. + return false; + } + }); + + return function isNonNfsDirectory(_x7) { + return _ref5.apply(this, arguments); + }; +})(); + +/** + * Promisified wrappers around fs-plus functions. + */ + +var _fs = _interopRequireDefault(require('fs')); + +var _fsPlus; + +function _load_fsPlus() { + return _fsPlus = _interopRequireDefault(require('fs-plus')); +} + +var _glob; + +function _load_glob() { + return _glob = _interopRequireDefault(require('glob')); +} + +var _mkdirp; + +function _load_mkdirp() { + return _mkdirp = _interopRequireDefault(require('mkdirp')); +} + +var _rimraf; + +function _load_rimraf() { + return _rimraf = _interopRequireDefault(require('rimraf')); +} + +var _temp; + +function _load_temp() { + return _temp = _interopRequireDefault(require('temp')); +} + +var _nuclideUri; + +function _load_nuclideUri() { + return _nuclideUri = _interopRequireDefault(require('./nuclideUri')); +} + +var _process; -import fs from 'fs'; -import fsPlus from 'fs-plus'; -import globLib from 'glob'; -import mkdirpLib from 'mkdirp'; -import rimraf from 'rimraf'; -import temp from 'temp'; +function _load_process() { + return _process = require('./process'); +} -import nuclideUri from './nuclideUri'; -import {runCommand} from './process'; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Create a temp directory with given prefix. The caller is responsible for cleaning up the @@ -26,9 +207,21 @@ import {runCommand} from './process'; * @param prefix optinal prefix for the temp directory name. * @return path to a temporary directory. */ -function tempdir(prefix: string = ''): Promise { +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +function tempdir(prefix = '') { return new Promise((resolve, reject) => { - temp.mkdir(prefix, (err, result) => { + (_temp || _load_temp()).default.mkdir(prefix, (err, result) => { if (err == null) { resolve(result); } else { @@ -42,13 +235,13 @@ function tempdir(prefix: string = ''): Promise { * @return path to a temporary file. The caller is responsible for cleaning up * the file. */ -function tempfile(options: any): Promise { +function tempfile(options) { return new Promise((resolve, reject) => { - temp.open(options, (err, info) => { + (_temp || _load_temp()).default.open(options, (err, info) => { if (err) { reject(err); } else { - fs.close(info.fd, closeErr => { + _fs.default.close(info.fd, closeErr => { if (closeErr) { reject(closeErr); } else { @@ -60,112 +253,21 @@ function tempfile(options: any): Promise { }); } -/** - * Searches upward through the filesystem from pathToDirectory to find a file with - * fileName. - * @param fileName The name of the file to find. - * @param pathToDirectory Where to begin the search. Must be a path to a directory, - * not a file. - * @return directory that contains the nearest file or null. - */ -async function findNearestFile( - fileName: string, - pathToDirectory: string, -): Promise { - // TODO(5586355): If this becomes a bottleneck, we should consider memoizing - // this function. The downside would be that if someone added a closer file - // with fileName to pathToFile (or deleted the one that was cached), then we - // would have a bug. This would probably be pretty rare, though. - let currentPath = nuclideUri.resolve(pathToDirectory); - for (;;) { - const fileToFind = nuclideUri.join(currentPath, fileName); - // eslint-disable-next-line no-await-in-loop - const hasFile = await exists(fileToFind); - if (hasFile) { - return currentPath; - } - if (nuclideUri.isRoot(currentPath)) { - return null; - } - currentPath = nuclideUri.dirname(currentPath); - } -} - -/** - * Searches upward through the filesystem from pathToDirectory to find the furthest - * file with fileName. - * @param fileName The name of the file to find. - * @param pathToDirectory Where to begin the search. Must be a path to a directory, - * not a file. - * @param stopOnMissing Stop searching when we reach a directory without fileName. - * @return directory that contains the furthest file or null. - */ -async function findFurthestFile( - fileName: string, - pathToDirectory: string, - stopOnMissing: boolean = false, -): Promise { - let currentPath = nuclideUri.resolve(pathToDirectory); - let result = null; - for (;;) { - const fileToFind = nuclideUri.join(currentPath, fileName); - // eslint-disable-next-line no-await-in-loop - const hasFile = await exists(fileToFind); - if ((!hasFile && stopOnMissing) || nuclideUri.isRoot(currentPath)) { - return result; - } else if (hasFile) { - result = currentPath; - } - currentPath = nuclideUri.dirname(currentPath); - } -} - -function getCommonAncestorDirectory(filePaths: Array): string { - let commonDirectoryPath = nuclideUri.dirname(filePaths[0]); - while ( - filePaths.some(filePath => !filePath.startsWith(commonDirectoryPath)) - ) { - commonDirectoryPath = nuclideUri.dirname(commonDirectoryPath); +function getCommonAncestorDirectory(filePaths) { + let commonDirectoryPath = (_nuclideUri || _load_nuclideUri()).default.dirname(filePaths[0]); + while (filePaths.some(filePath => !filePath.startsWith(commonDirectoryPath))) { + commonDirectoryPath = (_nuclideUri || _load_nuclideUri()).default.dirname(commonDirectoryPath); } return commonDirectoryPath; } -function exists(filePath: string): Promise { +function exists(filePath) { return new Promise((resolve, reject) => { - fs.exists(filePath, resolve); + _fs.default.exists(filePath, resolve); }); -} - -/** - * Runs the equivalent of `mkdir -p` with the given path. - * - * Like most implementations of mkdirp, if it fails, it is possible that - * directories were created for some prefix of the given path. - * @return true if the path was created; false if it already existed. - */ -async function mkdirp(filePath: string): Promise { - const isExistingDirectory = await exists(filePath); - if (isExistingDirectory) { - return false; - } else { - return new Promise((resolve, reject) => { - mkdirpLib(filePath, err => { - if (err) { - reject(err); - } else { - resolve(true); - } - }); - }); - } -} - -/** - * Removes directories even if they are non-empty. Does not fail if the directory doesn't exist. - */ -function rimrafWrapper(filePath: string): Promise { +}function rimrafWrapper(filePath) { return new Promise((resolve, reject) => { - rimraf(filePath, (err, result) => { + (0, (_rimraf || _load_rimraf()).default)(filePath, (err, result) => { if (err == null) { resolve(result); } else { @@ -175,30 +277,9 @@ function rimrafWrapper(filePath: string): Promise { }); } -/** @return true only if we are sure directoryPath is on NFS. */ -async function isNfs(entityPath: string): Promise { - if (process.platform === 'linux' || process.platform === 'darwin') { - try { - const stdout = await runCommand('stat', [ - '-f', - '-L', - '-c', - '%T', - entityPath, - ]).toPromise(); - return stdout.trim() === 'nfs'; - } catch (err) { - return false; - } - } else { - // TODO Handle other platforms (windows?): t9917576. - return false; - } -} - -function glob(pattern: string, options?: Object): Promise> { +function glob(pattern, options) { return new Promise((resolve, reject) => { - globLib(pattern, options, (err, result) => { + (0, (_glob || _load_glob()).default)(pattern, options, (err, result) => { if (err == null) { resolve(result); } else { @@ -208,29 +289,9 @@ function glob(pattern: string, options?: Object): Promise> { }); } -async function isNonNfsDirectory(directoryPath: string): Promise { - try { - const stats = await stat(directoryPath); - if (stats.isDirectory()) { - return !await isNfs(directoryPath); - } else { - return false; - } - } catch (e) { - // If the directory cannot be probed for whatever reason, just - // indicate that this is not a valid candidate directory. - // Typically this is ENOENT for missing directory. - return false; - } -} - -/** - * Promisified wrappers around fs-plus functions. - */ - -function copy(source: string, dest: string): Promise { +function copy(source, dest) { return new Promise((resolve, reject) => { - fsPlus.copy(source, dest, (err, result) => { + (_fsPlus || _load_fsPlus()).default.copy(source, dest, (err, result) => { if (err == null) { resolve(result); } else { @@ -240,9 +301,9 @@ function copy(source: string, dest: string): Promise { }); } -function move(source: string, dest: string): Promise { +function move(source, dest) { return new Promise((resolve, reject) => { - fsPlus.move(source, dest, (err, result) => { + (_fsPlus || _load_fsPlus()).default.move(source, dest, (err, result) => { if (err == null) { resolve(result); } else { @@ -256,13 +317,9 @@ function move(source: string, dest: string): Promise { * TODO: the fs-plus `writeFile` implementation runs `mkdirp` first. * We should use `fs.writeFile` and have callsites explicitly opt-in to this behaviour. */ -function writeFile( - filename: string, - data: Buffer | string, - options?: Object | string, -): Promise { +function writeFile(filename, data, options) { return new Promise((resolve, reject) => { - fsPlus.writeFile(filename, data, options, (err, result) => { + (_fsPlus || _load_fsPlus()).default.writeFile(filename, data, options, (err, result) => { if (err == null) { resolve(result); } else { @@ -276,9 +333,9 @@ function writeFile( * Promisified wrappers around fs functions. */ -function chmod(path: string, mode: number | string): Promise { +function chmod(path, mode) { return new Promise((resolve, reject) => { - fs.chmod(path, mode, (err, result) => { + _fs.default.chmod(path, mode, (err, result) => { if (err == null) { resolve(result); } else { @@ -288,9 +345,9 @@ function chmod(path: string, mode: number | string): Promise { }); } -function chown(path: string, uid: number, gid: number): Promise { +function chown(path, uid, gid) { return new Promise((resolve, reject) => { - fs.chown(path, uid, gid, (err, result) => { + _fs.default.chown(path, uid, gid, (err, result) => { if (err == null) { resolve(result); } else { @@ -300,9 +357,9 @@ function chown(path: string, uid: number, gid: number): Promise { }); } -function lstat(path: string): Promise { +function lstat(path) { return new Promise((resolve, reject) => { - fs.lstat(path, (err, result) => { + _fs.default.lstat(path, (err, result) => { if (err == null) { resolve(result); } else { @@ -312,9 +369,9 @@ function lstat(path: string): Promise { }); } -function mkdir(path: string, mode?: number): Promise { +function mkdir(path, mode) { return new Promise((resolve, reject) => { - fs.mkdir(path, mode, (err, result) => { + _fs.default.mkdir(path, mode, (err, result) => { if (err == null) { resolve(result); } else { @@ -326,17 +383,12 @@ function mkdir(path: string, mode?: number): Promise { // `fs.readFile` returns a Buffer unless an encoding is specified. // This workaround is adapted from the Flow declarations. -type ReadFileType = ((filename: string, encoding: string) => Promise) & - (( - filename: string, - options: {encoding: string, flag?: string}, - ) => Promise) & - ((filename: string, options?: {flag?: string}) => Promise); - -const readFile: ReadFileType = (function(...args: Array) { + + +const readFile = function (...args) { return new Promise((resolve, reject) => { // $FlowIssue: spread operator doesn't preserve any-type - fs.readFile(...args, (err, result) => { + _fs.default.readFile(...args, (err, result) => { if (err == null) { resolve(result); } else { @@ -344,11 +396,11 @@ const readFile: ReadFileType = (function(...args: Array) { } }); }); -}: any); +}; -function readdir(path: string): Promise> { +function readdir(path) { return new Promise((resolve, reject) => { - fs.readdir(path, (err, result) => { + _fs.default.readdir(path, (err, result) => { if (err == null) { resolve(result); } else { @@ -358,9 +410,9 @@ function readdir(path: string): Promise> { }); } -function readlink(path: string): Promise { +function readlink(path) { return new Promise((resolve, reject) => { - fs.readlink(path, (err, result) => { + _fs.default.readlink(path, (err, result) => { if (err == null) { resolve(result); } else { @@ -370,9 +422,9 @@ function readlink(path: string): Promise { }); } -function realpath(path: string, cache?: Object): Promise { +function realpath(path, cache) { return new Promise((resolve, reject) => { - fs.realpath(path, cache, (err, result) => { + _fs.default.realpath(path, cache, (err, result) => { if (err == null) { resolve(result); } else { @@ -382,9 +434,9 @@ function realpath(path: string, cache?: Object): Promise { }); } -function rename(oldPath: string, newPath: string): Promise { +function rename(oldPath, newPath) { return new Promise((resolve, reject) => { - fs.rename(oldPath, newPath, (err, result) => { + _fs.default.rename(oldPath, newPath, (err, result) => { if (err == null) { resolve(result); } else { @@ -394,9 +446,9 @@ function rename(oldPath: string, newPath: string): Promise { }); } -function stat(path: string): Promise { +function stat(path) { return new Promise((resolve, reject) => { - fs.stat(path, (err, result) => { + _fs.default.stat(path, (err, result) => { if (err == null) { resolve(result); } else { @@ -406,9 +458,9 @@ function stat(path: string): Promise { }); } -function symlink(source: string, dest: string, type?: string): Promise { +function symlink(source, dest, type) { return new Promise((resolve, reject) => { - fs.symlink(source, dest, type, (err, result) => { + _fs.default.symlink(source, dest, type, (err, result) => { if (err == null) { resolve(result); } else { @@ -418,9 +470,9 @@ function symlink(source: string, dest: string, type?: string): Promise { }); } -function unlink(path: string): Promise { +function unlink(path) { return new Promise((resolve, reject) => { - fs.unlink(path, (err, result) => { + _fs.default.unlink(path, (err, result) => { if (err == null) { resolve(result); } else { @@ -430,7 +482,7 @@ function unlink(path: string): Promise { }); } -export default { +exports.default = { tempdir, tempfile, findNearestFile, @@ -458,5 +510,5 @@ export default { rename, stat, symlink, - unlink, -}; + unlink +}; \ No newline at end of file diff --git a/modules/nuclide-commons/groupMatchIndexes.js b/modules/nuclide-commons/groupMatchIndexes.js index ad8c0c69..b339f328 100644 --- a/modules/nuclide-commons/groupMatchIndexes.js +++ b/modules/nuclide-commons/groupMatchIndexes.js @@ -1,3 +1,9 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = groupMatchIndexes; /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,16 +12,11 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -export default function groupMatchIndexes( - str: string, - matchIndexes: Array, - matchFn: (string, number | string) => T, - unmatchedFn: (string, number | string) => T, -): Array { +function groupMatchIndexes(str, matchIndexes, matchFn, unmatchedFn) { let streakOngoing = false; let start = 0; const pathComponents = []; @@ -48,4 +49,4 @@ export default function groupMatchIndexes( pathComponents.push(unmatchedFn(str.slice(start, str.length), 'last')); } return pathComponents; -} +} \ No newline at end of file diff --git a/modules/nuclide-commons/hasCommand.js b/modules/nuclide-commons/hasCommand.js index 397dd1f6..72c9fd51 100644 --- a/modules/nuclide-commons/hasCommand.js +++ b/modules/nuclide-commons/hasCommand.js @@ -1,17 +1,28 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import commandExists from 'command-exists'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.hasCommand = hasCommand; -export function hasCommand(command: string): Promise { - return commandExists(command).then(() => true, () => false); +var _commandExists; + +function _load_commandExists() { + return _commandExists = _interopRequireDefault(require('command-exists')); } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function hasCommand(command) { + return (0, (_commandExists || _load_commandExists()).default)(command).then(() => true, () => false); +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ \ No newline at end of file diff --git a/modules/nuclide-commons/memoizeUntilChanged.js b/modules/nuclide-commons/memoizeUntilChanged.js index 338e14b9..db7ee576 100644 --- a/modules/nuclide-commons/memoizeUntilChanged.js +++ b/modules/nuclide-commons/memoizeUntilChanged.js @@ -1,3 +1,24 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = memoizeUntilChanged; + +var _collection; + +function _load_collection() { + return _collection = require('./collection'); +} + +var _Hasher; + +function _load_Hasher() { + return _Hasher = _interopRequireDefault(require('./Hasher')); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,16 +27,10 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import {arrayEqual} from './collection'; -import Hasher from './Hasher'; - -type CompareFunc = (a: Array, b: Array) => boolean; -type KeySelector = (x: T) => U; - const NOTHING = Symbol('nothing'); /** @@ -35,16 +50,12 @@ const NOTHING = Symbol('nothing'); * } * } */ -export default function memoizeUntilChanged( - func: T, - keySelector_?: KeySelector, - compareKeys: CompareFunc = arrayEqual, -): T { +function memoizeUntilChanged(func, keySelector_, compareKeys = (_collection || _load_collection()).arrayEqual) { let prevArgKeys; let prevResult = NOTHING; - const keySelector: KeySelector = keySelector_ || createKeySelector(); + const keySelector = keySelector_ || createKeySelector(); // $FlowIssue: Flow can't express that we want the args to be the same type as the input func's. - return function(...args) { + return function (...args) { const argKeys = args.map(keySelector); if (prevResult === NOTHING || !compareKeys(argKeys, prevArgKeys)) { prevArgKeys = argKeys; @@ -54,7 +65,7 @@ export default function memoizeUntilChanged( }; } -function createKeySelector(): KeySelector { - const hasher: Hasher = new Hasher(); +function createKeySelector() { + const hasher = new (_Hasher || _load_Hasher()).default(); return x => hasher.getHash(x); -} +} \ No newline at end of file diff --git a/modules/nuclide-commons/nice.js b/modules/nuclide-commons/nice.js index f281cb9e..83fa6f09 100644 --- a/modules/nuclide-commons/nice.js +++ b/modules/nuclide-commons/nice.js @@ -1,38 +1,25 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import type {LRUCache} from 'lru-cache'; -import type {ObserveProcessOptions, ProcessMessage} from './process'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.niceSafeSpawn = undefined; -import LRU from 'lru-cache'; -import {Observable} from 'rxjs'; +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); -import which from './which'; -import {spawn, observeProcess} from './process'; +let niceSafeSpawn = exports.niceSafeSpawn = (() => { + var _ref = (0, _asyncToGenerator.default)(function* (command, args, execOptions) { + const nicified = yield nicifyCommand(command, args, execOptions); + const processStream = (0, (_process || _load_process()).spawn)(...nicified).publish(); + const processPromise = processStream.take(1).toPromise(); + processStream.connect(); + return processPromise; + }); -const NICE_COMMAND = 'nice'; -const IONICE_COMMAND = 'ionice'; - -export async function niceSafeSpawn( - command: string, - args: Array, - execOptions?: Object, -): Promise { - const nicified = await nicifyCommand(command, args, execOptions); - const processStream = spawn(...nicified).publish(); - const processPromise = processStream.take(1).toPromise(); - processStream.connect(); - return processPromise; -} + return function niceSafeSpawn(_x, _x2, _x3) { + return _ref.apply(this, arguments); + }; +})(); /** * Takes the arguments that you would normally pass to `spawn()` and returns an array of new @@ -46,62 +33,104 @@ export async function niceSafeSpawn( * * See also `scriptifyCommand()` which does a similar thing but for `script`. */ -async function nicifyCommand( - command: string, - args?: Array, - options: T, -): Promise<[string, Array, T]> { - const fullArgs = [command, ...(args || [])]; - if (await hasNiceCommand()) { - fullArgs.unshift(NICE_COMMAND); - } - if (await hasIoniceCommand()) { - // Leave the process in the Best Effort class (default), but set it to the lowest priority for - // that class. Priorities range from 0-7 with 4 as the default and lower numbers representing - // higher priorities. - // - // See `man ionice` or http://linux.die.net/man/1/ionice - // - // It's not specified by POSIX like `nice` is but since it is included in util-linux which is - // relatively core - // (https://git.kernel.org/cgit/utils/util-linux/util-linux.git/tree/schedutils/ionice.c), I - // think we can assume that it uses this interface if it exists. - fullArgs.unshift(IONICE_COMMAND, '-n', '7'); - } - return [fullArgs[0], fullArgs.slice(1), options]; + + +let nicifyCommand = (() => { + var _ref2 = (0, _asyncToGenerator.default)(function* (command, args, options) { + const fullArgs = [command, ...(args || [])]; + if (yield hasNiceCommand()) { + fullArgs.unshift(NICE_COMMAND); + } + if (yield hasIoniceCommand()) { + // Leave the process in the Best Effort class (default), but set it to the lowest priority for + // that class. Priorities range from 0-7 with 4 as the default and lower numbers representing + // higher priorities. + // + // See `man ionice` or http://linux.die.net/man/1/ionice + // + // It's not specified by POSIX like `nice` is but since it is included in util-linux which is + // relatively core + // (https://git.kernel.org/cgit/utils/util-linux/util-linux.git/tree/schedutils/ionice.c), I + // think we can assume that it uses this interface if it exists. + fullArgs.unshift(IONICE_COMMAND, '-n', '7'); + } + return [fullArgs[0], fullArgs.slice(1), options]; + }); + + return function nicifyCommand(_x4, _x5, _x6) { + return _ref2.apply(this, arguments); + }; +})(); + +let hasCommand = (() => { + var _ref3 = (0, _asyncToGenerator.default)(function* (command) { + let result = commandAvailabilityCache.get(command); + if (result == null) { + result = (yield (0, (_which || _load_which()).default)(command)) != null; + commandAvailabilityCache.set(command, result); + } + return result; + }); + + return function hasCommand(_x7) { + return _ref3.apply(this, arguments); + }; +})(); + +exports.niceObserveProcess = niceObserveProcess; + +var _lruCache; + +function _load_lruCache() { + return _lruCache = _interopRequireDefault(require('lru-cache')); } -const commandAvailabilityCache: LRUCache = LRU({ +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _which; + +function _load_which() { + return _which = _interopRequireDefault(require('./which')); +} + +var _process; + +function _load_process() { + return _process = require('./process'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const NICE_COMMAND = 'nice'; +const IONICE_COMMAND = 'ionice'; + +const commandAvailabilityCache = (0, (_lruCache || _load_lruCache()).default)({ max: 10, // Realistically this will not change very often so we can cache for long periods of time. We // probably could just check at startup and get away with it, but maybe someone will install // `ionice` and it would be nice to pick that up. - maxAge: 1000 * 60 * 5, // 5 minutes -}); + maxAge: 1000 * 60 * 5 }); -function hasNiceCommand(): Promise { +function hasNiceCommand() { return hasCommand(NICE_COMMAND); } -function hasIoniceCommand(): Promise { +function hasIoniceCommand() { return hasCommand(IONICE_COMMAND); } -async function hasCommand(command: string): Promise { - let result: ?boolean = commandAvailabilityCache.get(command); - if (result == null) { - result = (await which(command)) != null; - commandAvailabilityCache.set(command, result); - } - return result; -} - -export function niceObserveProcess( - command: string, - args?: Array, - options?: ObserveProcessOptions, -): Observable { - return Observable.defer(() => - nicifyCommand(command, args, options), - ).switchMap(spawnArgs => observeProcess(...spawnArgs)); -} +function niceObserveProcess(command, args, options) { + return _rxjsBundlesRxMinJs.Observable.defer(() => nicifyCommand(command, args, options)).switchMap(spawnArgs => (0, (_process || _load_process()).observeProcess)(...spawnArgs)); +} \ No newline at end of file diff --git a/modules/nuclide-commons/nuclideUri.js b/modules/nuclide-commons/nuclideUri.js index 35dc4f65..193c13ce 100644 --- a/modules/nuclide-commons/nuclideUri.js +++ b/modules/nuclide-commons/nuclideUri.js @@ -1,3 +1,28 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.__TEST__ = undefined; + +var _path = _interopRequireDefault(require('path')); + +var _url = _interopRequireDefault(require('url')); + +var _os = _interopRequireDefault(require('os')); + +var _string; + +function _load_string() { + return _string = require('./string'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// eslint-disable-next-line rulesdir/prefer-nuclide-uri +const REMOTE_PATH_URI_PREFIX = 'nuclide://'; +// TODO(ljw): following regex is incorrect. A URI scheme must start with +// [A-Za-z] not [0-9_-]. Also, not all schemes require // after them. /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,7 +31,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ @@ -15,68 +40,37 @@ // // This package creates, queries and decomposes NuclideUris. -export type NuclideUri = string; - -type ParsedUrl = { - hostname: ?string, - path: string, -}; - -type ParsedRemoteUrl = { - hostname: string, - path: string, -}; - -type ParsedPath = { - root: string, - dir: string, - base: string, - ext: string, - name: string, -}; - -import invariant from 'assert'; -// eslint-disable-next-line rulesdir/prefer-nuclide-uri -import pathModule from 'path'; - -import url from 'url'; -import os from 'os'; -import {maybeToString} from './string'; - -const REMOTE_PATH_URI_PREFIX = 'nuclide://'; -// TODO(ljw): following regex is incorrect. A URI scheme must start with -// [A-Za-z] not [0-9_-]. Also, not all schemes require // after them. const URI_PREFIX_REGEX = /^[A-Za-z0-9_-]+:\/\/.*/; -function isRemote(uri: NuclideUri): boolean { +function isRemote(uri) { return uri.startsWith(REMOTE_PATH_URI_PREFIX); } // When restoring Atom state on load, Atom mangles our remote URIs by // removing one of the '/'s. These TextBuffers/TextEditors live for a short time // and are destroyed during Nuclide startup. -function isBrokenDeserializedUri(uri: ?NuclideUri): boolean { +function isBrokenDeserializedUri(uri) { return uri != null && uri.match(/nuclide:[\\/][^/]/) != null; } // Atom often puts its URIs in places where we'd expect to see Nuclide URIs (or plain paths) -function isAtomUri(uri: NuclideUri): boolean { +function isAtomUri(uri) { return uri.startsWith('atom://'); } -function isUri(uri: string): boolean { +function isUri(uri) { return URI_PREFIX_REGEX.test(uri); } -function isLocal(uri: NuclideUri): boolean { +function isLocal(uri) { return !isRemote(uri) && !isUri(uri) && !isAtomUri(uri); } -function createRemoteUri(hostname: string, remotePath: string): string { - invariant( - remotePath != null && remotePath !== '', - 'NuclideUri must include a path.', - ); +function createRemoteUri(hostname, remotePath) { + if (!(remotePath != null && remotePath !== '')) { + throw new Error('NuclideUri must include a path.'); + } + return `nuclide://${hostname}${remotePath}`; } @@ -89,64 +83,63 @@ function createRemoteUri(hostname: string, remotePath: string): string { * Everything that does not contain a '://' is assumed to be a local path. Both POSIX and Windows * paths are legal */ -function parse(uri: NuclideUri): ParsedUrl { +function parse(uri) { if (uri.startsWith(REMOTE_PATH_URI_PREFIX)) { const hostAndPath = uri.substr(REMOTE_PATH_URI_PREFIX.length); const hostSep = hostAndPath.indexOf('/'); - invariant( - hostSep !== -1, - `Remote URIs must contain a hostname and a path. Failed to parse ${uri}`, - ); + if (!(hostSep !== -1)) { + throw new Error(`Remote URIs must contain a hostname and a path. Failed to parse ${uri}`); + } const hostname = hostAndPath.substr(0, hostSep); - invariant( - hostname !== '', - `Remote URIs must contain a hostname. Failed to parse ${uri}`, - ); + + if (!(hostname !== '')) { + throw new Error(`Remote URIs must contain a hostname. Failed to parse ${uri}`); + } const path = hostAndPath.substr(hostSep); - return {hostname, path}; + return { hostname, path }; } - invariant( - uri.indexOf('://') === -1, - 'Nuclide URI must be either local file names or URLs starting with nuclide://', - ); + if (!(uri.indexOf('://') === -1)) { + throw new Error('Nuclide URI must be either local file names or URLs starting with nuclide://'); + } - return {hostname: null, path: uri}; + return { hostname: null, path: uri }; } -function parseRemoteUri(remoteUri: NuclideUri): ParsedRemoteUrl { +function parseRemoteUri(remoteUri) { if (!isRemote(remoteUri)) { throw new Error('Expected remote uri. Got ' + remoteUri); } const parsedUri = parse(remoteUri); - invariant( - // flowlint-next-line sketchy-null-string:off - parsedUri.hostname, - `Remote Nuclide URIs must contain hostnames, '${maybeToString( - parsedUri.hostname, - )}' found while parsing '${remoteUri}'`, - ); + + if (! + // flowlint-next-line sketchy-null-string:off + parsedUri.hostname) { + throw new Error(`Remote Nuclide URIs must contain hostnames, '${(0, (_string || _load_string()).maybeToString)(parsedUri.hostname)}' found while parsing '${remoteUri}'`); + } // Explicitly copying object properties appeases Flow's "maybe" type handling. Using the `...` // operator causes null/undefined errors, and `Object.assign` bypasses type checking. + + return { hostname: parsedUri.hostname, - path: parsedUri.path, + path: parsedUri.path }; } -function getPath(uri: NuclideUri): string { +function getPath(uri) { return parse(uri).path; } -function getHostname(remoteUri: NuclideUri): string { +function getHostname(remoteUri) { return parseRemoteUri(remoteUri).hostname; } -function getHostnameOpt(remoteUri: ?NuclideUri): ?string { +function getHostnameOpt(remoteUri) { if (remoteUri == null || !isRemote(remoteUri)) { return null; } @@ -154,53 +147,45 @@ function getHostnameOpt(remoteUri: ?NuclideUri): ?string { return getHostname(remoteUri); } -function join(uri: NuclideUri, ...relativePath: Array): NuclideUri { +function join(uri, ...relativePath) { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); if (isRemote(uri)) { - const {hostname, path} = parseRemoteUri(uri); + const { hostname, path } = parseRemoteUri(uri); relativePath.splice(0, 0, path); - return createRemoteUri( - hostname, - uriPathModule.join.apply(null, relativePath), - ); + return createRemoteUri(hostname, uriPathModule.join.apply(null, relativePath)); } else { relativePath.splice(0, 0, uri); return uriPathModule.join.apply(null, relativePath); } } -function normalize(uri: NuclideUri): NuclideUri { +function normalize(uri) { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); if (isRemote(uri)) { - const {hostname, path} = parseRemoteUri(uri); + const { hostname, path } = parseRemoteUri(uri); return createRemoteUri(hostname, uriPathModule.normalize(path)); } else { return uriPathModule.normalize(uri); } } -function normalizeDir(uri: NuclideUri): NuclideUri { +function normalizeDir(uri) { return ensureTrailingSeparator(normalize(uri)); } -function getParent(uri: NuclideUri): NuclideUri { +function getParent(uri) { // TODO: Is this different than dirname? return normalize(join(uri, '..')); } -function relative(uri: NuclideUri, other: NuclideUri): string { +function relative(uri, other) { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); const remote = isRemote(uri); - if ( - remote !== isRemote(other) || - (remote && getHostname(uri) !== getHostname(other)) - ) { - throw new Error( - `Cannot relative urls on different hosts: ${uri} and ${other}`, - ); + if (remote !== isRemote(other) || remote && getHostname(uri) !== getHostname(other)) { + throw new Error(`Cannot relative urls on different hosts: ${uri} and ${other}`); } if (remote) { return uriPathModule.relative(getPath(uri), getPath(other)); @@ -209,30 +194,30 @@ function relative(uri: NuclideUri, other: NuclideUri): string { } } -function basename(uri: NuclideUri, ext: string = ''): string { +function basename(uri, ext = '') { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); return uriPathModule.basename(getPath(uri), ext); } -function dirname(uri: NuclideUri): NuclideUri { +function dirname(uri) { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); if (isRemote(uri)) { - const {hostname, path} = parseRemoteUri(uri); + const { hostname, path } = parseRemoteUri(uri); return createRemoteUri(hostname, uriPathModule.dirname(path)); } else { return uriPathModule.dirname(uri); } } -function extname(uri: NuclideUri): string { +function extname(uri) { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); return uriPathModule.extname(getPath(uri)); } -function stripExtension(uri: NuclideUri): NuclideUri { +function stripExtension(uri) { _testForAtomUri(uri); const ext = extname(uri); if (ext.length === 0) { @@ -242,11 +227,11 @@ function stripExtension(uri: NuclideUri): NuclideUri { return uri.slice(0, -1 * ext.length); } -function _isWindowsPath(path: string): boolean { - return _pathModuleFor(path) === pathModule.win32; +function _isWindowsPath(path) { + return _pathModuleFor(path) === _path.default.win32; } -function _getWindowsPathFromWindowsFileUri(uri: string): ?string { +function _getWindowsPathFromWindowsFileUri(uri) { const prefix = 'file://'; if (!uri.startsWith(prefix)) { return null; @@ -262,7 +247,7 @@ function _getWindowsPathFromWindowsFileUri(uri: string): ?string { * * Returns null if not a valid file: URI. */ -function uriToNuclideUri(uri: string): ?string { +function uriToNuclideUri(uri) { // TODO(ljw): the following check is incorrect. It's designed to support // two-slash file URLs of the form "file://c:\path". But those are invalid // file URLs, and indeed it fails to %-escape "file://c:\My%20Documents". @@ -276,7 +261,7 @@ function uriToNuclideUri(uri: string): ?string { return windowsPathFromUri; } - const urlParts = url.parse(_escapeSpecialCharacters(uri), false); + const urlParts = _url.default.parse(_escapeSpecialCharacters(uri), false); // flowlint-next-line sketchy-null-string:off if (urlParts.protocol === 'file:' && urlParts.path) { // only handle real files for now. @@ -291,7 +276,7 @@ function uriToNuclideUri(uri: string): ?string { /** * Converts local paths to file: URI's. Leaves remote URI's alone. */ -function nuclideUriToUri(uri: NuclideUri): string { +function nuclideUriToUri(uri) { _testForAtomUri(uri); if (isRemote(uri)) { return uri; @@ -303,7 +288,7 @@ function nuclideUriToUri(uri: NuclideUri): string { /** * Returns true if child is equal to, or is a proper child of parent. */ -function contains(parent: NuclideUri, child: NuclideUri): boolean { +function contains(parent, child) { _testForAtomUri(parent); _testForAtomUri(child); @@ -349,7 +334,7 @@ function contains(parent: NuclideUri, child: NuclideUri): boolean { * Filter an array of paths to contain only the collapsed root paths, e.g. * [a/b/c, a/, c/d/, c/d/e] collapses to [a/, c/d/] */ -function collapse(paths: Array): Array { +function collapse(paths) { return paths.filter(p => !paths.some(fp => contains(fp, p) && fp !== p)); } @@ -357,10 +342,10 @@ const hostFormatters = []; // A formatter which may shorten hostnames. // Returns null if the formatter won't shorten the hostname. -export type HostnameFormatter = (uri: NuclideUri) => ?string; + // Registers a host formatter for nuclideUriToDisplayString -function registerHostnameFormatter(formatter: HostnameFormatter): IDisposable { +function registerHostnameFormatter(formatter) { hostFormatters.push(formatter); return { dispose: () => { @@ -368,7 +353,7 @@ function registerHostnameFormatter(formatter: HostnameFormatter): IDisposable { if (index >= 0) { hostFormatters.splice(index, 1); } - }, + } }; } @@ -376,7 +361,7 @@ function registerHostnameFormatter(formatter: HostnameFormatter): IDisposable { * NuclideUris should never be shown to humans. * This function returns a human usable string. */ -function nuclideUriToDisplayString(uri: NuclideUri): string { +function nuclideUriToDisplayString(uri) { _testForAtomUri(uri); if (isRemote(uri)) { let hostname = getHostname(uri); @@ -394,7 +379,7 @@ function nuclideUriToDisplayString(uri: NuclideUri): string { } } -function ensureTrailingSeparator(uri: NuclideUri): NuclideUri { +function ensureTrailingSeparator(uri) { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); if (uri.endsWith(uriPathModule.sep)) { @@ -404,7 +389,7 @@ function ensureTrailingSeparator(uri: NuclideUri): NuclideUri { return uri + uriPathModule.sep; } -function trimTrailingSeparator(uri: NuclideUri): NuclideUri { +function trimTrailingSeparator(uri) { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); let stripped = uri; @@ -416,13 +401,13 @@ function trimTrailingSeparator(uri: NuclideUri): NuclideUri { return stripped; } -function endsWithSeparator(uri: NuclideUri): boolean { +function endsWithSeparator(uri) { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); return uri.endsWith(uriPathModule.sep); } -function isAbsolute(uri: NuclideUri): boolean { +function isAbsolute(uri) { _testForAtomUri(uri); if (isRemote(uri)) { return true; @@ -432,11 +417,11 @@ function isAbsolute(uri: NuclideUri): boolean { } } -function resolve(uri: NuclideUri, ...paths: Array): NuclideUri { +function resolve(uri, ...paths) { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); if (isRemote(uri)) { - const {hostname, path} = parseRemoteUri(uri); + const { hostname, path } = parseRemoteUri(uri); paths.splice(0, 0, path); return createRemoteUri(hostname, uriPathModule.resolve.apply(null, paths)); } else { @@ -445,7 +430,7 @@ function resolve(uri: NuclideUri, ...paths: Array): NuclideUri { } } -function expandHomeDir(uri: NuclideUri): NuclideUri { +function expandHomeDir(uri) { _testForAtomUri(uri); // Do not expand non home relative uris @@ -456,11 +441,14 @@ function expandHomeDir(uri: NuclideUri): NuclideUri { // "home" on Windows is %UserProfile%. Note that Windows environment variables // are NOT case sensitive, but process.env is a magic object that wraps GetEnvironmentVariableW // on Windows, so asking for any case is expected to work. - const {HOME, UserProfile} = process.env; + const { HOME, UserProfile } = process.env; - const isWindows = !isRemote(uri) && os.platform() === 'win32'; + const isWindows = !isRemote(uri) && _os.default.platform() === 'win32'; const homePath = isWindows ? UserProfile : HOME; - invariant(homePath != null); + + if (!(homePath != null)) { + throw new Error('Invariant violation: "homePath != null"'); + } if (uri === '~') { return homePath; @@ -471,7 +459,7 @@ function expandHomeDir(uri: NuclideUri): NuclideUri { return uri; } - return pathModule.resolve(homePath, uri.replace('~', '.')); + return _path.default.resolve(homePath, uri.replace('~', '.')); } /** @@ -480,11 +468,11 @@ function expandHomeDir(uri: NuclideUri): NuclideUri { * * Since remote URI might contain the delimiter, only local paths are allowed. */ -function splitPathList(paths: string): Array { - invariant( - paths.indexOf(REMOTE_PATH_URI_PREFIX) < 0, - 'Splitting remote URIs is not supported', - ); +function splitPathList(paths) { + if (!(paths.indexOf(REMOTE_PATH_URI_PREFIX) < 0)) { + throw new Error('Splitting remote URIs is not supported'); + } + const uriPathModule = _pathModuleFor(paths); return paths.split(uriPathModule.delimiter); @@ -496,15 +484,14 @@ function splitPathList(paths: string): Array { * * Since remote URI might contain the delimiter, only local paths are allowed. */ -function joinPathList(paths: Array): string { +function joinPathList(paths) { if (paths.length === 0) { return ''; } - invariant( - paths.every(path => !isRemote(path)), - 'Joining of remote URIs is not supported', - ); + if (!paths.every(path => !isRemote(path))) { + throw new Error('Joining of remote URIs is not supported'); + } const uriPathModule = _pathModuleFor(paths[0]); return paths.join(uriPathModule.delimiter); @@ -514,15 +501,17 @@ function joinPathList(paths: Array): string { * This function prepends the given relative path with a "current-folder" prefix * which is `./` on *nix and .\ on Windows */ -function ensureLocalPrefix(uri: NuclideUri): NuclideUri { +function ensureLocalPrefix(uri) { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); - invariant(!isRemote(uri), 'Local prefix can not be added to a remote path'); - invariant( - !isAbsolute(uri), - 'Local prefix can not be added to an absolute path', - ); + if (!!isRemote(uri)) { + throw new Error('Local prefix can not be added to a remote path'); + } + + if (!!isAbsolute(uri)) { + throw new Error('Local prefix can not be added to an absolute path'); + } const localPrefix = `.${uriPathModule.sep}`; if (uri.startsWith(localPrefix)) { @@ -532,22 +521,22 @@ function ensureLocalPrefix(uri: NuclideUri): NuclideUri { return localPrefix + uri; } -function isRoot(uri: NuclideUri): boolean { +function isRoot(uri) { _testForAtomUri(uri); return dirname(uri) === uri; } -function parsePath(uri: NuclideUri): ParsedPath { +function parsePath(uri) { _testForAtomUri(uri); const uriPathModule = _pathModuleFor(uri); return uriPathModule.parse(getPath(uri)); } -function pathSeparatorFor(uri: NuclideUri): string { +function pathSeparatorFor(uri) { return _pathModuleFor(uri).sep; } -function split(uri: NuclideUri): Array { +function split(uri) { const parts = []; let current = uri; let parent = dirname(current); @@ -566,24 +555,21 @@ function split(uri: NuclideUri): Array { return parts; } -function _pathModuleFor(uri: NuclideUri): typeof pathModule { - if (uri.startsWith(pathModule.posix.sep)) { - return pathModule.posix; +function _pathModuleFor(uri) { + if (uri.startsWith(_path.default.posix.sep)) { + return _path.default.posix; } if (uri.indexOf('://') > -1) { - return pathModule.posix; + return _path.default.posix; } - if (uri[1] === ':' && uri[2] === pathModule.win32.sep) { - return pathModule.win32; + if (uri[1] === ':' && uri[2] === _path.default.win32.sep) { + return _path.default.win32; } - if ( - uri.split(pathModule.win32.sep).length > - uri.split(pathModule.posix.sep).length - ) { - return pathModule.win32; + if (uri.split(_path.default.win32.sep).length > uri.split(_path.default.posix.sep).length) { + return _path.default.win32; } else { - return pathModule.posix; + return _path.default.posix; } } @@ -592,11 +578,11 @@ function _pathModuleFor(uri: NuclideUri): typeof pathModule { * paths. They, however, are being automatically "corrected" by node's `url.parse()` method if not * escaped properly. */ -function _escapeSpecialCharacters(uri: NuclideUri): NuclideUri { +function _escapeSpecialCharacters(uri) { return uri.replace(/%/g, '%25').replace(/\\/g, '%5C'); } -function _testForAtomUri(uri: ?NuclideUri): void { +function _testForAtomUri(uri) { if (uri != null && isAtomUri(uri)) { throw new Error(`Path operation invoked on Atom URI ${uri}`); } @@ -606,24 +592,34 @@ const NUCLIDE_URI_TYPE_NAME = 'NuclideUri'; // If mustBeRemote is present then remote-ness must match, otherwise remote-ness // is ignored. -function validate(uri: NuclideUri, mustBeRemote?: boolean): void { +function validate(uri, mustBeRemote) { // Be a little extra paranoid to catch places where the type system may be weak. - invariant(uri != null, 'Unexpected null NuclideUri'); - invariant( - typeof uri === 'string', - `Unexpected NuclideUri type: ${String(uri)}`, - ); + if (!(uri != null)) { + throw new Error('Unexpected null NuclideUri'); + } + + if (!(typeof uri === 'string')) { + throw new Error(`Unexpected NuclideUri type: ${String(uri)}`); + } if (isRemote(uri)) { parse(uri); - invariant(mustBeRemote !== false, 'Expected remote NuclideUri'); + + if (!(mustBeRemote !== false)) { + throw new Error('Expected remote NuclideUri'); + } } else { - invariant(uri !== '', 'NuclideUri must contain a non-empty path'); - invariant(mustBeRemote !== true, 'Expected local NuclideUri'); + if (!(uri !== '')) { + throw new Error('NuclideUri must contain a non-empty path'); + } + + if (!(mustBeRemote !== true)) { + throw new Error('Expected local NuclideUri'); + } } } -export default { +exports.default = { basename, dirname, extname, @@ -662,9 +658,8 @@ export default { parsePath, split, pathSeparatorFor, - NUCLIDE_URI_TYPE_NAME, -}; - -export const __TEST__ = { - _pathModuleFor, + NUCLIDE_URI_TYPE_NAME }; +const __TEST__ = exports.__TEST__ = { + _pathModuleFor +}; \ No newline at end of file diff --git a/modules/nuclide-commons/observable.js b/modules/nuclide-commons/observable.js index 752dba07..1b9fa849 100644 --- a/modules/nuclide-commons/observable.js +++ b/modules/nuclide-commons/observable.js @@ -1,21 +1,36 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -/* global requestAnimationFrame, cancelAnimationFrame */ +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.nextAnimationFrame = exports.macrotask = exports.microtask = undefined; +exports.splitStream = splitStream; +exports.bufferUntil = bufferUntil; +exports.cacheWhileSubscribed = cacheWhileSubscribed; +exports.diffSets = diffSets; +exports.reconcileSetDiffs = reconcileSetDiffs; +exports.reconcileSets = reconcileSets; +exports.toggle = toggle; +exports.compact = compact; +exports.takeWhileInclusive = takeWhileInclusive; +exports.concatLatest = concatLatest; +exports.throttle = throttle; -import UniversalDisposable from './UniversalDisposable'; -import invariant from 'assert'; -import {Observable, ReplaySubject} from 'rxjs'; -import {setDifference} from './collection'; +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('./UniversalDisposable')); +} + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _collection; + +function _load_collection() { + return _collection = require('./collection'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Splits a stream of strings on newlines. @@ -23,9 +38,9 @@ import {setDifference} from './collection'; * Sends any non-newline terminated data before closing. * Never sends an empty string. */ -export function splitStream(input: Observable): Observable { - return Observable.create(observer => { - let current: string = ''; +function splitStream(input) { + return _rxjsBundlesRxMinJs.Observable.create(observer => { + let current = ''; function onEnd() { if (current !== '') { @@ -34,21 +49,17 @@ export function splitStream(input: Observable): Observable { } } - return input.subscribe( - value => { - const lines = (current + value).split('\n'); - current = lines.pop(); - lines.forEach(line => observer.next(line + '\n')); - }, - error => { - onEnd(); - observer.error(error); - }, - () => { - onEnd(); - observer.complete(); - }, - ); + return input.subscribe(value => { + const lines = (current + value).split('\n'); + current = lines.pop(); + lines.forEach(line => observer.next(line + '\n')); + }, error => { + onEnd(); + observer.error(error); + }, () => { + onEnd(); + observer.complete(); + }); }); } @@ -61,11 +72,22 @@ export function splitStream(input: Observable): Observable { * (which includes the element). IMPORTANT: DO NOT MUTATE THE BUFFER. It returns a boolean * specifying whether to complete the buffer (and begin a new one). */ -export function bufferUntil( - stream: Observable, - condition: (item: T, buffer: Array) => boolean, -): Observable> { - return Observable.create(observer => { +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +/* global requestAnimationFrame, cancelAnimationFrame */ + +function bufferUntil(stream, condition) { + return _rxjsBundlesRxMinJs.Observable.create(observer => { let buffer = null; const flush = () => { if (buffer != null) { @@ -73,25 +95,21 @@ export function bufferUntil( buffer = null; } }; - return stream.subscribe( - x => { - if (buffer == null) { - buffer = []; - } - buffer.push(x); - if (condition(x, buffer)) { - flush(); - } - }, - err => { - flush(); - observer.error(err); - }, - () => { + return stream.subscribe(x => { + if (buffer == null) { + buffer = []; + } + buffer.push(x); + if (condition(x, buffer)) { flush(); - observer.complete(); - }, - ); + } + }, err => { + flush(); + observer.error(err); + }, () => { + flush(); + observer.complete(); + }); }); } @@ -103,49 +121,36 @@ export function bufferUntil( * be just fine because the hot Observable will continue producing values even when there are no * subscribers, so you can be assured that the cached values are up-to-date. */ -export function cacheWhileSubscribed(input: Observable): Observable { - return input.multicast(() => new ReplaySubject(1)).refCount(); +function cacheWhileSubscribed(input) { + return input.multicast(() => new _rxjsBundlesRxMinJs.ReplaySubject(1)).refCount(); } -type Diff = { - added: Set, - removed: Set, -}; - /** * Given a stream of sets, return a stream of diffs. * **IMPORTANT:** These sets are assumed to be immutable by convention. Don't mutate them! */ -export function diffSets( - sets: Observable>, - hash?: (v: T) => any, -): Observable> { - return Observable.concat( - Observable.of(new Set()), // Always start with no items with an empty set - sets, - ) - .pairwise() - .map(([previous, next]) => ({ - added: setDifference(next, previous, hash), - removed: setDifference(previous, next, hash), - })) - .filter(diff => diff.added.size > 0 || diff.removed.size > 0); +function diffSets(sets, hash) { + return _rxjsBundlesRxMinJs.Observable.concat(_rxjsBundlesRxMinJs.Observable.of(new Set()), // Always start with no items with an empty set + sets).pairwise().map(([previous, next]) => ({ + added: (0, (_collection || _load_collection()).setDifference)(next, previous, hash), + removed: (0, (_collection || _load_collection()).setDifference)(previous, next, hash) + })).filter(diff => diff.added.size > 0 || diff.removed.size > 0); } /** * Give a stream of diffs, perform an action for each added item and dispose of the returned * disposable when the item is removed. */ -export function reconcileSetDiffs( - diffs: Observable>, - addAction: (addedItem: T) => IDisposable, - hash_?: (v: T) => any, -): IDisposable { +function reconcileSetDiffs(diffs, addAction, hash_) { const hash = hash_ || (x => x); const itemsToDisposables = new Map(); const disposeItem = item => { const disposable = itemsToDisposables.get(hash(item)); - invariant(disposable != null); + + if (!(disposable != null)) { + throw new Error('Invariant violation: "disposable != null"'); + } + disposable.dispose(); itemsToDisposables.delete(item); }; @@ -156,18 +161,15 @@ export function reconcileSetDiffs( itemsToDisposables.clear(); }; - return new UniversalDisposable( - diffs.subscribe(diff => { - // For every item that got added, perform the add action. - diff.added.forEach(item => { - itemsToDisposables.set(hash(item), addAction(item)); - }); + return new (_UniversalDisposable || _load_UniversalDisposable()).default(diffs.subscribe(diff => { + // For every item that got added, perform the add action. + diff.added.forEach(item => { + itemsToDisposables.set(hash(item), addAction(item)); + }); - // "Undo" the add action for each item that got removed. - diff.removed.forEach(disposeItem); - }), - disposeAll, - ); + // "Undo" the add action for each item that got removed. + diff.removed.forEach(disposeItem); + }), disposeAll); } /** @@ -198,90 +200,51 @@ export function reconcileSetDiffs( * of the dogs observable, his notification will remain until `disposable.dispose()` is called, at * which point the cleanup for all remaining items will be performed. */ -export function reconcileSets( - sets: Observable>, - addAction: (addedItem: T) => IDisposable, - hash?: (v: T) => any, -): IDisposable { +function reconcileSets(sets, addAction, hash) { const diffs = diffSets(sets, hash); return reconcileSetDiffs(diffs, addAction, hash); } -export function toggle( - source: Observable, - toggler: Observable, -): Observable { - return toggler - .distinctUntilChanged() - .switchMap(enabled => (enabled ? source : Observable.empty())); +function toggle(source, toggler) { + return toggler.distinctUntilChanged().switchMap(enabled => enabled ? source : _rxjsBundlesRxMinJs.Observable.empty()); } -export function compact(source: Observable): Observable { +function compact(source) { // Flow does not understand the semantics of `filter` - return (source.filter(x => x != null): any); + return source.filter(x => x != null); } /** * Like `takeWhile`, but includes the first item that doesn't match the predicate. */ -export function takeWhileInclusive( - source: Observable, - predicate: (value: T) => boolean, -): Observable { - return Observable.create(observer => - source.subscribe( - x => { - observer.next(x); - if (!predicate(x)) { - observer.complete(); - } - }, - err => { - observer.error(err); - }, - () => { - observer.complete(); - }, - ), - ); +function takeWhileInclusive(source, predicate) { + return _rxjsBundlesRxMinJs.Observable.create(observer => source.subscribe(x => { + observer.next(x); + if (!predicate(x)) { + observer.complete(); + } + }, err => { + observer.error(err); + }, () => { + observer.complete(); + })); } // Concatenate the latest values from each input observable into one big list. // Observables who have not emitted a value yet are treated as empty. -export function concatLatest( - ...observables: Array>> -): Observable> { +function concatLatest(...observables) { // First, tag all input observables with their index. - // Flow errors with ambiguity without the explicit annotation. - const tagged: Array< - Observable<[Array, number]>, - > = observables.map((observable, index) => - observable.map(list => [list, index]), - ); - return Observable.merge(...tagged) - .scan((accumulator, [list, index]) => { - accumulator[index] = list; - return accumulator; - }, observables.map(x => [])) - .map(accumulator => [].concat(...accumulator)); + const tagged = observables.map((observable, index) => observable.map(list => [list, index])); + return _rxjsBundlesRxMinJs.Observable.merge(...tagged).scan((accumulator, [list, index]) => { + accumulator[index] = list; + return accumulator; + }, observables.map(x => [])).map(accumulator => [].concat(...accumulator)); } -type ThrottleOptions = { - // Should the first element be emitted immeditately? Defaults to true. - leading?: boolean, -}; - /** * A more sensible alternative to RxJS's throttle/audit/sample operators. */ -export function throttle( - source: Observable, - duration: - | number - | Observable - | ((value: T) => Observable | Promise), - options_: ?ThrottleOptions, -): Observable { +function throttle(source, duration, options_) { const options = options_ || {}; const leading = options.leading !== false; let audit; @@ -301,27 +264,21 @@ export function throttle( return audit(source); } - return Observable.create(observer => { + return _rxjsBundlesRxMinJs.Observable.create(observer => { const connectableSource = source.publish(); - const throttled = Observable.merge( - connectableSource.take(1), - audit(connectableSource.skip(1)), - ); - return new UniversalDisposable( - throttled.subscribe(observer), - connectableSource.connect(), - ); + const throttled = _rxjsBundlesRxMinJs.Observable.merge(connectableSource.take(1), audit(connectableSource.skip(1))); + return new (_UniversalDisposable || _load_UniversalDisposable()).default(throttled.subscribe(observer), connectableSource.connect()); }); } -export const microtask = Observable.create(observer => { +const microtask = exports.microtask = _rxjsBundlesRxMinJs.Observable.create(observer => { process.nextTick(() => { observer.next(); observer.complete(); }); }); -export const macrotask = Observable.create(observer => { +const macrotask = exports.macrotask = _rxjsBundlesRxMinJs.Observable.create(observer => { const timerId = setImmediate(() => { observer.next(); observer.complete(); @@ -331,7 +288,7 @@ export const macrotask = Observable.create(observer => { }; }); -export const nextAnimationFrame = Observable.create(observer => { +const nextAnimationFrame = exports.nextAnimationFrame = _rxjsBundlesRxMinJs.Observable.create(observer => { if (typeof requestAnimationFrame === 'undefined') { throw new Error('This util can only be used in Atom'); } @@ -342,4 +299,4 @@ export const nextAnimationFrame = Observable.create(observer => { return () => { cancelAnimationFrame(id); }; -}); +}); \ No newline at end of file diff --git a/modules/nuclide-commons/performanceNow.js b/modules/nuclide-commons/performanceNow.js index 12914cb0..4ba73296 100644 --- a/modules/nuclide-commons/performanceNow.js +++ b/modules/nuclide-commons/performanceNow.js @@ -1,3 +1,8 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,7 +11,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ @@ -22,9 +27,7 @@ * const timeItTookInMilliseconds = performanceNow() - now; */ -export default (typeof performance !== 'undefined' - ? (): number => performance.now() - : (): number => { - const [seconds, nanoseconds] = process.hrtime(); - return seconds * 1000 + nanoseconds / 1000000; - }); +exports.default = typeof performance !== 'undefined' ? () => performance.now() : () => { + const [seconds, nanoseconds] = process.hrtime(); + return seconds * 1000 + nanoseconds / 1000000; +}; \ No newline at end of file diff --git a/modules/nuclide-commons/process.js b/modules/nuclide-commons/process.js index 0536117e..fe4e7e36 100644 --- a/modules/nuclide-commons/process.js +++ b/modules/nuclide-commons/process.js @@ -1,66 +1,217 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.killUnixProcessTree = exports.loggedCalls = exports.ProcessTimeoutError = exports.MaxBufferExceededError = exports.ProcessSystemError = exports.ProcessExitError = exports.psTree = exports.getChildrenOfProcess = exports.getOriginalEnvironment = undefined; + +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + +let getOriginalEnvironment = exports.getOriginalEnvironment = (() => { + var _ref6 = (0, _asyncToGenerator.default)(function* () { + yield new Promise(function (resolve) { + whenShellEnvironmentLoaded(resolve); + }); + if (cachedOriginalEnvironment != null) { + return cachedOriginalEnvironment; + } + + const { NUCLIDE_ORIGINAL_ENV } = process.env; + if (NUCLIDE_ORIGINAL_ENV != null && NUCLIDE_ORIGINAL_ENV.trim() !== '') { + const envString = new Buffer(NUCLIDE_ORIGINAL_ENV, 'base64').toString(); + cachedOriginalEnvironment = {}; + for (const envVar of envString.split('\0')) { + // envVar should look like A=value_of_A + const equalIndex = envVar.indexOf('='); + if (equalIndex !== -1) { + cachedOriginalEnvironment[envVar.substring(0, equalIndex)] = envVar.substring(equalIndex + 1); + } + } + // Guard against invalid original environments. + if (!Object.keys(cachedOriginalEnvironment).length) { + cachedOriginalEnvironment = process.env; + } + } else { + cachedOriginalEnvironment = process.env; + } + return cachedOriginalEnvironment; + }); + + return function getOriginalEnvironment() { + return _ref6.apply(this, arguments); + }; +})(); + /** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format + * Returns a string suitable for including in displayed error messages. */ -// -// __ __ __ __ ___ __ __ __ -// |__) |__) / \ / ` |__ /__` /__` | /__` -// | | \ \__/ \__, |___ .__/ .__/ .\__/ .__/ -// -// This module contains utilities for spawning processes in Nuclide. In general: -// -// - They accept similar arguments. -// - They return an observable. -// - The process is spawned if/when you subscribe to the observable. -// - If you unsubscribe before the observable completes, the process is killed. -// - The observable errors if the process completes with a non-zero exit code (by default; this can -// be changed) or if the process can't be spawned. -// -// The most important functions in this module are `runCommand()`--for running a quick command and -// getting its output--and `observeProcess()`--for streaming output from a process. They'll handle -// the majority of use cases. -// -// ## Why observables? -// -// Unlike Promises, observables have a standardized, composable cancelation mechanism _today_. -// Moreover, observables integrate nicely with Atom's callback + IDisposable formula for cancelable, -// async APIs. Along with React, [RxJS] is one of the core libaries utilized by Nuclide. -// -// ## Why errors? -// -// In the past, we had some process APIs that used errors and some that used return values. -// Consistency has obvious benefits; standardizing on errors makes sense because: -// -// - The error-throwing APIs were the most used, by a large margin. -// - Unhandled errors can be caught and logged at the top level. -// - Observables have a separate channel for errors which allows for cool, error-aware operators -// like `retry()` and caching. -// - Errors in observables are stream-ending. This means you won't continue to do work in a chain of -// operators accidentally. -// -// [RxJS]: http://reactivex.io/rxjs/ -import child_process from 'child_process'; -import idx from 'idx'; -import invariant from 'assert'; -import {Observable, TimeoutError} from 'rxjs'; +let getChildrenOfProcess = exports.getChildrenOfProcess = (() => { + var _ref7 = (0, _asyncToGenerator.default)(function* (processId) { + const processes = yield psTree(); -import UniversalDisposable from './UniversalDisposable'; -import nuclideUri from './nuclideUri'; -import performanceNow from './performanceNow'; -import {MultiMap} from './collection'; -import {observableFromSubscribeFunction} from './event'; -import {observeStream} from './stream'; -import {splitStream, takeWhileInclusive} from './observable'; -import {shellQuote} from './string'; + return processes.filter(function (processInfo) { + return processInfo.parentPid === processId; + }); + }); + + return function getChildrenOfProcess(_x) { + return _ref7.apply(this, arguments); + }; +})(); + +/** + * Get a list of descendants, sorted by increasing depth (including the one with the provided pid). + */ + + +let getDescendantsOfProcess = (() => { + var _ref8 = (0, _asyncToGenerator.default)(function* (pid) { + const processes = yield psTree(); + let rootProcessInfo; + const pidToChildren = new (_collection || _load_collection()).MultiMap(); + processes.forEach(function (info) { + if (info.pid === pid) { + rootProcessInfo = info; + } + pidToChildren.add(info.parentPid, info); + }); + const descendants = rootProcessInfo == null ? [] : [rootProcessInfo]; + // Walk through the array, adding the children of the current element to the end. This + // breadth-first traversal means that the elements will be sorted by depth. + for (let i = 0; i < descendants.length; i++) { + const info = descendants[i]; + const children = pidToChildren.get(info.pid); + descendants.push(...Array.from(children)); + } + return descendants; + }); + + return function getDescendantsOfProcess(_x2) { + return _ref8.apply(this, arguments); + }; +})(); + +let psTree = exports.psTree = (() => { + var _ref9 = (0, _asyncToGenerator.default)(function* () { + const stdout = isWindowsPlatform() ? // See also: https://github.com/nodejs/node-v0.x-archive/issues/2318 + yield runCommand('wmic.exe', ['PROCESS', 'GET', 'ParentProcessId,ProcessId,Name']).toPromise() : yield runCommand('ps', ['-A', '-o', 'ppid,pid,comm']).toPromise(); + return parsePsOutput(stdout); + }); + + return function psTree() { + return _ref9.apply(this, arguments); + }; +})(); + +let _killProcess = (() => { + var _ref10 = (0, _asyncToGenerator.default)(function* (proc, killTree) { + proc.wasKilled = true; + if (!killTree) { + proc.kill(); + return; + } + if (/^win/.test(process.platform)) { + yield killWindowsProcessTree(proc.pid); + } else { + yield killUnixProcessTree(proc); + } + }); + + return function _killProcess(_x3, _x4) { + return _ref10.apply(this, arguments); + }; +})(); + +let killUnixProcessTree = exports.killUnixProcessTree = (() => { + var _ref11 = (0, _asyncToGenerator.default)(function* (proc) { + const descendants = yield getDescendantsOfProcess(proc.pid); + // Kill the processes, starting with those of greatest depth. + for (const info of descendants.reverse()) { + killPid(info.pid); + } + }); + + return function killUnixProcessTree(_x5) { + return _ref11.apply(this, arguments); + }; +})(); + +exports.runCommand = runCommand; +exports.observeProcess = observeProcess; +exports.runCommandDetailed = runCommandDetailed; +exports.observeProcessRaw = observeProcessRaw; +exports.spawn = spawn; +exports.fork = fork; +exports.getOutputStream = getOutputStream; +exports.scriptifyCommand = scriptifyCommand; +exports.killProcess = killProcess; +exports.killPid = killPid; +exports.exitEventToMessage = exitEventToMessage; +exports.parsePsOutput = parsePsOutput; +exports.preventStreamsFromThrowing = preventStreamsFromThrowing; +exports.logStreamErrors = logStreamErrors; + +var _child_process = _interopRequireDefault(require('child_process')); + +var _idx; + +function _load_idx() { + return _idx = _interopRequireDefault(require('idx')); +} + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('./UniversalDisposable')); +} + +var _nuclideUri; + +function _load_nuclideUri() { + return _nuclideUri = _interopRequireDefault(require('./nuclideUri')); +} + +var _performanceNow; + +function _load_performanceNow() { + return _performanceNow = _interopRequireDefault(require('./performanceNow')); +} + +var _collection; + +function _load_collection() { + return _collection = require('./collection'); +} + +var _event; + +function _load_event() { + return _event = require('./event'); +} + +var _stream; + +function _load_stream() { + return _stream = require('./stream'); +} + +var _observable; + +function _load_observable() { + return _observable = require('./observable'); +} + +var _string; + +function _load_string() { + return _string = require('./string'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Run a command, accumulate the output. Errors are surfaced as stream errors and unsubscribing will @@ -115,12 +266,7 @@ import {shellQuote} from './string'; * [1]: https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options * [2]: https://nodejs.org/api/errors.html#errors_class_system_error */ -export function runCommand( - command: string, - args?: Array = [], - options?: ObserveProcessOptions = {}, - rest: void, -): Observable { +function runCommand(command, args = [], options = {}, rest) { return runCommandDetailed(command, args, options).map(event => event.stdout); } @@ -150,14 +296,58 @@ export function runCommand( * }); * ``` */ -export function observeProcess( - command: string, - args?: Array, - options?: ObserveProcessOptions, -): Observable { - return spawn(command, args, options).flatMap(proc => - getOutputStream(proc, options), - ); +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +// +// __ __ __ __ ___ __ __ __ +// |__) |__) / \ / ` |__ /__` /__` | /__` +// | | \ \__/ \__, |___ .__/ .__/ .\__/ .__/ +// +// This module contains utilities for spawning processes in Nuclide. In general: +// +// - They accept similar arguments. +// - They return an observable. +// - The process is spawned if/when you subscribe to the observable. +// - If you unsubscribe before the observable completes, the process is killed. +// - The observable errors if the process completes with a non-zero exit code (by default; this can +// be changed) or if the process can't be spawned. +// +// The most important functions in this module are `runCommand()`--for running a quick command and +// getting its output--and `observeProcess()`--for streaming output from a process. They'll handle +// the majority of use cases. +// +// ## Why observables? +// +// Unlike Promises, observables have a standardized, composable cancelation mechanism _today_. +// Moreover, observables integrate nicely with Atom's callback + IDisposable formula for cancelable, +// async APIs. Along with React, [RxJS] is one of the core libaries utilized by Nuclide. +// +// ## Why errors? +// +// In the past, we had some process APIs that used errors and some that used return values. +// Consistency has obvious benefits; standardizing on errors makes sense because: +// +// - The error-throwing APIs were the most used, by a large margin. +// - Unhandled errors can be caught and logged at the top level. +// - Observables have a separate channel for errors which allows for cool, error-aware operators +// like `retry()` and caching. +// - Errors in observables are stream-ending. This means you won't continue to do work in a chain of +// operators accidentally. +// +// [RxJS]: http://reactivex.io/rxjs/ + +function observeProcess(command, args, options) { + return spawn(command, args, options).flatMap(proc => getOutputStream(proc, options)); } /** @@ -168,58 +358,38 @@ export function observeProcess( * In general, you should prefer `runCommand()`, however, this function is useful for when stderr is * needed even if the process exits successfully. */ -export function runCommandDetailed( - command: string, - args?: Array = [], - options?: ObserveProcessOptions = {}, - rest: void, -): Observable<{stdout: string, stderr: string, exitCode: ?number}> { - const maxBuffer = idx(options, _ => _.maxBuffer) || DEFAULT_MAX_BUFFER; - return observeProcess(command, args, {...options, maxBuffer}) - .catch(error => { - // Catch ProcessExitErrors so that we can add stdout to them. - if (error instanceof ProcessExitError) { - return Observable.of({kind: 'process-exit-error', error}); - } - throw error; - }) - .reduce( - (acc, event) => { - switch (event.kind) { - case 'stdout': - return {...acc, stdout: acc.stdout + event.data}; - case 'stderr': - return {...acc, stderr: acc.stderr + event.data}; - case 'exit': - return {...acc, exitCode: event.exitCode}; - case 'process-exit-error': - const {error} = event; - throw new ProcessExitError( - error.exitCode, - error.signal, - error.process, - acc.stderr, - acc.stdout, - ); - default: - throw new Error(`Invalid event kind: ${event.kind}`); - } - }, - {stdout: '', stderr: '', exitCode: null}, - ); +function runCommandDetailed(command, args = [], options = {}, rest) { + var _ref; + + const maxBuffer = ((_ref = options) != null ? _ref.maxBuffer : _ref) || DEFAULT_MAX_BUFFER; + return observeProcess(command, args, Object.assign({}, options, { maxBuffer })).catch(error => { + // Catch ProcessExitErrors so that we can add stdout to them. + if (error instanceof ProcessExitError) { + return _rxjsBundlesRxMinJs.Observable.of({ kind: 'process-exit-error', error }); + } + throw error; + }).reduce((acc, event) => { + switch (event.kind) { + case 'stdout': + return Object.assign({}, acc, { stdout: acc.stdout + event.data }); + case 'stderr': + return Object.assign({}, acc, { stderr: acc.stderr + event.data }); + case 'exit': + return Object.assign({}, acc, { exitCode: event.exitCode }); + case 'process-exit-error': + const { error } = event; + throw new ProcessExitError(error.exitCode, error.signal, error.process, acc.stderr, acc.stdout); + default: + throw new Error(`Invalid event kind: ${event.kind}`); + } + }, { stdout: '', stderr: '', exitCode: null }); } /** * Identical to `observeProcess()`, but doesn't buffer by line. */ -export function observeProcessRaw( - command: string, - args?: Array, - options?: ObserveProcessOptions, -): Observable { - return spawn(command, args, options).flatMap(proc => - getOutputStream(proc, {...options, splitByLines: false}), - ); +function observeProcessRaw(command, args, options) { + return spawn(command, args, options).flatMap(proc => getOutputStream(proc, Object.assign({}, options, { splitByLines: false }))); } // @@ -255,22 +425,14 @@ export function observeProcessRaw( * }); * ``` */ -export function spawn( - command: string, - args?: Array, - options?: SpawnProcessOptions, -): Observable { +function spawn(command, args, options) { return createProcessStream('spawn', command, args, options); } /** * Identical to `spawn()` (above), but uses `child_process.fork()` to create the process. */ -export function fork( - modulePath: string, - args?: Array, - options?: ForkProcessOptions, -): Observable { +function fork(modulePath, args, options) { return createProcessStream('fork', modulePath, args, options); } @@ -285,72 +447,39 @@ export function fork( * This function intentionally does not close the process when you unsubscribe. It's usually used in * conjunction with `spawn()` which does that already. */ -export function getOutputStream( - proc: child_process$ChildProcess, - options?: GetOutputStreamOptions, - rest: void, -): Observable { - const chunk = - idx(options, _ => _.splitByLines) === false ? x => x : splitStream; - const maxBuffer = idx(options, _ => _.maxBuffer); - const isExitError = idx(options, _ => _.isExitError) || isExitErrorDefault; - const exitErrorBufferSize = idx(options, _ => _.exitErrorBufferSize) || 2000; - return Observable.defer(() => { - const stdoutEvents = chunk( - limitBufferSize(observeStream(proc.stdout), maxBuffer, 'stdout'), - ).map(data => ({kind: 'stdout', data})); - const stderrEvents = chunk( - limitBufferSize(observeStream(proc.stderr), maxBuffer, 'stderr'), - ) - .map(data => ({kind: 'stderr', data})) - .share(); +function getOutputStream(proc, options, rest) { + var _ref2, _ref3, _ref4, _ref5; + + const chunk = ((_ref2 = options) != null ? _ref2.splitByLines : _ref2) === false ? x => x : (_observable || _load_observable()).splitStream; + const maxBuffer = (_ref3 = options) != null ? _ref3.maxBuffer : _ref3; + const isExitError = ((_ref4 = options) != null ? _ref4.isExitError : _ref4) || isExitErrorDefault; + const exitErrorBufferSize = ((_ref5 = options) != null ? _ref5.exitErrorBufferSize : _ref5) || 2000; + return _rxjsBundlesRxMinJs.Observable.defer(() => { + const stdoutEvents = chunk(limitBufferSize((0, (_stream || _load_stream()).observeStream)(proc.stdout), maxBuffer, 'stdout')).map(data => ({ kind: 'stdout', data })); + const stderrEvents = chunk(limitBufferSize((0, (_stream || _load_stream()).observeStream)(proc.stderr), maxBuffer, 'stderr')).map(data => ({ kind: 'stderr', data })).share(); // Accumulate the first `exitErrorBufferSize` bytes of stderr so that we can give feedback about // about exit errors (then stop so we don't fill up memory with it). - const accumulatedStderr = takeWhileInclusive( - stderrEvents - .scan( - (acc, event) => (acc + event.data).slice(0, exitErrorBufferSize), - '', - ) - .startWith(''), - acc => acc.length < exitErrorBufferSize, - ); + const accumulatedStderr = (0, (_observable || _load_observable()).takeWhileInclusive)(stderrEvents.scan((acc, event) => (acc + event.data).slice(0, exitErrorBufferSize), '').startWith(''), acc => acc.length < exitErrorBufferSize); // We need to start listening for the exit event immediately, but defer emitting it until the // (buffered) output streams end. - const closeEvents = Observable.fromEvent( - proc, - // We listen to the "close" event instead of "exit" because we want to get all of the stdout - // and stderr. - 'close', - (exitCode: ?number, signal: ?string) => ({ - kind: 'exit', - exitCode, - signal, - }), - ) - .filter(isRealExit) - .take(1) - .withLatestFrom(accumulatedStderr) - .map(([event, stderr]) => { - if (isExitError(event)) { - throw new ProcessExitError( - event.exitCode, - event.signal, - proc, - stderr, - ); - } - return event; - }) - .publishReplay(); + const closeEvents = _rxjsBundlesRxMinJs.Observable.fromEvent(proc, + // We listen to the "close" event instead of "exit" because we want to get all of the stdout + // and stderr. + 'close', (exitCode, signal) => ({ + kind: 'exit', + exitCode, + signal + })).filter(isRealExit).take(1).withLatestFrom(accumulatedStderr).map(([event, stderr]) => { + if (isExitError(event)) { + throw new ProcessExitError(event.exitCode, event.signal, proc, stderr); + } + return event; + }).publishReplay(); const exitSub = closeEvents.connect(); - return takeWhileInclusive( - Observable.merge(stdoutEvents, stderrEvents).concat(closeEvents), - event => event.kind !== 'error' && event.kind !== 'exit', - ).finally(() => { + return (0, (_observable || _load_observable()).takeWhileInclusive)(_rxjsBundlesRxMinJs.Observable.merge(stdoutEvents, stderrEvents).concat(closeEvents), event => event.kind !== 'error' && event.kind !== 'exit').finally(() => { exitSub.unsubscribe(); }); }); @@ -375,52 +504,39 @@ export function getOutputStream( * * See also `nicifyCommand()` which does a similar thing but for `nice`. */ -export function scriptifyCommand( - command: string, - args?: Array = [], - options: T, -): [string, Array, T] { +function scriptifyCommand(command, args = [], options) { if (process.platform === 'darwin') { // On OS X, script takes the program to run and its arguments as varargs at the end. return ['script', ['-q', '/dev/null', command].concat(args), options]; } else { // On Linux, script takes the command to run as the -c parameter so we have to combine all of // the arguments into a single string. - const joined = shellQuote([command, ...args]); + const joined = (0, (_string || _load_string()).shellQuote)([command, ...args]); // flowlint-next-line sketchy-null-mixed:off const opts = options || {}; // flowlint-next-line sketchy-null-mixed:off const env = opts.env || {}; - return [ - 'script', - ['-q', '/dev/null', '-c', joined], - // `script` will use `SHELL`, but shells have different behaviors with regard to escaping. To - // make sure that out escaping is correct, we need to force a particular shell. - // $FlowIssue: Adding SHELL here makes it no longer really T - {...opts, env: {...env, SHELL: '/bin/bash'}}, - ]; + return ['script', ['-q', '/dev/null', '-c', joined], + // `script` will use `SHELL`, but shells have different behaviors with regard to escaping. To + // make sure that out escaping is correct, we need to force a particular shell. + // $FlowIssue: Adding SHELL here makes it no longer really T + Object.assign({}, opts, { env: Object.assign({}, env, { SHELL: '/bin/bash' }) })]; } } /** * Kills a process and, optionally, its descendants. */ -export function killProcess( - proc: child_process$ChildProcess, - killTree: boolean, -): void { - _killProcess(proc, killTree).then( - () => {}, - error => { - logError(`Killing process ${proc.pid} failed`, error); - }, - ); +function killProcess(proc, killTree) { + _killProcess(proc, killTree).then(() => {}, error => { + logError(`Killing process ${proc.pid} failed`, error); + }); } /** * Kill the process with the provided pid. */ -export function killPid(pid: number): void { +function killPid(pid) { try { process.kill(pid); } catch (err) { @@ -433,99 +549,19 @@ export function killPid(pid: number): void { // If provided, read the original environment from NUCLIDE_ORIGINAL_ENV. // This should contain the base64-encoded output of `env -0`. let cachedOriginalEnvironment = null; -export async function getOriginalEnvironment(): Promise { - await new Promise(resolve => { - whenShellEnvironmentLoaded(resolve); - }); - if (cachedOriginalEnvironment != null) { - return cachedOriginalEnvironment; - } - - const {NUCLIDE_ORIGINAL_ENV} = process.env; - if (NUCLIDE_ORIGINAL_ENV != null && NUCLIDE_ORIGINAL_ENV.trim() !== '') { - const envString = new Buffer(NUCLIDE_ORIGINAL_ENV, 'base64').toString(); - cachedOriginalEnvironment = {}; - for (const envVar of envString.split('\0')) { - // envVar should look like A=value_of_A - const equalIndex = envVar.indexOf('='); - if (equalIndex !== -1) { - cachedOriginalEnvironment[ - envVar.substring(0, equalIndex) - ] = envVar.substring(equalIndex + 1); - } - } - // Guard against invalid original environments. - if (!Object.keys(cachedOriginalEnvironment).length) { - cachedOriginalEnvironment = process.env; - } - } else { - cachedOriginalEnvironment = process.env; - } - return cachedOriginalEnvironment; -} - -/** - * Returns a string suitable for including in displayed error messages. - */ -export function exitEventToMessage(event: { - exitCode: ?number, - signal: ?string, -}): string { +function exitEventToMessage(event) { if (event.exitCode != null) { return `exit code ${event.exitCode}`; } else { - invariant(event.signal != null); - return `signal ${event.signal}`; - } -} - -export async function getChildrenOfProcess( - processId: number, -): Promise> { - const processes = await psTree(); - - return processes.filter(processInfo => processInfo.parentPid === processId); -} - -/** - * Get a list of descendants, sorted by increasing depth (including the one with the provided pid). - */ -async function getDescendantsOfProcess( - pid: number, -): Promise> { - const processes = await psTree(); - let rootProcessInfo; - const pidToChildren = new MultiMap(); - processes.forEach(info => { - if (info.pid === pid) { - rootProcessInfo = info; + if (!(event.signal != null)) { + throw new Error('Invariant violation: "event.signal != null"'); } - pidToChildren.add(info.parentPid, info); - }); - const descendants = rootProcessInfo == null ? [] : [rootProcessInfo]; - // Walk through the array, adding the children of the current element to the end. This - // breadth-first traversal means that the elements will be sorted by depth. - for (let i = 0; i < descendants.length; i++) { - const info = descendants[i]; - const children = pidToChildren.get(info.pid); - descendants.push(...Array.from(children)); - } - return descendants; -} -export async function psTree(): Promise> { - const stdout = isWindowsPlatform() - ? // See also: https://github.com/nodejs/node-v0.x-archive/issues/2318 - await runCommand('wmic.exe', [ - 'PROCESS', - 'GET', - 'ParentProcessId,ProcessId,Name', - ]).toPromise() - : await runCommand('ps', ['-A', '-o', 'ppid,pid,comm']).toPromise(); - return parsePsOutput(stdout); + return `signal ${event.signal}`; + } } -export function parsePsOutput(psOutput: string): Array { +function parsePsOutput(psOutput) { // Remove the first header line. const lines = psOutput.split(/\n|\r\n/).slice(1); @@ -537,7 +573,7 @@ export function parsePsOutput(psOutput: string): Array { return { command, parentPid: parseInt(parentPid, 10), - pid: parseInt(pid, 10), + pid: parseInt(pid, 10) }; }); } @@ -545,36 +581,18 @@ export function parsePsOutput(psOutput: string): Array { /** * Add no-op error handlers to the process's streams so that Node doesn't throw them. */ -export function preventStreamsFromThrowing( - proc: child_process$ChildProcess, -): IDisposable { - return new UniversalDisposable(getStreamErrorEvents(proc).subscribe()); +function preventStreamsFromThrowing(proc) { + return new (_UniversalDisposable || _load_UniversalDisposable()).default(getStreamErrorEvents(proc).subscribe()); } /** * Log errors from a process's streams. This function returns an `rxjs$ISubscription` so that it * can easily be used with `Observable.using()`. */ -export function logStreamErrors( - proc: child_process$ChildProcess, - command: string, - args: Array, - options?: Object, -): IDisposable & rxjs$ISubscription { - return new UniversalDisposable( - getStreamErrorEvents(proc) - .do(([err, streamName]) => { - logError( - `stream error on stream ${streamName} with command:`, - command, - args, - options, - 'error:', - err, - ); - }) - .subscribe(), - ); +function logStreamErrors(proc, command, args, options) { + return new (_UniversalDisposable || _load_UniversalDisposable()).default(getStreamErrorEvents(proc).do(([err, streamName]) => { + logError(`stream error on stream ${streamName} with command:`, command, args, options, 'error:', err); + }).subscribe()); } // @@ -583,89 +601,11 @@ export function logStreamErrors( // Exactly one of exitCode and signal will be non-null. // Killing a process will result in a null exitCode but a non-null signal. -export type ProcessExitMessage = { - kind: 'exit', - exitCode: ?number, - signal: ?string, -}; -export type ProcessMessage = - | { - kind: 'stdout', - data: string, - } - | { - kind: 'stderr', - data: string, - } - | ProcessExitMessage; // In older versions of process.js, errors were emitted as messages instead of errors. This type // exists to support the transition, but no new usages should be added. -export type LegacyProcessMessage = - | ProcessMessage - | {kind: 'error', error: Object}; - -export type ProcessInfo = { - parentPid: number, - pid: number, - command: string, -}; - -export type Level = 'info' | 'log' | 'warning' | 'error' | 'debug' | 'success'; -export type Message = {text: string, level: Level}; - -export type MessageEvent = { - type: 'message', - message: Message, -}; - -export type ProgressEvent = { - type: 'progress', - progress: ?number, -}; - -export type ResultEvent = { - type: 'result', - result: mixed, -}; - -export type StatusEvent = { - type: 'status', - status: ?string, -}; - -export type TaskEvent = - | MessageEvent - | ProgressEvent - | ResultEvent - | StatusEvent; - -type CreateProcessStreamOptions = ( - | child_process$spawnOpts - | child_process$forkOpts) & { - killTreeWhenDone?: ?boolean, - timeout?: ?number, - input?: ?(string | Observable), - dontLogInNuclide?: ?boolean, -}; - -type GetOutputStreamOptions = { - splitByLines?: ?boolean, - maxBuffer?: ?number, - exitErrorBufferSize?: ?number, - isExitError?: ?(event: ProcessExitMessage) => boolean, -}; -export type ObserveProcessOptions = SpawnProcessOptions & - GetOutputStreamOptions; - -export type SpawnProcessOptions = child_process$spawnOpts & - CreateProcessStreamOptions; -export type ForkProcessOptions = child_process$forkOpts & - CreateProcessStreamOptions; - -export type ProcessError = ProcessSystemError | ProcessExitError; // // Errors @@ -680,30 +620,16 @@ export type ProcessError = ProcessSystemError | ProcessExitError; * `observeProcess()`, it will be truncated. Similarly, `stdout` will only be populated when the * error is thrown by output-accumulating functions. For others, it will always be `null`. */ -export class ProcessExitError extends Error { - exitCode: ?number; - signal: ?string; - stderr: string; - stdout: ?string; - process: child_process$ChildProcess; - - constructor( - exitCode: ?number, - signal: ?string, - proc: child_process$ChildProcess, - stderr: string, - stdout?: string, - ) { +class ProcessExitError extends Error { + + constructor(exitCode, signal, proc, stderr, stdout) { // $FlowIssue: This isn't typed in the Flow node type defs - const {spawnargs} = proc; - const commandName = - spawnargs[0] === process.execPath ? spawnargs[1] : spawnargs[0]; - super( - `"${commandName}" failed with ${exitEventToMessage({ - exitCode, - signal, - })}\n\n${stderr}`, - ); + const { spawnargs } = proc; + const commandName = spawnargs[0] === process.execPath ? spawnargs[1] : spawnargs[0]; + super(`"${commandName}" failed with ${exitEventToMessage({ + exitCode, + signal + })}\n\n${stderr}`); this.name = 'ProcessExitError'; this.exitCode = exitCode; this.signal = signal; @@ -713,18 +639,14 @@ export class ProcessExitError extends Error { } } -/** - * Process system errors are just augmented Error objects. We wrap the errors and expose the process - * since our utilities throw the errors before returning the process. - */ -export class ProcessSystemError extends Error { - errno: number | string; - code: string; - path: ?string; - syscall: ?string; - process: child_process$ChildProcess; - - constructor(err: any, proc: child_process$ChildProcess) { +exports.ProcessExitError = ProcessExitError; /** + * Process system errors are just augmented Error objects. We wrap the errors and expose the process + * since our utilities throw the errors before returning the process. + */ + +class ProcessSystemError extends Error { + + constructor(err, proc) { super(err.message); this.name = 'ProcessSystemError'; this.errno = err.errno; @@ -735,46 +657,45 @@ export class ProcessSystemError extends Error { } } -export class MaxBufferExceededError extends Error { - constructor(streamName: string) { +exports.ProcessSystemError = ProcessSystemError; +class MaxBufferExceededError extends Error { + constructor(streamName) { super(`${streamName} maxBuffer exceeded`); this.name = 'MaxBufferExceededError'; } } -export class ProcessTimeoutError extends Error { - constructor(timeout: number, proc: child_process$ChildProcess) { +exports.MaxBufferExceededError = MaxBufferExceededError; +class ProcessTimeoutError extends Error { + constructor(timeout, proc) { // $FlowIssue: This isn't typed in the Flow node type defs - const {spawnargs} = proc; - const commandName = - spawnargs[0] === process.execPath ? spawnargs[1] : spawnargs[0]; + const { spawnargs } = proc; + const commandName = spawnargs[0] === process.execPath ? spawnargs[1] : spawnargs[0]; super(`"${commandName}" timed out after ${timeout}ms`); this.name = 'ProcessTimeoutError'; } } -// +exports.ProcessTimeoutError = ProcessTimeoutError; // // Internal Stuff // // Pay no attention! This is just stuff that's used internally to implement the good stuff. // // Node crashes if we allow buffers that are too large. + const DEFAULT_MAX_BUFFER = 100 * 1024 * 1024; const MAX_LOGGED_CALLS = 100; const PREVERVED_HISTORY_CALLS = 50; -const noopDisposable = {dispose: () => {}}; -const whenShellEnvironmentLoaded = - typeof atom !== 'undefined' && !atom.inSpecMode() - ? atom.whenShellEnvironmentLoaded.bind(atom) - : cb => { - cb(); - return noopDisposable; - }; +const noopDisposable = { dispose: () => {} }; +const whenShellEnvironmentLoaded = typeof atom !== 'undefined' && !atom.inSpecMode() ? atom.whenShellEnvironmentLoaded.bind(atom) : cb => { + cb(); + return noopDisposable; +}; -export const loggedCalls = []; +const loggedCalls = exports.loggedCalls = []; function logCall(duration, command, args) { // Trim the history once in a while, to avoid doing expensive array // manipulation all the time after we reached the end of the history @@ -782,13 +703,13 @@ function logCall(duration, command, args) { loggedCalls.splice(0, loggedCalls.length - PREVERVED_HISTORY_CALLS, { time: new Date(), duration: 0, - command: '... history stripped ...', + command: '... history stripped ...' }); } loggedCalls.push({ duration, command: [command, ...args].join(' '), - time: new Date(), + time: new Date() }); } @@ -810,171 +731,104 @@ function logError(...args) { * * IMPORTANT: The exit event does NOT mean that all stdout and stderr events have been received. */ -function createProcessStream( - type: 'spawn' | 'fork' = 'spawn', - commandOrModulePath: string, - args?: Array = [], - options?: CreateProcessStreamOptions = {}, -): Observable { +function createProcessStream(type = 'spawn', commandOrModulePath, args = [], options = {}) { const inputOption = options.input; let input; if (inputOption != null) { - input = - typeof inputOption === 'string' - ? Observable.of(inputOption) - : inputOption; + input = typeof inputOption === 'string' ? _rxjsBundlesRxMinJs.Observable.of(inputOption) : inputOption; } - return observableFromSubscribeFunction(whenShellEnvironmentLoaded) - .take(1) - .switchMap(() => { - const {dontLogInNuclide, killTreeWhenDone, timeout} = options; - // flowlint-next-line sketchy-null-number:off - const enforceTimeout = timeout - ? x => - // TODO: Use `timeoutWith()` when we upgrade to an RxJS that has it. - timeoutWith( - x, - timeout, - Observable.throw(new ProcessTimeoutError(timeout, proc)), - ) - : x => x; - const proc = child_process[type]( - nuclideUri.expandHomeDir(commandOrModulePath), - args, - // $FlowFixMe: child_process$spawnOpts and child_process$forkOpts have incompatable stdio types. - {...options}, - ); - - // Don't let Node throw stream errors and crash the process. Note that we never dispose of - // this because stream errors can still occur after the user unsubscribes from our process - // observable. That's okay; when the streams close, the listeners will be removed. - preventStreamsFromThrowing(proc); - - // If we were to connect the error handler as part of the returned observable, unsubscribing - // would cause it to be removed. That would leave no attached error handler, so node would - // throw, triggering Atom's uncaught exception handler. - const errors = Observable.fromEvent(proc, 'error') - .flatMap(Observable.throw) - .publish(); - errors.connect(); - - const exitEvents = Observable.fromEvent( - proc, - 'exit', - (exitCode: ?number, signal: ?string) => ({ - kind: 'exit', - exitCode, - signal, - }), - ) - .filter(isRealExit) - .take(1); - - if (dontLogInNuclide !== true) { - // Log the completion of the process. Note that we intentionally don't merge this with the - // returned observable because we don't want to cancel the side-effect when the user - // unsubscribes or when the process exits ("close" events come after "exit" events). - const now = performanceNow(); - Observable.fromEvent(proc, 'close') - .do(() => { - logCall( - Math.round(performanceNow() - now), - commandOrModulePath, - args, - ); - }) - .subscribe(); - } + return (0, (_event || _load_event()).observableFromSubscribeFunction)(whenShellEnvironmentLoaded).take(1).switchMap(() => { + const { dontLogInNuclide, killTreeWhenDone, timeout } = options; + // flowlint-next-line sketchy-null-number:off + const enforceTimeout = timeout ? x => + // TODO: Use `timeoutWith()` when we upgrade to an RxJS that has it. + timeoutWith(x, timeout, _rxjsBundlesRxMinJs.Observable.throw(new ProcessTimeoutError(timeout, proc))) : x => x; + const proc = _child_process.default[type]((_nuclideUri || _load_nuclideUri()).default.expandHomeDir(commandOrModulePath), args, + // $FlowFixMe: child_process$spawnOpts and child_process$forkOpts have incompatable stdio types. + Object.assign({}, options)); + + // Don't let Node throw stream errors and crash the process. Note that we never dispose of + // this because stream errors can still occur after the user unsubscribes from our process + // observable. That's okay; when the streams close, the listeners will be removed. + preventStreamsFromThrowing(proc); + + // If we were to connect the error handler as part of the returned observable, unsubscribing + // would cause it to be removed. That would leave no attached error handler, so node would + // throw, triggering Atom's uncaught exception handler. + const errors = _rxjsBundlesRxMinJs.Observable.fromEvent(proc, 'error').flatMap(_rxjsBundlesRxMinJs.Observable.throw).publish(); + errors.connect(); + + const exitEvents = _rxjsBundlesRxMinJs.Observable.fromEvent(proc, 'exit', (exitCode, signal) => ({ + kind: 'exit', + exitCode, + signal + })).filter(isRealExit).take(1); + + if (dontLogInNuclide !== true) { + // Log the completion of the process. Note that we intentionally don't merge this with the + // returned observable because we don't want to cancel the side-effect when the user + // unsubscribes or when the process exits ("close" events come after "exit" events). + const now = (0, (_performanceNow || _load_performanceNow()).default)(); + _rxjsBundlesRxMinJs.Observable.fromEvent(proc, 'close').do(() => { + logCall(Math.round((0, (_performanceNow || _load_performanceNow()).default)() - now), commandOrModulePath, args); + }).subscribe(); + } - let finished = false; - return enforceTimeout( - Observable.using( - // Log stream errors, but only for as long as you're subscribed to the process observable. - () => logStreamErrors(proc, commandOrModulePath, args, options), - () => - Observable.merge( - // Node [delays the emission of process errors][1] by a tick in order to give - // consumers a chance to subscribe to the error event. This means that our observable - // would normally emit the process and then, a tick later, error. However, it's more - // convenient to never emit the process if there was an error. Although observables - // don't require the error to be delayed at all, the underlying event emitter - // abstraction does, so we'll just roll with that and use `pid == null` as a signal - // that an error is forthcoming. - // - // [1]: https://github.com/nodejs/node/blob/v7.10.0/lib/internal/child_process.js#L301 - proc.pid == null ? Observable.empty() : Observable.of(proc), - Observable.never(), // Don't complete until we say so! - ), - ) - .takeUntil(errors) - .takeUntil(exitEvents) - .merge( - // Write any input to stdin. This is just for the side-effect. We merge it here to - // ensure that writing to the stdin stream happens after our event listeners are added. - input == null - ? Observable.empty() - : input - .do({ - next: str => { - proc.stdin.write(str); - }, - complete: () => { - proc.stdin.end(); - }, - }) - .ignoreElements(), - ) - .do({ - error: () => { - finished = true; - }, - complete: () => { - finished = true; - }, - }), - ) - .catch(err => { - // Since this utility errors *before* emitting the process, add the process to the error - // so that users can get whatever info they need off of it. - if (err instanceof Error && err.name === 'Error' && 'errno' in err) { - throw new ProcessSystemError(err, proc); - } - throw err; - }) - .finally(() => { - // flowlint-next-line sketchy-null-mixed:off - if (!proc.wasKilled && !finished) { - killProcess(proc, Boolean(killTreeWhenDone)); - } - }); + let finished = false; + return enforceTimeout(_rxjsBundlesRxMinJs.Observable.using( + // Log stream errors, but only for as long as you're subscribed to the process observable. + () => logStreamErrors(proc, commandOrModulePath, args, options), () => _rxjsBundlesRxMinJs.Observable.merge( + // Node [delays the emission of process errors][1] by a tick in order to give + // consumers a chance to subscribe to the error event. This means that our observable + // would normally emit the process and then, a tick later, error. However, it's more + // convenient to never emit the process if there was an error. Although observables + // don't require the error to be delayed at all, the underlying event emitter + // abstraction does, so we'll just roll with that and use `pid == null` as a signal + // that an error is forthcoming. + // + // [1]: https://github.com/nodejs/node/blob/v7.10.0/lib/internal/child_process.js#L301 + proc.pid == null ? _rxjsBundlesRxMinJs.Observable.empty() : _rxjsBundlesRxMinJs.Observable.of(proc), _rxjsBundlesRxMinJs.Observable.never())).takeUntil(errors).takeUntil(exitEvents).merge( + // Write any input to stdin. This is just for the side-effect. We merge it here to + // ensure that writing to the stdin stream happens after our event listeners are added. + input == null ? _rxjsBundlesRxMinJs.Observable.empty() : input.do({ + next: str => { + proc.stdin.write(str); + }, + complete: () => { + proc.stdin.end(); + } + }).ignoreElements()).do({ + error: () => { + finished = true; + }, + complete: () => { + finished = true; + } + })).catch(err => { + // Since this utility errors *before* emitting the process, add the process to the error + // so that users can get whatever info they need off of it. + if (err instanceof Error && err.name === 'Error' && 'errno' in err) { + throw new ProcessSystemError(err, proc); + } + throw err; + }).finally(() => { + // flowlint-next-line sketchy-null-mixed:off + if (!proc.wasKilled && !finished) { + killProcess(proc, Boolean(killTreeWhenDone)); + } }); + }); } -function isRealExit(event: {exitCode: ?number, signal: ?string}): boolean { +function isRealExit(event) { // An exit signal from SIGUSR1 doesn't actually exit the process, so skip that. return event.signal !== 'SIGUSR1'; } -async function _killProcess( - proc: child_process$ChildProcess & {wasKilled?: boolean}, - killTree: boolean, -): Promise { - proc.wasKilled = true; - if (!killTree) { - proc.kill(); - return; - } - if (/^win/.test(process.platform)) { - await killWindowsProcessTree(proc.pid); - } else { - await killUnixProcessTree(proc); - } -} - -function killWindowsProcessTree(pid: number): Promise { +function killWindowsProcessTree(pid) { return new Promise((resolve, reject) => { - child_process.exec(`taskkill /pid ${pid} /T /F`, error => { + _child_process.default.exec(`taskkill /pid ${pid} /T /F`, error => { if (error == null) { reject(error); } else { @@ -984,33 +838,20 @@ function killWindowsProcessTree(pid: number): Promise { }); } -export async function killUnixProcessTree( - proc: child_process$ChildProcess, -): Promise { - const descendants = await getDescendantsOfProcess(proc.pid); - // Kill the processes, starting with those of greatest depth. - for (const info of descendants.reverse()) { - killPid(info.pid); - } -} - -function isExitErrorDefault(exit: ProcessExitMessage): boolean { +function isExitErrorDefault(exit) { return exit.exitCode !== 0; } -function isWindowsPlatform(): boolean { - return /^win/.test(process.platform); +function isWindowsPlatform() { + return (/^win/.test(process.platform) + ); } -function limitBufferSize( - stream: Observable, - maxBuffer: ?number, - streamName: string, -): Observable { +function limitBufferSize(stream, maxBuffer, streamName) { if (maxBuffer == null) { return stream; } - return Observable.defer(() => { + return _rxjsBundlesRxMinJs.Observable.defer(() => { let totalSize = 0; return stream.do(data => { totalSize += data.length; @@ -1022,40 +863,18 @@ function limitBufferSize( } // TODO: Use `Observable::timeoutWith()` when we upgrade RxJS -function timeoutWith( - source: Observable, - time: number, - other: Observable, -): Observable { - return ( - source - .timeout(time) - // Technically we could catch other TimeoutErrors here. `Observable::timeoutWith()` won't have - // this problem. - .catch( - err => (err instanceof TimeoutError ? other : Observable.throw(err)), - ) - ); +function timeoutWith(source, time, other) { + return source.timeout(time) + // Technically we could catch other TimeoutErrors here. `Observable::timeoutWith()` won't have + // this problem. + .catch(err => err instanceof _rxjsBundlesRxMinJs.TimeoutError ? other : _rxjsBundlesRxMinJs.Observable.throw(err)); } /** * Get an observable of error events for a process's streams. Note that these are represented as * normal elements, not observable errors. */ -function getStreamErrorEvents( - proc: child_process$ChildProcess, -): Observable<[Error, string]> { - const streams = [ - ['stdin', proc.stdin], - ['stdout', proc.stdout], - ['stderr', proc.stderr], - ]; - return Observable.merge( - ...streams.map( - ([name, stream]) => - stream == null - ? Observable.empty() - : Observable.fromEvent(stream, 'error').map(err => [err, name]), - ), - ); -} +function getStreamErrorEvents(proc) { + const streams = [['stdin', proc.stdin], ['stdout', proc.stdout], ['stderr', proc.stderr]]; + return _rxjsBundlesRxMinJs.Observable.merge(...streams.map(([name, stream]) => stream == null ? _rxjsBundlesRxMinJs.Observable.empty() : _rxjsBundlesRxMinJs.Observable.fromEvent(stream, 'error').map(err => [err, name]))); +} \ No newline at end of file diff --git a/modules/nuclide-commons/promise.js b/modules/nuclide-commons/promise.js index 0bff0c14..7fd82d8a 100644 --- a/modules/nuclide-commons/promise.js +++ b/modules/nuclide-commons/promise.js @@ -1,25 +1,254 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PromiseWithState = exports.asyncSome = exports.asyncObjFilter = exports.asyncFilter = exports.Deferred = exports.retryLimit = exports.TimedOutError = exports.triggerAfterWait = exports.RequestSerializer = undefined; + +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + /** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * Executes a provided callback only if a promise takes longer than + * `milliSeconds` milliseconds to resolve. * - * @flow - * @format + * @param `promise` the promise to wait on. + * @param `milliSeconds` max amount of time that `promise` can take to resolve + * before timeoutFn is fired. + * @param `timeoutFn` the function to execute when a promise takes longer than + * `milliSeconds` ms to resolve. + * @param `cleanupFn` the cleanup function to execute after the promise resolves. + */ +let triggerAfterWait = exports.triggerAfterWait = (() => { + var _ref = (0, _asyncToGenerator.default)(function* (promise, milliSeconds, timeoutFn, cleanupFn) { + const timeout = setTimeout(timeoutFn, milliSeconds); + try { + return yield promise; + } finally { + clearTimeout(timeout); + if (cleanupFn) { + cleanupFn(); + } + } + }); + + return function triggerAfterWait(_x, _x2, _x3, _x4) { + return _ref.apply(this, arguments); + }; +})(); + +/** + * Thrown by `timeoutPromise` if the timer fires before the promise resolves/rejects. */ -import invariant from 'assert'; -type RunReturn = - | { - status: 'success', - result: T, +/** + * Call an async function repeatedly with a maximum number of trials limit, + * until a valid result that's defined by a validation function. + * A failed call can result from an async thrown exception, or invalid result. + * + * @param `retryFunction` the async logic that's wanted to be retried. + * @param `validationFunction` the validation function that decides whether a response is valid. + * @param `maximumTries` the number of times the `retryFunction` can fail to get a valid + * response before the `retryLimit` is terminated reporting an error. + * @param `retryIntervalMs` optional, the number of milliseconds to wait between trials, if wanted. + * + * If an exception is encountered on the last trial, the exception is thrown. + * If no valid response is found, an exception is thrown. + */ +let retryLimit = exports.retryLimit = (() => { + var _ref2 = (0, _asyncToGenerator.default)(function* (retryFunction, validationFunction, maximumTries, retryIntervalMs = 0) { + let result = null; + let tries = 0; + let lastError = null; + while (tries === 0 || tries < maximumTries) { + try { + // eslint-disable-next-line no-await-in-loop + result = yield retryFunction(); + lastError = null; + if (validationFunction(result)) { + return result; + } + } catch (error) { + lastError = error; + result = null; + } + + if (++tries < maximumTries && retryIntervalMs !== 0) { + // eslint-disable-next-line no-await-in-loop + yield sleep(retryIntervalMs); + } } - | { - status: 'outdated', - }; + if (lastError != null) { + throw lastError; + } else if (tries === maximumTries) { + throw new Error('No valid response found!'); + } else { + return result; + } + }); + + return function retryLimit(_x5, _x6, _x7) { + return _ref2.apply(this, arguments); + }; +})(); + +/** + * Limits async function execution parallelism to only one at a time. + * Hence, if a call is already running, it will wait for it to finish, + * then start the next async execution, but if called again while not finished, + * it will return the scheduled execution promise. + * + * Sample Usage: + * ``` + * let i = 1; + * const oneExecAtATime = oneParallelAsyncCall(() => { + * return next Promise((resolve, reject) => { + * setTimeout(200, () => resolve(i++)); + * }); + * }); + * + * const result1Promise = oneExecAtATime(); // Start an async, and resolve to 1 in 200 ms. + * const result2Promise = oneExecAtATime(); // Schedule the next async, and resolve to 2 in 400 ms. + * const result3Promise = oneExecAtATime(); // Reuse scheduled promise and resolve to 2 in 400 ms. + * ``` + */ + + +/** + * `filter` Promise utility that allows filtering an array with an async Promise function. + * It's an alternative to `Array.prototype.filter` that accepts an async function. + * You can optionally configure a limit to set the maximum number of async operations at a time. + * + * Previously, with the `Promise.all` primitive, we can't set the parallelism limit and we have to + * `filter`, so, we replace the old `filter` code: + * var existingFilePaths = []; + * await Promise.all(filePaths.map(async (filePath) => { + * if (await fsPromise.exists(filePath)) { + * existingFilePaths.push(filePath); + * } + * })); + * with limit 5 parallel filesystem operations at a time: + * var existingFilePaths = await asyncFilter(filePaths, fsPromise.exists, 5); + * + * @param array the array of items for `filter`ing. + * @param filterFunction the async `filter` function that returns a Promise that resolves to a + * boolean. + * @param limit the configurable number of parallel async operations. + */ +let asyncFilter = exports.asyncFilter = (() => { + var _ref5 = (0, _asyncToGenerator.default)(function* (array, filterFunction, limit) { + const filteredList = []; + // flowlint-next-line sketchy-null-number:off + yield asyncLimit(array, limit || array.length, (() => { + var _ref6 = (0, _asyncToGenerator.default)(function* (item) { + if (yield filterFunction(item)) { + filteredList.push(item); + } + }); + + return function (_x12) { + return _ref6.apply(this, arguments); + }; + })()); + return filteredList; + }); + + return function asyncFilter(_x9, _x10, _x11) { + return _ref5.apply(this, arguments); + }; +})(); + +let asyncObjFilter = exports.asyncObjFilter = (() => { + var _ref7 = (0, _asyncToGenerator.default)(function* (obj, filterFunction, limit) { + const keys = Object.keys(obj); + const filteredObj = {}; + // flowlint-next-line sketchy-null-number:off + yield asyncLimit(keys, limit || keys.length, (() => { + var _ref8 = (0, _asyncToGenerator.default)(function* (key) { + const item = obj[key]; + if (yield filterFunction(item, key)) { + filteredObj[key] = item; + } + }); + + return function (_x16) { + return _ref8.apply(this, arguments); + }; + })()); + return filteredObj; + }); + + return function asyncObjFilter(_x13, _x14, _x15) { + return _ref7.apply(this, arguments); + }; +})(); + +/** + * `some` Promise utility that allows `some` an array with an async Promise some function. + * It's an alternative to `Array.prototype.some` that accepts an async some function. + * You can optionally configure a limit to set the maximum number of async operations at a time. + * + * Previously, with the Promise.all primitive, we can't set the parallelism limit and we have to + * `some`, so, we replace the old `some` code: + * var someFileExist = false; + * await Promise.all(filePaths.map(async (filePath) => { + * if (await fsPromise.exists(filePath)) { + * someFileExist = true; + * } + * })); + * with limit 5 parallel filesystem operations at a time: + * var someFileExist = await asyncSome(filePaths, fsPromise.exists, 5); + * + * @param array the array of items for `some`ing. + * @param someFunction the async `some` function that returns a Promise that resolves to a + * boolean. + * @param limit the configurable number of parallel async operations. + */ + + +let asyncSome = exports.asyncSome = (() => { + var _ref9 = (0, _asyncToGenerator.default)(function* (array, someFunction, limit) { + let resolved = false; + // flowlint-next-line sketchy-null-number:off + yield asyncLimit(array, limit || array.length, (() => { + var _ref10 = (0, _asyncToGenerator.default)(function* (item) { + if (resolved) { + // We don't need to call the someFunction anymore or wait any longer. + return; + } + if (yield someFunction(item)) { + resolved = true; + } + }); + + return function (_x20) { + return _ref10.apply(this, arguments); + }; + })()); + return resolved; + }); + + return function asyncSome(_x17, _x18, _x19) { + return _ref9.apply(this, arguments); + }; +})(); + +/** + * Check if an object is Promise by testing if it has a `then` function property. + */ + + +exports.sleep = sleep; +exports.nextTick = nextTick; +exports.timeoutPromise = timeoutPromise; +exports.serializeAsyncCall = serializeAsyncCall; +exports.asyncFind = asyncFind; +exports.denodeify = denodeify; +exports.asyncLimit = asyncLimit; +exports.isPromise = isPromise; +exports.lastly = lastly; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Allows a caller to ensure that the results it receives from consecutive @@ -46,11 +275,19 @@ type RunReturn = * receive a 'success' status. If promise1 later resolved, the first callsite * would receive an 'outdated' status. */ -export class RequestSerializer { - _lastDispatchedOp: number; - _lastFinishedOp: number; - _latestPromise: Promise; - _waitResolve: Function; +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +class RequestSerializer { constructor() { this._lastDispatchedOp = 0; @@ -60,215 +297,109 @@ export class RequestSerializer { }); } - async run(promise: Promise): Promise> { - const thisOp = this._lastDispatchedOp + 1; - this._lastDispatchedOp = thisOp; - this._latestPromise = promise; - this._waitResolve(); - const result = await promise; - if (this._lastFinishedOp < thisOp) { - this._lastFinishedOp = thisOp; - return { - status: 'success', - result, - }; - } else { - return { - status: 'outdated', - }; - } + run(promise) { + var _this = this; + + return (0, _asyncToGenerator.default)(function* () { + const thisOp = _this._lastDispatchedOp + 1; + _this._lastDispatchedOp = thisOp; + _this._latestPromise = promise; + _this._waitResolve(); + const result = yield promise; + if (_this._lastFinishedOp < thisOp) { + _this._lastFinishedOp = thisOp; + return { + status: 'success', + result + }; + } else { + return { + status: 'outdated' + }; + } + })(); } /** * Returns a Promise that resolves to the last result of `run`, * as soon as there are no more outstanding `run` calls. */ - async waitForLatestResult(): Promise { - let lastPromise = null; - let result: any = null; - while (lastPromise !== this._latestPromise) { - lastPromise = this._latestPromise; - // Wait for the current last know promise to resolve, or a next run have started. - // eslint-disable-next-line no-await-in-loop - result = await new Promise((resolve, reject) => { - this._waitResolve = resolve; - this._latestPromise.then(resolve); - }); - } - return (result: T); + waitForLatestResult() { + var _this2 = this; + + return (0, _asyncToGenerator.default)(function* () { + let lastPromise = null; + let result = null; + while (lastPromise !== _this2._latestPromise) { + lastPromise = _this2._latestPromise; + // Wait for the current last know promise to resolve, or a next run have started. + // eslint-disable-next-line no-await-in-loop + result = yield new Promise(function (resolve, reject) { + _this2._waitResolve = resolve; + _this2._latestPromise.then(resolve); + }); + } + return result; + })(); } - isRunInProgress(): boolean { + isRunInProgress() { return this._lastDispatchedOp > this._lastFinishedOp; } } -/* - * Returns a promise that will resolve after `milliSeconds` milli seconds. - * this can be used to pause execution asynchronously. - * e.g. await sleep(1000), pauses the async flow execution for 1 second. - */ -export function sleep(milliSeconds: number): Promise { +exports.RequestSerializer = RequestSerializer; /* + * Returns a promise that will resolve after `milliSeconds` milli seconds. + * this can be used to pause execution asynchronously. + * e.g. await sleep(1000), pauses the async flow execution for 1 second. + */ + +function sleep(milliSeconds) { return new Promise(resolve => { setTimeout(resolve, milliSeconds); }); } -export function nextTick(): Promise { +function nextTick() { return new Promise(resolve => { process.nextTick(resolve); }); -} - -/** - * Executes a provided callback only if a promise takes longer than - * `milliSeconds` milliseconds to resolve. - * - * @param `promise` the promise to wait on. - * @param `milliSeconds` max amount of time that `promise` can take to resolve - * before timeoutFn is fired. - * @param `timeoutFn` the function to execute when a promise takes longer than - * `milliSeconds` ms to resolve. - * @param `cleanupFn` the cleanup function to execute after the promise resolves. - */ -export async function triggerAfterWait( - promise: Promise, - milliSeconds: number, - timeoutFn: () => void, - cleanupFn?: () => void, -): Promise { - const timeout = setTimeout(timeoutFn, milliSeconds); - try { - return await promise; - } finally { - clearTimeout(timeout); - if (cleanupFn) { - cleanupFn(); - } - } -} - -/** - * Thrown by `timeoutPromise` if the timer fires before the promise resolves/rejects. - */ -export class TimedOutError extends Error { - timeout: number; - constructor(milliseconds: number) { +}class TimedOutError extends Error { + constructor(milliseconds) { super(`Timed out after ${String(milliseconds)} ms`); this.timeout = milliseconds; } } -/** - * Returns a Promise that resolves to the same value as the given promise, or rejects with - * `TimedOutError` if it takes longer than `milliseconds` milliseconds. - */ -export function timeoutPromise( - promise: Promise, - milliseconds: number, -): Promise { +exports.TimedOutError = TimedOutError; /** + * Returns a Promise that resolves to the same value as the given promise, or rejects with + * `TimedOutError` if it takes longer than `milliseconds` milliseconds. + */ + +function timeoutPromise(promise, milliseconds) { return new Promise((resolve, reject) => { let timeout = setTimeout(() => { timeout = null; reject(new TimedOutError(milliseconds)); }, milliseconds); - promise - .then(value => { - if (timeout != null) { - clearTimeout(timeout); - } - resolve(value); - }) - .catch(value => { - if (timeout != null) { - clearTimeout(timeout); - } - reject(value); - }); - }); -} - -/** - * Call an async function repeatedly with a maximum number of trials limit, - * until a valid result that's defined by a validation function. - * A failed call can result from an async thrown exception, or invalid result. - * - * @param `retryFunction` the async logic that's wanted to be retried. - * @param `validationFunction` the validation function that decides whether a response is valid. - * @param `maximumTries` the number of times the `retryFunction` can fail to get a valid - * response before the `retryLimit` is terminated reporting an error. - * @param `retryIntervalMs` optional, the number of milliseconds to wait between trials, if wanted. - * - * If an exception is encountered on the last trial, the exception is thrown. - * If no valid response is found, an exception is thrown. - */ -export async function retryLimit( - retryFunction: () => Promise, - validationFunction: (result: T) => boolean, - maximumTries: number, - retryIntervalMs?: number = 0, -): Promise { - let result = null; - let tries = 0; - let lastError = null; - while (tries === 0 || tries < maximumTries) { - try { - // eslint-disable-next-line no-await-in-loop - result = await retryFunction(); - lastError = null; - if (validationFunction(result)) { - return result; + promise.then(value => { + if (timeout != null) { + clearTimeout(timeout); } - } catch (error) { - lastError = error; - result = null; - } - - if (++tries < maximumTries && retryIntervalMs !== 0) { - // eslint-disable-next-line no-await-in-loop - await sleep(retryIntervalMs); - } - } - if (lastError != null) { - throw lastError; - } else if (tries === maximumTries) { - throw new Error('No valid response found!'); - } else { - return ((result: any): T); - } -} - -/** - * Limits async function execution parallelism to only one at a time. - * Hence, if a call is already running, it will wait for it to finish, - * then start the next async execution, but if called again while not finished, - * it will return the scheduled execution promise. - * - * Sample Usage: - * ``` - * let i = 1; - * const oneExecAtATime = oneParallelAsyncCall(() => { - * return next Promise((resolve, reject) => { - * setTimeout(200, () => resolve(i++)); - * }); - * }); - * - * const result1Promise = oneExecAtATime(); // Start an async, and resolve to 1 in 200 ms. - * const result2Promise = oneExecAtATime(); // Schedule the next async, and resolve to 2 in 400 ms. - * const result3Promise = oneExecAtATime(); // Reuse scheduled promise and resolve to 2 in 400 ms. - * ``` - */ -export function serializeAsyncCall( - asyncFun: () => Promise, -): () => Promise { + resolve(value); + }).catch(value => { + if (timeout != null) { + clearTimeout(timeout); + } + reject(value); + }); + }); +}function serializeAsyncCall(asyncFun) { let scheduledCall = null; let pendingCall = null; const startAsyncCall = () => { const resultPromise = asyncFun(); - pendingCall = resultPromise.then( - () => (pendingCall = null), - () => (pendingCall = null), - ); + pendingCall = resultPromise.then(() => pendingCall = null, () => pendingCall = null); return resultPromise; }; const callNext = () => { @@ -277,7 +408,10 @@ export function serializeAsyncCall( }; const scheduleNextCall = () => { if (scheduledCall == null) { - invariant(pendingCall, 'pendingCall must not be null!'); + if (!pendingCall) { + throw new Error('pendingCall must not be null!'); + } + scheduledCall = pendingCall.then(callNext, callNext); } return scheduledCall; @@ -298,10 +432,7 @@ export function serializeAsyncCall( * IMPORTANT: This should almost never be used!! Instead, use the Promise constructor. See * */ -export class Deferred { - promise: Promise; - resolve: (value: T) => void; - reject: (error: Error) => void; +class Deferred { constructor() { this.promise = new Promise((resolve, reject) => { @@ -311,29 +442,26 @@ export class Deferred { } } -/** - * Returns a value derived asynchronously from an element in the items array. - * The test function is applied sequentially to each element in items until - * one returns a Promise that resolves to a non-null value. When this happens, - * the Promise returned by this method will resolve to that non-null value. If - * no such Promise is produced, then the Promise returned by this function - * will resolve to null. - * - * @param items Array of elements that will be passed to test, one at a time. - * @param test Will be called with each item and must return either: - * (1) A "thenable" (i.e, a Promise or promise-like object) that resolves - * to a derived value (that will be returned) or null. - * (2) null. - * In both cases where null is returned, test will be applied to the next - * item in the array. - * @param thisArg Receiver that will be used when test is called. - * @return Promise that resolves to an asynchronously derived value or null. - */ -export function asyncFind( - items_: Array, - test: (t: T) => ?Promise, - thisArg?: mixed, -): Promise { +exports.Deferred = Deferred; /** + * Returns a value derived asynchronously from an element in the items array. + * The test function is applied sequentially to each element in items until + * one returns a Promise that resolves to a non-null value. When this happens, + * the Promise returned by this method will resolve to that non-null value. If + * no such Promise is produced, then the Promise returned by this function + * will resolve to null. + * + * @param items Array of elements that will be passed to test, one at a time. + * @param test Will be called with each item and must return either: + * (1) A "thenable" (i.e, a Promise or promise-like object) that resolves + * to a derived value (that will be returned) or null. + * (2) null. + * In both cases where null is returned, test will be applied to the next + * item in the array. + * @param thisArg Receiver that will be used when test is called. + * @return Promise that resolves to an asynchronously derived value or null. + */ + +function asyncFind(items_, test, thisArg) { let items = items_; return new Promise((resolve, reject) => { // Create a local copy of items to defend against the caller modifying the @@ -341,29 +469,33 @@ export function asyncFind( items = items.slice(); const numItems = items.length; - const next = async function(index) { - if (index === numItems) { - resolve(null); - return; - } + const next = (() => { + var _ref3 = (0, _asyncToGenerator.default)(function* (index) { + if (index === numItems) { + resolve(null); + return; + } - const item = items[index]; - const result = await test.call(thisArg, item); - if (result != null) { - resolve(result); - } else { - next(index + 1); - } - }; + const item = items[index]; + const result = yield test.call(thisArg, item); + if (result != null) { + resolve(result); + } else { + next(index + 1); + } + }); + + return function next(_x8) { + return _ref3.apply(this, arguments); + }; + })(); next(0); }); } -export function denodeify( - f: (...args: Array) => any, -): (...args: Array) => Promise { - return function(...args: Array) { +function denodeify(f) { + return function (...args) { return new Promise((resolve, reject) => { function callback(error, result) { if (error) { @@ -393,162 +525,56 @@ export function denodeify( * @param limit the configurable number of parallel async operations. * @param mappingFunction the async Promise function that could return a useful result. */ -export function asyncLimit( - array: Array, - limit: number, - mappingFunction: (item: T) => Promise, -): Promise> { - const result: Array = new Array(array.length); +function asyncLimit(array, limit, mappingFunction) { + const result = new Array(array.length); let parallelPromises = 0; let index = 0; let parallelLimit = Math.min(limit, array.length) || 1; return new Promise((resolve, reject) => { - const runPromise = async () => { - if (index === array.length) { - if (parallelPromises === 0) { - resolve(result); + const runPromise = (() => { + var _ref4 = (0, _asyncToGenerator.default)(function* () { + if (index === array.length) { + if (parallelPromises === 0) { + resolve(result); + } + return; } - return; - } - ++parallelPromises; - const i = index++; - try { - result[i] = await mappingFunction(array[i]); - } catch (e) { - reject(e); - } - --parallelPromises; - runPromise(); - }; + ++parallelPromises; + const i = index++; + try { + result[i] = yield mappingFunction(array[i]); + } catch (e) { + reject(e); + } + --parallelPromises; + runPromise(); + }); + + return function runPromise() { + return _ref4.apply(this, arguments); + }; + })(); while (parallelLimit--) { runPromise(); } }); -} - -/** - * `filter` Promise utility that allows filtering an array with an async Promise function. - * It's an alternative to `Array.prototype.filter` that accepts an async function. - * You can optionally configure a limit to set the maximum number of async operations at a time. - * - * Previously, with the `Promise.all` primitive, we can't set the parallelism limit and we have to - * `filter`, so, we replace the old `filter` code: - * var existingFilePaths = []; - * await Promise.all(filePaths.map(async (filePath) => { - * if (await fsPromise.exists(filePath)) { - * existingFilePaths.push(filePath); - * } - * })); - * with limit 5 parallel filesystem operations at a time: - * var existingFilePaths = await asyncFilter(filePaths, fsPromise.exists, 5); - * - * @param array the array of items for `filter`ing. - * @param filterFunction the async `filter` function that returns a Promise that resolves to a - * boolean. - * @param limit the configurable number of parallel async operations. - */ -export async function asyncFilter( - array: Array, - filterFunction: (item: T) => Promise, - limit?: number, -): Promise> { - const filteredList = []; - // flowlint-next-line sketchy-null-number:off - await asyncLimit(array, limit || array.length, async (item: T) => { - if (await filterFunction(item)) { - filteredList.push(item); - } - }); - return filteredList; -} - -export async function asyncObjFilter( - obj: {[key: string]: T}, - filterFunction: (item: T, key: string) => Promise, - limit?: number, -): Promise<{[key: string]: T}> { - const keys = Object.keys(obj); - const filteredObj = {}; - // flowlint-next-line sketchy-null-number:off - await asyncLimit(keys, limit || keys.length, async (key: string) => { - const item = obj[key]; - if (await filterFunction(item, key)) { - filteredObj[key] = item; - } - }); - return filteredObj; -} - -/** - * `some` Promise utility that allows `some` an array with an async Promise some function. - * It's an alternative to `Array.prototype.some` that accepts an async some function. - * You can optionally configure a limit to set the maximum number of async operations at a time. - * - * Previously, with the Promise.all primitive, we can't set the parallelism limit and we have to - * `some`, so, we replace the old `some` code: - * var someFileExist = false; - * await Promise.all(filePaths.map(async (filePath) => { - * if (await fsPromise.exists(filePath)) { - * someFileExist = true; - * } - * })); - * with limit 5 parallel filesystem operations at a time: - * var someFileExist = await asyncSome(filePaths, fsPromise.exists, 5); - * - * @param array the array of items for `some`ing. - * @param someFunction the async `some` function that returns a Promise that resolves to a - * boolean. - * @param limit the configurable number of parallel async operations. - */ -export async function asyncSome( - array: Array, - someFunction: (item: T) => Promise, - limit?: number, -): Promise { - let resolved = false; - // flowlint-next-line sketchy-null-number:off - await asyncLimit(array, limit || array.length, async (item: T) => { - if (resolved) { - // We don't need to call the someFunction anymore or wait any longer. - return; - } - if (await someFunction(item)) { - resolved = true; - } - }); - return resolved; -} - -/** - * Check if an object is Promise by testing if it has a `then` function property. - */ -export function isPromise(object: any): boolean { - return ( - Boolean(object) && - typeof object === 'object' && - typeof object.then === 'function' - ); +}function isPromise(object) { + return Boolean(object) && typeof object === 'object' && typeof object.then === 'function'; } /** * We can't name a function 'finally', so use lastly instead. * fn() will be executed (and completed) after the provided promise resolves/rejects. */ -export function lastly( - promise: Promise, - fn: () => Promise | mixed, -): Promise { - return promise.then( - ret => { - return Promise.resolve(fn()).then(() => ret); - }, - err => { - return Promise.resolve(fn()).then(() => Promise.reject(err)); - }, - ); +function lastly(promise, fn) { + return promise.then(ret => { + return Promise.resolve(fn()).then(() => ret); + }, err => { + return Promise.resolve(fn()).then(() => Promise.reject(err)); + }); } /** @@ -556,34 +582,25 @@ export function lastly( * whether or not it has 'settled' (i.e. been fulfilled or rejected). * Here we provide a wrapper that provides that information. */ -export type PromiseState = - | {kind: 'pending'} - | {kind: 'fulfilled', value: T} - | {kind: 'rejected', error: any}; - -export class PromiseWithState { - _promise: Promise; - _state: PromiseState; - - constructor(promise: Promise) { - this._state = {kind: 'pending'}; - this._promise = promise.then( - value => { - this._state = {kind: 'fulfilled', value}; - return value; - }, - error => { - this._state = {kind: 'rejected', error}; - throw error; - }, - ); +class PromiseWithState { + + constructor(promise) { + this._state = { kind: 'pending' }; + this._promise = promise.then(value => { + this._state = { kind: 'fulfilled', value }; + return value; + }, error => { + this._state = { kind: 'rejected', error }; + throw error; + }); } - getPromise(): Promise { + getPromise() { return this._promise; } - getState(): PromiseState { + getState() { return this._state; } } +exports.PromiseWithState = PromiseWithState; \ No newline at end of file diff --git a/modules/nuclide-commons/range.js b/modules/nuclide-commons/range.js index 63dbe0eb..915e0fc7 100644 --- a/modules/nuclide-commons/range.js +++ b/modules/nuclide-commons/range.js @@ -1,3 +1,11 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.wordAtPositionFromBuffer = wordAtPositionFromBuffer; +exports.matchRegexEndingAt = matchRegexEndingAt; +exports.isPositionInRange = isPositionInRange; /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,25 +14,18 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -export function wordAtPositionFromBuffer( - buffer: atom$TextBuffer | simpleTextBuffer$TextBuffer, - position: atom$PointObject, - wordRegex: RegExp, -): ?{wordMatch: Array, range: atom$Range} { - const {row, column} = position; +function wordAtPositionFromBuffer(buffer, position, wordRegex) { + const { row, column } = position; const rowRange = buffer.rangeForRow(row); let matchData; // Extract the expression from the row text. buffer.scanInRange(wordRegex, rowRange, data => { - const {range} = data; - if ( - range.start.isLessThanOrEqual(position) && - range.end.isGreaterThan(position) - ) { + const { range } = data; + if (range.start.isLessThanOrEqual(position) && range.end.isGreaterThan(position)) { matchData = data; } // Stop the scan if the scanner has passed our position. @@ -35,7 +36,7 @@ export function wordAtPositionFromBuffer( if (matchData) { return { wordMatch: matchData.match, - range: matchData.range, + range: matchData.range }; } else { return null; @@ -45,21 +46,12 @@ export function wordAtPositionFromBuffer( // Matches a regex on the text of the line ending at endPosition. // regex should end with a '$'. // Useful for autocomplete. -export function matchRegexEndingAt( - buffer: atom$TextBuffer | simpleTextBuffer$TextBuffer, - endPosition: atom$PointObject, - regex: RegExp, -): ?string { +function matchRegexEndingAt(buffer, endPosition, regex) { const line = buffer.getTextInRange([[endPosition.row, 0], endPosition]); const match = regex.exec(line); return match == null ? null : match[0]; } -export function isPositionInRange( - position: atom$Point, - range: atom$Range | Array, -): boolean { - return Array.isArray(range) - ? range.some(r => r.containsPoint(position)) - : range.containsPoint(position); -} +function isPositionInRange(position, range) { + return Array.isArray(range) ? range.some(r => r.containsPoint(position)) : range.containsPoint(position); +} \ No newline at end of file diff --git a/modules/nuclide-commons/redux-observable.js b/modules/nuclide-commons/redux-observable.js index 0d321166..385493ce 100644 --- a/modules/nuclide-commons/redux-observable.js +++ b/modules/nuclide-commons/redux-observable.js @@ -1,14 +1,34 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ActionsObservable = undefined; +exports.combineEpics = combineEpics; +exports.createEpicMiddleware = createEpicMiddleware; + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +// This should be { type: readonly string } when we get readonly props. Because this is used with +// disjoint unions we can't use `string` here due to mutation concerns. Flow doesn't know that we +// aren't going to mutate the objects with a random string value so it can't allow us to pass a +// specific action type into something of type { type: string } +function combineEpics(...epics) { + return (actions, store, extra) => { + const streams = epics.map(epic => epic(actions, store, extra)); + return _rxjsBundlesRxMinJs.Observable.merge(...streams); + }; +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ // Derived from because their version // imports an Rx operator module and we use a bundle. Original license follows: @@ -35,46 +55,15 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -import {Observable, Subject} from 'rxjs'; - -// This should be { type: readonly string } when we get readonly props. Because this is used with -// disjoint unions we can't use `string` here due to mutation concerns. Flow doesn't know that we -// aren't going to mutate the objects with a random string value so it can't allow us to pass a -// specific action type into something of type { type: string } -type Action = {type: any}; -type Store = { - dispatch(action: T): void, - getState(): U, -}; -type Next = (action: T) => T; -export type Epic = ( - actions: ActionsObservable, - store: Store, - extra: E, -) => Observable; - -export function combineEpics( - ...epics: Array> -): Epic { - return (actions: ActionsObservable, store: Store, extra: E) => { - const streams: Array> = epics.map(epic => - epic(actions, store, extra), - ); - return Observable.merge(...streams); - }; -} - -export function createEpicMiddleware( - rootEpic?: Epic, -) { - const actions = new Subject(); +function createEpicMiddleware(rootEpic) { + const actions = new _rxjsBundlesRxMinJs.Subject(); const actionsObs = new ActionsObservable(actions); - return (store: Store) => (next: Next) => { + return store => next => { if (rootEpic != null) { rootEpic(actionsObs, store).subscribe(store.dispatch); } - return (action: T) => { + return action => { const result = next(action); actions.next(action); return result; @@ -82,22 +71,21 @@ export function createEpicMiddleware( }; } -export class ActionsObservable extends Observable { - operator: any; +class ActionsObservable extends _rxjsBundlesRxMinJs.Observable { - constructor(actionsSubject: Observable) { + constructor(actionsSubject) { super(); this.source = actionsSubject; } - lift(operator: any): Observable { + lift(operator) { const observable = new ActionsObservable(this); observable.operator = operator; return observable; } - ofType(...keys: Array): ActionsObservable { - const result = this.filter(({type}) => { + ofType(...keys) { + const result = this.filter(({ type }) => { const len = keys.length; if (len === 1) { return type === keys[0]; @@ -110,6 +98,7 @@ export class ActionsObservable extends Observable { } return false; }); - return ((result: any): ActionsObservable); + return result; } } +exports.ActionsObservable = ActionsObservable; \ No newline at end of file diff --git a/modules/nuclide-commons/spec/BatchProcessedQueue-spec.js b/modules/nuclide-commons/spec/BatchProcessedQueue-spec.js deleted file mode 100644 index df865a6f..00000000 --- a/modules/nuclide-commons/spec/BatchProcessedQueue-spec.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import BatchProcessedQueue from '../BatchProcessedQueue'; - -describe('analytics - BatchProcessedQueue', () => { - it('regular operation', () => { - const handler = jasmine.createSpy('handler'); - const queue = new BatchProcessedQueue(5000, handler); - - queue.add(1); - queue.add(2); - queue.add(3); - queue.add(4); - queue.add(5); - expect(handler).not.toHaveBeenCalled(); - - advanceClock(4999); - expect(handler).not.toHaveBeenCalled(); - advanceClock(1); - expect(handler).toHaveBeenCalledWith([1, 2, 3, 4, 5]); - - queue.add(42); - advanceClock(10000); - expect(handler).toHaveBeenCalledWith([42]); - }); -}); diff --git a/modules/nuclide-commons/spec/ConfigCache-spec.js b/modules/nuclide-commons/spec/ConfigCache-spec.js deleted file mode 100644 index d2a941c3..00000000 --- a/modules/nuclide-commons/spec/ConfigCache-spec.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import {ConfigCache} from '../ConfigCache'; -import nuclideUri from '../nuclideUri'; - -const CONFIG_FILE_NAME = '.test_nuclide_config_file'; -const CONFIG_FILE_NAME_2 = '.test_nuclide_config_file_2'; - -describe('ConfigCache', () => { - const noConfigFolder = nuclideUri.join(__dirname, 'fixtures'); - const rootFolder = nuclideUri.join(__dirname, 'fixtures/ConfigCache'); - const rootFile = nuclideUri.join(__dirname, 'fixtures/ConfigCache/file'); - const nestedFolder = nuclideUri.join( - __dirname, - 'fixtures/ConfigCache/testFolder', - ); - const nestedFolder2 = nuclideUri.join( - __dirname, - 'fixtures/ConfigCache/testFolder2', - ); - const nestedFile = nuclideUri.join( - __dirname, - 'fixtures/ConfigCache/testFolder/file', - ); - - it('finds the right config dir', () => { - waitsForPromise(async () => { - const cache = new ConfigCache([CONFIG_FILE_NAME]); - - expect(await cache.getConfigDir(noConfigFolder)).toBe(null); - expect(await cache.getConfigDir(rootFolder)).toBe(rootFolder); - expect(await cache.getConfigDir(rootFile)).toBe(rootFolder); - expect(await cache.getConfigDir(nestedFolder)).toBe(rootFolder); - expect(await cache.getConfigDir(nestedFile)).toBe(rootFolder); - }); - }); - - it('prefers closer matches with multiple config files', () => { - waitsForPromise(async () => { - const cache = new ConfigCache([CONFIG_FILE_NAME, CONFIG_FILE_NAME_2]); - - expect(await cache.getConfigDir(rootFolder)).toBe(rootFolder); - expect(await cache.getConfigDir(nestedFolder2)).toBe(nestedFolder2); - }); - }); -}); diff --git a/modules/nuclide-commons/spec/Hasher-spec.js b/modules/nuclide-commons/spec/Hasher-spec.js deleted file mode 100644 index 8135f1c1..00000000 --- a/modules/nuclide-commons/spec/Hasher-spec.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import Hasher from '../Hasher'; - -describe('Hasher', () => { - it('creates a new hash for each object', () => { - const a = {}; - const b = {}; - const hasher = new Hasher(); - expect(hasher.getHash(a)).not.toBe(hasher.getHash(b)); - }); - - it('returns the same hash for the same object', () => { - const a = {}; - const hasher = new Hasher(); - expect(hasher.getHash(a)).toBe(hasher.getHash(a)); - }); - - it('works for numbers', () => { - const hasher = new Hasher(); - expect(hasher.getHash(1)).toBe(hasher.getHash(1)); - expect(hasher.getHash(1)).not.toBe(hasher.getHash(2)); - }); - - it('works for booleans', () => { - const hasher = new Hasher(); - expect(hasher.getHash(true)).toBe(hasher.getHash(true)); - expect(hasher.getHash(true)).not.toBe(hasher.getHash(false)); - }); - - it('works for strings', () => { - const hasher = new Hasher(); - expect(hasher.getHash('a')).toBe(hasher.getHash('a')); - expect(hasher.getHash('a')).not.toBe(hasher.getHash('b')); - }); -}); diff --git a/modules/nuclide-commons/spec/Model-spec.js b/modules/nuclide-commons/spec/Model-spec.js deleted file mode 100644 index e7ae46a9..00000000 --- a/modules/nuclide-commons/spec/Model-spec.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import Model from '../Model'; - -describe('Model', () => { - it('setStates state when setState is called', () => { - const model = new Model({count: 0, other: true}); - model.setState({count: 5}); - expect(model.state.count).toBe(5); - }); - - it('only changes the provided values when setState is called', () => { - const model = new Model({count: 0, other: true}); - model.setState({count: 5}); - expect(model.state.other).toBe(true); - }); - - it('can be converted to an observable', () => { - waitsForPromise(async () => { - const model = new Model({count: 0, other: true}); - const states = model.toObservable().take(2).toArray().toPromise(); - model.setState({count: 5}); - expect(await states).toEqual([ - {count: 0, other: true}, - {count: 5, other: true}, - ]); - }); - }); -}); diff --git a/modules/nuclide-commons/spec/UniversalDisposable-spec.js b/modules/nuclide-commons/spec/UniversalDisposable-spec.js deleted file mode 100644 index f3f0744f..00000000 --- a/modules/nuclide-commons/spec/UniversalDisposable-spec.js +++ /dev/null @@ -1,200 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import UniversalDisposable from '../UniversalDisposable'; - -describe('UniversalDisposable', () => { - it('disposes of the Disposable arguments', () => { - const dispose = jasmine.createSpy('dispose'); - const universal = new UniversalDisposable({dispose}); - - expect(dispose.wasCalled).toBe(false); - universal.dispose(); - expect(dispose.callCount).toBe(1); - }); - - it('throws if you add after disposing', () => { - const universal = new UniversalDisposable(); - universal.dispose(); - expect(() => { - universal.add(() => {}); - }).toThrow('Cannot add to an already disposed UniversalDisposable!'); - }); - - it('calls function arguments', () => { - const foo = jasmine.createSpy('foo'); - const universal = new UniversalDisposable(foo); - - expect(foo.wasCalled).toBe(false); - universal.dispose(); - expect(foo.callCount).toBe(1); - }); - - it('calls unsubscribe arguments', () => { - const unsubscribe = jasmine.createSpy('unsubscribe'); - const universal = new UniversalDisposable(unsubscribe); - - expect(unsubscribe.wasCalled).toBe(false); - universal.dispose(); - expect(unsubscribe.callCount).toBe(1); - }); - - it('supports creation with mixed teardowns', () => { - const dispose = jasmine.createSpy('dispose'); - const unsubscribe = jasmine.createSpy('unsubscribe'); - const foo = jasmine.createSpy('foo'); - const universal = new UniversalDisposable({dispose}, {unsubscribe}, foo); - - expect(dispose.wasCalled).toBe(false); - expect(unsubscribe.wasCalled).toBe(false); - expect(foo.wasCalled).toBe(false); - universal.dispose(); - expect(dispose.callCount).toBe(1); - expect(unsubscribe.callCount).toBe(1); - expect(foo.callCount).toBe(1); - }); - - it('supports adding mixed teardowns', () => { - const dispose = jasmine.createSpy('dispose'); - const unsubscribe = jasmine.createSpy('unsubscribe'); - const foo = jasmine.createSpy('foo'); - const universal = new UniversalDisposable(); - universal.add({dispose}, {unsubscribe}, foo); - - expect(dispose.wasCalled).toBe(false); - expect(unsubscribe.wasCalled).toBe(false); - expect(foo.wasCalled).toBe(false); - universal.dispose(); - expect(dispose.callCount).toBe(1); - expect(unsubscribe.callCount).toBe(1); - expect(foo.callCount).toBe(1); - }); - - it('supports unsubscribe as well', () => { - const dispose = jasmine.createSpy('dispose'); - const unsubscribe = jasmine.createSpy('unsubscribe'); - const foo = jasmine.createSpy('foo'); - const universal = new UniversalDisposable({dispose}, {unsubscribe}, foo); - - expect(dispose.wasCalled).toBe(false); - expect(unsubscribe.wasCalled).toBe(false); - expect(foo.wasCalled).toBe(false); - universal.unsubscribe(); - expect(dispose.callCount).toBe(1); - expect(unsubscribe.callCount).toBe(1); - expect(foo.callCount).toBe(1); - }); - - it('multiple dispose/unsubscribe calls have no effect', () => { - const dispose = jasmine.createSpy('dispose'); - const unsubscribe = jasmine.createSpy('unsubscribe'); - const foo = jasmine.createSpy('foo'); - const universal = new UniversalDisposable({dispose}, {unsubscribe}, foo); - - expect(dispose.wasCalled).toBe(false); - expect(unsubscribe.wasCalled).toBe(false); - expect(foo.wasCalled).toBe(false); - universal.unsubscribe(); - universal.dispose(); - universal.unsubscribe(); - universal.dispose(); - expect(dispose.callCount).toBe(1); - expect(unsubscribe.callCount).toBe(1); - expect(foo.callCount).toBe(1); - }); - - it('supports removal of the teardowns', () => { - const dispose = {dispose: jasmine.createSpy('dispose')}; - const unsubscribe = {unsubscribe: jasmine.createSpy('unsubscribe')}; - const foo = jasmine.createSpy('foo'); - const universal = new UniversalDisposable(dispose, unsubscribe, foo); - - universal.remove(unsubscribe); - universal.remove(dispose); - universal.remove(foo); - - universal.dispose(); - - expect(dispose.dispose.wasCalled).toBe(false); - expect(unsubscribe.unsubscribe.wasCalled).toBe(false); - expect(foo.wasCalled).toBe(false); - }); - - it('can clear all of the teardowns', () => { - const dispose = {dispose: jasmine.createSpy('dispose')}; - const unsubscribe = {unsubscribe: jasmine.createSpy('unsubscribe')}; - const foo = jasmine.createSpy('foo'); - const universal = new UniversalDisposable(dispose, unsubscribe, foo); - - universal.clear(); - - universal.dispose(); - - expect(dispose.dispose.wasCalled).toBe(false); - expect(unsubscribe.unsubscribe.wasCalled).toBe(false); - expect(foo.wasCalled).toBe(false); - }); - - it('maintains implicit order of the teardowns', () => { - const ids = []; - - const foo1 = () => ids.push(1); - const foo2 = () => ids.push(2); - const foo3 = () => ids.push(3); - const foo4 = () => ids.push(4); - - const universal = new UniversalDisposable(foo1, foo3); - universal.add(foo4, foo2); - - universal.dispose(); - - expect(ids).toEqual([1, 3, 4, 2]); - }); - - describe('teardown priority', () => { - it('calls dispose()', () => { - const foo: Function = jasmine.createSpy('foo'); - foo.dispose = jasmine.createSpy('dispose'); - foo.unsubscribe = jasmine.createSpy('unsubscribe'); - - const universal = new UniversalDisposable(foo); - universal.dispose(); - - expect(foo.dispose.wasCalled).toBe(true); - expect(foo.unsubscribe.wasCalled).toBe(false); - expect(foo.wasCalled).toBe(false); - }); - - it('calls unsubscribe()', () => { - const foo: Function = jasmine.createSpy('foo'); - foo.dispose = null; - foo.unsubscribe = jasmine.createSpy('unsubscribe'); - - const universal = new UniversalDisposable(foo); - universal.dispose(); - - expect(foo.unsubscribe.wasCalled).toBe(true); - expect(foo.wasCalled).toBe(false); - }); - - it('calls the function', () => { - const foo: Function = jasmine.createSpy('foo'); - foo.dispose = null; - foo.unsubscribe = null; - - const universal = new UniversalDisposable(foo); - universal.dispose(); - - expect(foo.wasCalled).toBe(true); - }); - }); -}); diff --git a/modules/nuclide-commons/spec/cache-spec.js b/modules/nuclide-commons/spec/cache-spec.js deleted file mode 100644 index 7e50353d..00000000 --- a/modules/nuclide-commons/spec/cache-spec.js +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import {Cache} from '../cache'; - -describe('Cache', () => { - const key1 = 'key1'; - const key2 = 'key2'; - const value = 'value'; - - it('creates values on demand', () => { - let callCount = 0; - const factory = jasmine.createSpy('factory').andCallFake(key => { - callCount += 1; - expect(key).toEqual(key1); - return value; - }); - const cache: Cache = new Cache(factory); - - expect(factory).not.toHaveBeenCalled(); - expect(cache.has(key1)).toEqual(false); - expect(cache.get(key1)).toEqual(value); - expect(callCount).toEqual(1); - expect(cache.has(key1)).toEqual(true); - expect(factory).toHaveBeenCalledWith(key1); - expect(Array.from(cache.values())).toEqual([value]); - - expect(cache.get(key1)).toEqual(value); - expect(callCount).toEqual(1); - }); - - it('delete', () => { - const factory = jasmine.createSpy('factory').andReturn(value); - const cache: Cache = new Cache(factory); - - expect(cache.delete(key1)).toEqual(false); - cache.get(key1); - expect(cache.has(key1)).toEqual(true); - expect(cache.delete(key1)).toEqual(true); - expect(cache.has(key1)).toEqual(false); - }); - - it('delete disposes values', () => { - const factory = jasmine.createSpy('factory').andReturn(value); - const dispose = jasmine.createSpy('dispose'); - const cache: Cache = new Cache(factory, dispose); - - cache.get(key1); - cache.delete(key1); - expect(dispose).toHaveBeenCalledWith(value); - }); - - it('clear disposes values', () => { - const factory = jasmine.createSpy('factory').andReturn(value); - const dispose = jasmine.createSpy('dispose'); - const cache: Cache = new Cache(factory, dispose); - - cache.get(key1); - cache.clear(); - expect(dispose).toHaveBeenCalledWith(value); - }); - - it('dispose disposes values', () => { - const factory = jasmine.createSpy('factory').andReturn(value); - const dispose = jasmine.createSpy('dispose'); - const cache: Cache = new Cache(factory, dispose); - - cache.get(key1); - cache.dispose(); - expect(dispose).toHaveBeenCalledWith(value); - }); - - it('observeValues sees existing and new values', () => { - waitsForPromise(async () => { - const factory = jasmine.createSpy('factory').andCallFake(key => key); - const cache: Cache = new Cache(factory); - - cache.get(key1); - const values = cache.observeValues().toArray().toPromise(); - cache.get(key2); - cache.dispose(); - expect(await values).toEqual([key1, key2]); - }); - }); - - it('observeKeys sees existing and new keys', () => { - waitsForPromise(async () => { - const factory = jasmine.createSpy('factory').andCallFake(key => value); - const cache: Cache = new Cache(factory); - - cache.get(key1); - const values = cache.observeKeys().toArray().toPromise(); - cache.get(key2); - cache.dispose(); - expect(await values).toEqual([key1, key2]); - }); - }); -}); diff --git a/modules/nuclide-commons/spec/collection-spec.js b/modules/nuclide-commons/spec/collection-spec.js deleted file mode 100644 index deae902e..00000000 --- a/modules/nuclide-commons/spec/collection-spec.js +++ /dev/null @@ -1,533 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import { - arrayRemove, - arrayEqual, - arrayCompact, - arrayFindLastIndex, - mapUnion, - isEmpty, - isIterable, - keyMirror, - setFilter, - setIntersect, - setUnion, - collect, - MultiMap, - objectEntries, - objectFromMap, - objectValues, - concatIterators, - areSetsEqual, - someOfIterable, - findInIterable, - filterIterable, - mapEqual, - mapIterable, - mapGetWithDefault, - count, -} from '../collection'; - -describe('arrayRemove', () => { - let a: any; - let empty: any; - let single: any; - - beforeEach(() => { - a = ['a', 'b', 'c']; - empty = []; - single = ['x']; - }); - - it('removes an element properly', () => { - arrayRemove(a, 'b'); - expect(a).toEqual(['a', 'c']); - }); - - it('removes the first element properly', () => { - arrayRemove(a, 'a'); - expect(a).toEqual(['b', 'c']); - }); - - it('removes the last element properly', () => { - arrayRemove(a, 'c'); - expect(a).toEqual(['a', 'b']); - }); - - it('does nothing if the element is not found', () => { - arrayRemove(a, 'd'); - expect(a).toEqual(['a', 'b', 'c']); - }); - - it('does nothing to an empty array', () => { - arrayRemove(empty, 'a'); - expect(empty).toEqual([]); - }); - - it('works when there is a single element', () => { - arrayRemove(single, 'x'); - expect(single).toEqual([]); - }); -}); - -describe('arrayEqual', () => { - it('checks boolean elements', () => { - expect(arrayEqual([true, false, true], [true, false, true])).toBe(true); - expect(arrayEqual([true], [false])).toBe(false); - }); - - it('checks number elements', () => { - expect(arrayEqual([1, 2, 3], [1, 2, 3])).toBe(true); - expect(arrayEqual([1, 5, 3], [1, 2, 3])).toBe(false); - }); - - it('checks object elements', () => { - expect(arrayEqual([{}], [{}])).toBe(false); - expect( - arrayEqual([{x: 1}, {x: 2}], [{x: 1}, {x: 2}], (a, b) => a.x === b.x), - ).toBe(true); - }); - - it('works with arrays of different lengths', () => { - expect(arrayEqual([1, 2], [1, 2, 3])).toBe(false); - expect(arrayEqual([1, 2, 3], [1, 2])).toBe(false); - }); -}); - -describe('arrayCompact', () => { - it('filters out null and undefined elements', () => { - expect(arrayCompact([0, false, '', [], null, undefined])).toEqual([ - 0, - false, - '', - [], - ]); - }); -}); - -describe('arrayFindLastIndex', () => { - it('returns the last matching index', () => { - expect(arrayFindLastIndex([1, 1, 2], x => x === 1)).toBe(1); - }); - - it('returns -1 if no match is found', () => { - expect(arrayFindLastIndex([1, 1, 2], x => x === 0)).toBe(-1); - }); -}); - -describe('mapUnion', () => { - it('merges two unique maps', () => { - const map1 = new Map([['key1', 'value1'], ['key2', 'value2']]); - const map2 = new Map([['key3', 'value3'], ['key4', 'value4']]); - const result = mapUnion(map1, map2); - - expect(result.size).toBe(4); - expect(result.get('key1')).toBe('value1'); - expect(result.get('key2')).toBe('value2'); - expect(result.get('key3')).toBe('value3'); - expect(result.get('key4')).toBe('value4'); - }); - - it('overrodes with the values of the latest maps', () => { - const map1 = new Map([['commonKey', 'value1'], ['key2', 'value2']]); - const map2 = new Map([['commonKey', 'value3'], ['key4', 'value4']]); - const result = mapUnion(...[map1, map2]); - - expect(result.size).toBe(3); - expect(result.get('commonKey')).toBe('value3'); - expect(result.get('key2')).toBe('value2'); - expect(result.get('key4')).toBe('value4'); - }); -}); - -describe('isEmpty', () => { - it('correctly identifies empty Objects', () => { - expect(isEmpty({})).toEqual(true); - }); - - it('correctly identifies non-empty Objects', () => { - const proto = {a: 1, b: 2, c: 3}; - const objWithOwnProperties = Object.create(proto, {foo: {value: 'bar'}}); - const objWithoutOwnProperties = Object.create(proto); - - expect(isEmpty({a: 1})).toEqual(false); - expect(isEmpty(objWithOwnProperties)).toEqual(false); - expect(isEmpty(objWithoutOwnProperties)).toEqual(false); - }); -}); - -describe('isIterable', () => { - it('detects arrays are iterable', () => { - expect(isIterable(['foo', 'bar'])).toBe(true); - }); - - it('detects strings are iterable', () => { - expect(isIterable('foo')).toBe(true); - }); - - it('detects Sets are iterable', () => { - expect(isIterable(new Set(['foo', 'bar']))).toBe(true); - }); - - it('detects iterable objects are iterable', () => { - const anIterable = { - *[Symbol.iterator]() { - yield 1; - yield 42; - }, - }; - - expect(isIterable(anIterable)).toBe(true); - }); - - it('detects plain objects are not iterable', () => { - expect(isIterable({foo: 'bar', baz: 42})).toBe(false); - }); - - it('detects numbers are not iterable', () => { - expect(isIterable(42)).toBe(false); - }); -}); - -describe('keyMirror', () => { - it('correctly mirrors objects', () => { - expect(keyMirror({a: null, b: null})).toEqual({a: 'a', b: 'b'}); - }); -}); - -describe('setFilter', () => { - it('filters', () => { - const set = new Set(['foo', 'bar', 'baz']); - const filtered = setFilter(set, x => x.startsWith('b')); - - expect(filtered.size).toBe(2); - expect(filtered.has('bar')).toBe(true); - expect(filtered.has('baz')).toBe(true); - expect(filtered.has('foo')).toBe(false); - }); -}); - -describe('setIntersect', () => { - it('intersects', () => { - const set1 = new Set(['foo', 'bar', 'baz']); - const set2 = new Set(['fool', 'bar', 'bazl']); - const result = setIntersect(set1, set2); - - expect(result.size).toBe(1); - expect(result.has('bar')).toBe(true); - }); -}); - -describe('setUnion', () => { - it('unions', () => { - const set1 = new Set(['foo', 'bar', 'baz']); - const set2 = new Set(['fool', 'bar', 'bazl']); - const result = setUnion(set1, set2); - - const expected = new Set(['foo', 'bar', 'baz', 'fool', 'bazl']); - expect(areSetsEqual(result, expected)).toBe(true); - }); -}); - -describe('collect', () => { - it('collects key-value pairs into a Map of arrays', () => { - const pairs = [ - ['neither', 1], - ['neither', 2], - ['fizz', 3], - ['neither', 4], - ['buzz', 5], - ['fizz', 6], - ['neither', 7], - ['neither', 8], - ['fizz', 9], - ]; - const result = collect(pairs); - - expect(result.size).toBe(3); - expect(result.get('fizz')).toEqual([3, 6, 9]); - expect(result.get('buzz')).toEqual([5]); - expect(result.get('neither')).toEqual([1, 2, 4, 7, 8]); - }); -}); - -describe('MultiMap', () => { - let multimap: MultiMap = (null: any); - - beforeEach(() => { - multimap = new MultiMap(); - }); - - afterEach(() => { - // check representation invariants - let size = 0; - for (const [, set] of multimap._map) { - expect(set.size).toBeGreaterThan(0); - size += set.size; - } - expect(multimap.size).toEqual(size); - }); - - it("returns an empty set when a binding doesn't exist", () => { - expect(multimap.get(4)).toEqual(new Set()); - }); - - it('returns itself from add', () => { - expect(multimap.add(1, 2)).toBe(multimap); - }); - - it('properly adds a single binding', () => { - multimap.add(1, 2); - expect(multimap.size).toEqual(1); - expect(multimap.get(1)).toEqual(new Set([2])); - }); - - it('properly adds multiple bindings', () => { - multimap.add(1, 2).add(1, 3).add(10, 11); - expect(multimap.size).toEqual(3); - expect(multimap.get(1)).toEqual(new Set([2, 3])); - expect(multimap.get(10)).toEqual(new Set([11])); - }); - - it('returns false from delete when nothing was deleted', () => { - multimap.add(1, 2); - expect(multimap.delete(1, 3)).toBe(false); - expect(multimap.delete(2, 3)).toBe(false); - }); - - it('properly deletes a single binding', () => { - multimap.add(1, 2).add(1, 3).add(10, 11); - expect(multimap.delete(1, 2)).toBe(true); - expect(multimap.get(1)).toEqual(new Set([3])); - expect(multimap.get(10)).toEqual(new Set([11])); - expect(multimap.size).toEqual(2); - }); - - it('returns false from deleteAll when nothing was deleted', () => { - expect(multimap.deleteAll(5)).toBe(false); - }); - - it('properly deletes all bindings for a given key', () => { - multimap.add(1, 2).add(1, 3); - expect(multimap.deleteAll(1)).toBe(true); - expect(multimap.size).toEqual(0); - expect(multimap.get(1)).toEqual(new Set()); - }); - - it('properly clears', () => { - multimap.add(1, 2).add(1, 3).add(10, 11); - multimap.clear(); - expect(multimap.size).toEqual(0); - expect(multimap.get(1)).toEqual(new Set()); - expect(multimap.get(10)).toEqual(new Set()); - }); - - it('checks membership with has', () => { - multimap.add(1, 2); - expect(multimap.has(5, 6)).toBe(false); - expect(multimap.has(1, 2)).toBe(true); - expect(multimap.has(1, 3)).toBe(false); - }); - - it('checks membership with hasAny', () => { - multimap.add(1, 2); - expect(multimap.hasAny(1)).toBe(true); - expect(multimap.hasAny(2)).toBe(false); - }); -}); - -describe('objectValues', () => { - it('returns the values of an object', () => { - expect( - objectValues({ - a: 1, - b: 2, - c: 4, - }), - ).toEqual([1, 2, 4]); - }); - - it('throws for null', () => { - expect(() => objectEntries(null)).toThrow(); - }); - - it('throws for undefined', () => { - expect(() => objectEntries(undefined)).toThrow(); - }); -}); - -describe('objectEntries', () => { - it('gets the entries of an object', () => { - expect(objectEntries({a: 1, b: 2})).toEqual([['a', 1], ['b', 2]]); - }); - - it('errors for null', () => { - expect(() => objectEntries((null: any))).toThrow(); - }); - - it('errors for undefined', () => { - expect(() => objectEntries((null: any))).toThrow(); - }); - - it('only includes own properties', () => { - const a = {a: 1}; - const b = {b: 2}; - Object.setPrototypeOf(b, a); - expect(objectEntries(b)).toEqual([['b', 2]]); - }); -}); - -describe('objectFromMap', () => { - it('converts a map to an object', () => { - expect(objectFromMap(new Map([['a', 1], ['b', 2]]))).toEqual({a: 1, b: 2}); - }); -}); - -describe('concatIterators', () => { - it('concatenates different iterable stuff to a single iterator', () => { - expect( - Array.from( - concatIterators( - new Set([1, 2, 3]), - [4, 5, 6], - new Set([7, 8, 9]).values(), - ), - ), - ).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]); - }); -}); - -describe('areSetsEqual', () => { - it('correctly compares empty sets', () => { - expect(areSetsEqual(new Set(), new Set())).toBe(true); - }); - - it('correctly compares sets with the same properties', () => { - expect(areSetsEqual(new Set(['foo']), new Set(['foo']))).toBe(true); - }); - - it('returns false when properties are not equal', () => { - expect(areSetsEqual(new Set(['foo']), new Set(['bar']))).toBe(false); - }); - - it('returns false when an item exists in one set but not the other', () => { - expect(areSetsEqual(new Set(['foo']), new Set())).toBe(false); - expect(areSetsEqual(new Set(), new Set(['foo']))).toBe(false); - }); -}); - -describe('someOfIterable', () => { - it('lazily returns whether any element of an iterable fulfills a given predicate', () => { - expect( - someOfIterable(new Set([1, 2, 3, 4, 5]), element => element % 2 === 0), - ).toEqual(true); - expect( - someOfIterable(new Set([1, 2, 3, 4, 5]), element => element % 5 === 0), - ).toEqual(true); - expect( - someOfIterable(new Set([1, 2, 3, 4, 5]), element => element % 6 === 0), - ).toEqual(false); - expect(someOfIterable([], element => true)).toEqual(false); - }); -}); - -describe('findInIterable', () => { - it('return the first element of an iterable which fulfills a given predicate', () => { - expect( - findInIterable(new Set([1, 2, 3, 4, 5]), element => element % 2 === 0), - ).toEqual(2); - expect( - findInIterable(new Set([1, 2, 3, 4, 5]), element => element % 5 === 0), - ).toEqual(5); - expect( - findInIterable(new Set([1, 2, 3, 4, 5]), element => element % 6 === 0), - ).toEqual(null); - expect(findInIterable([], element => true)).toEqual(null); - }); -}); - -describe('filterIterable', () => { - it('returns a (lazy) iterable containing all elements which fulfill the given predicate', () => { - expect( - Array.from( - filterIterable(new Set([1, 2, 3, 4, 5]), element => element % 2 === 0), - ), - ).toEqual([2, 4]); - expect( - Array.from(filterIterable(new Set([1, 2, 3, 4, 5]), element => true)), - ).toEqual([1, 2, 3, 4, 5]); - expect( - Array.from(filterIterable(new Set([1, 2, 3, 4, 5]), element => false)), - ).toEqual([]); - expect(Array.from(filterIterable([], element => true))).toEqual([]); - }); -}); - -describe('mapEqual', () => { - it('checks primary elements', () => { - expect( - mapEqual( - new Map([[1, true], [2, false], [5, true]]), - new Map([[1, true], [2, false], [5, true]]), - ), - ).toBe(true); - expect(mapEqual(new Map([[1, true]]), new Map([[1, false]]))).toBe(false); - expect(mapEqual(new Map([[1, true]]), new Map([]))).toBe(false); - expect(mapEqual(new Map([[1, true]]), new Map([[2, false]]))).toBe(false); - }); - - it('checks object value elements', () => { - expect(mapEqual(new Map([[1, {x: 1}]]), new Map([[1, {x: 1}]]))).toBe( - false, - ); - expect( - mapEqual( - new Map([[1, {x: 1}]]), - new Map([[1, {x: 1}]]), - (v1, v2) => v1.x === v2.x, - ), - ).toBe(true); - }); -}); - -describe('mapIterable', () => { - it('projects each element of an iterable into a new iterable', () => { - expect(Array.from(mapIterable(new Set(), element => true))).toEqual([]); - expect( - Array.from( - mapIterable(new Set([1, 2, 3, 4, 5]), element => element * element), - ), - ).toEqual([1, 4, 9, 16, 25]); - }); -}); - -describe('mapGetWithDefault', () => { - it('normally returns whatever is in the map', () => { - expect(mapGetWithDefault(new Map([[1, 2]]), 1, 3)).toBe(2); - }); - - it('returns the default if the key is not in the map', () => { - expect(mapGetWithDefault(new Map([[1, 2]]), 5, 3)).toBe(3); - }); - - it('returns `null` or `undefined` if they are values in the map', () => { - expect(mapGetWithDefault(new Map([[1, null]]), 1, 3)).toBeNull(); - expect(mapGetWithDefault(new Map([[1, undefined]]), 1, 3)).toBeUndefined(); - }); -}); - -describe('count', () => { - it('returns how many values are in an iterable', () => { - expect(count([1, 2])).toBe(2); - }); -}); diff --git a/modules/nuclide-commons/spec/debounce-spec.js b/modules/nuclide-commons/spec/debounce-spec.js deleted file mode 100644 index 76328e1f..00000000 --- a/modules/nuclide-commons/spec/debounce-spec.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import invariant from 'assert'; -import debounce from '../debounce'; - -describe('debounce()', () => { - it('only calls function once after time advances', () => { - const timerCallback: any = jasmine.createSpy('timerCallback'); - const debouncedFunc = debounce(timerCallback, 100, false); - - debouncedFunc(); - expect(timerCallback).not.toHaveBeenCalled(); - - advanceClock(101); - expect(timerCallback).toHaveBeenCalled(); - }); - - it('disposes', () => { - const timerCallback: any = jasmine.createSpy('timerCallback'); - const debouncedFunc = debounce(timerCallback, 100, false); - - debouncedFunc(); - expect(timerCallback).not.toHaveBeenCalled(); - - debouncedFunc.dispose(); - - advanceClock(101); - expect(timerCallback).not.toHaveBeenCalled(); - }); - - it('does not swallow flow types', () => { - const func = (a: string): number => 1; - const debounced = debounce(func, 0); - const ret = debounced('bar'); - - // $FlowIgnore: func's first param should be a string. - debounced(1); - - expect(() => { - // $FlowIgnore: debounce's return type is "maybe func's return" type. - (ret: number); - // This is false because we haven't waited for the timer. - invariant(ret != null); - (ret: number); - }).toThrow(); - - debounced.dispose(); - - expect(() => { - // $FlowIgnore: debounced has no "bar" property. - debounced.bar(); - }).toThrow(); - }); -}); diff --git a/modules/nuclide-commons/spec/event-spec.js b/modules/nuclide-commons/spec/event-spec.js deleted file mode 100644 index d8d3ac12..00000000 --- a/modules/nuclide-commons/spec/event-spec.js +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import invariant from 'assert'; -import EventEmitter from 'events'; -import {attachEvent, observableFromSubscribeFunction} from '../event'; - -describe('attachEvent', () => { - describe('the returned disposable', () => { - it("doesn't remove other listeners when disposed multiple times", () => { - const foo = jasmine.createSpy('foo'); - const emitter = new EventEmitter(); - const d1 = attachEvent(emitter, 'event', foo); - attachEvent(emitter, 'event', foo); - d1.dispose(); - d1.dispose(); - emitter.emit('event'); - expect(foo).toHaveBeenCalled(); - }); - }); -}); - -describe('observableFromSubscribeFunction', () => { - let callback: ?(item: number) => mixed; - let disposable: ?IDisposable; - - // The subscribe function will put the given callback and the returned disposable in the variables - // above for inspection. - const subscribeFunction = fn => { - callback = fn; - disposable = { - dispose() { - callback = null; - }, - }; - spyOn(disposable, 'dispose').andCallThrough(); - return disposable; - }; - - beforeEach(() => { - callback = null; - disposable = null; - }); - - it('should not call the subscription function until the Observable is subscribed to', () => { - const observable = observableFromSubscribeFunction(subscribeFunction); - expect(callback).toBeNull(); - observable.subscribe(() => {}); - expect(callback).not.toBeNull(); - }); - - it('should send events to the observable stream', () => { - waitsForPromise(async () => { - const result = observableFromSubscribeFunction(subscribeFunction) - .take(2) - .toArray() - .toPromise(); - invariant(callback != null); - callback(1); - callback(2); - expect(await result).toEqual([1, 2]); - }); - }); - - it('should properly unsubscribe and resubscribe', () => { - const observable = observableFromSubscribeFunction(subscribeFunction); - let subscription = observable.subscribe(() => {}); - expect(callback).not.toBeNull(); - - invariant(disposable != null); - expect(disposable.dispose).not.toHaveBeenCalled(); - subscription.unsubscribe(); - expect(disposable.dispose).toHaveBeenCalled(); - - expect(callback).toBeNull(); - - subscription = observable.subscribe(() => {}); - - expect(callback).not.toBeNull(); - - expect(disposable.dispose).not.toHaveBeenCalled(); - subscription.unsubscribe(); - expect(disposable.dispose).toHaveBeenCalled(); - }); -}); diff --git a/modules/nuclide-commons/spec/fixtures/ConfigCache/.test_nuclide_config_file b/modules/nuclide-commons/spec/fixtures/ConfigCache/.test_nuclide_config_file deleted file mode 100644 index e69de29b..00000000 diff --git a/modules/nuclide-commons/spec/fixtures/ConfigCache/file b/modules/nuclide-commons/spec/fixtures/ConfigCache/file deleted file mode 100644 index e69de29b..00000000 diff --git a/modules/nuclide-commons/spec/fixtures/ConfigCache/testFolder/file b/modules/nuclide-commons/spec/fixtures/ConfigCache/testFolder/file deleted file mode 100644 index e69de29b..00000000 diff --git a/modules/nuclide-commons/spec/fixtures/ConfigCache/testFolder2/.test_nuclide_config_file_2 b/modules/nuclide-commons/spec/fixtures/ConfigCache/testFolder2/.test_nuclide_config_file_2 deleted file mode 100644 index e69de29b..00000000 diff --git a/modules/nuclide-commons/spec/fixtures/lyrics b/modules/nuclide-commons/spec/fixtures/lyrics deleted file mode 100644 index ce2c212a..00000000 --- a/modules/nuclide-commons/spec/fixtures/lyrics +++ /dev/null @@ -1,49 +0,0 @@ -I wanna be the very best -Like no one ever was -To catch them is my real test -To train them is my cause - -I will travel across the land -Searching far and wide -Each Pokemon to understand -The power that's inside - -Pokemon, gotta catch 'em all -Its you and me -I know it's my destiny -Pokemon, oh, you're my best friend -In a world we must defend -Pokemon, gotta catch 'em all -A heart so true -Our courage will pull us through - -You teach me and I'll teach you -Pokemon, gotta catch 'em all -Gotta catch 'em all -Yeah - -Every challenge along the way -With courage I will face -I will battle every day -To claim my rightful place - -Come with me, the time is right -There's no better team -Arm in arm we'll win the fight -It's always been our dream - -Pokemon, gotta catch 'em all -Its you and me -I know it's my destiny -Pokemon, oh, you're my best friend -In a world we must defend -Pokemon, gotta catch 'em all -A heart so true -Our courage will pull us through - -You teach me and I'll teach you -Pokemon, gotta catch 'em all -Gotta catch 'em all -Gotta catch 'em all -Gotta catch 'em all -Yeah diff --git a/modules/nuclide-commons/spec/fixtures/symbol-definition-preview-sample.js b/modules/nuclide-commons/spec/fixtures/symbol-definition-preview-sample.js deleted file mode 100644 index 6536861e..00000000 --- a/modules/nuclide-commons/spec/fixtures/symbol-definition-preview-sample.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the license found in the LICENSE file in - * the root directory of this source tree. - * - * @flow - */ -// license header above without @format -// eslint-disable-next-line -const A_CONSTANT = 42; -const SOME_OTHER_CONSTANT = 24; - -// eslint-disable-next-line -const A_MULTILINE_CONST = ` - hey look I span - multiple - lines -`; - -type Something = { - name: string, - age?: number, -}; - -export function aSingleLineFunctionSignature() { - return A_CONSTANT + SOME_OTHER_CONSTANT; -} - -export function aMultiLineFunctionSignature( - aReallyReallyLongArgumentNameThatWouldRequireThisToBreakAcrossMultipleLines: Something, -): number { - return 97; -} - - export function aPoorlyIndentedFunction( -aReallyReallyLongArgumentNameThatWouldRequireThisToBreakAcrossMultipleLines: Something, -): number { - return 97; -} - -type SomethingComplex = { - properties: { - name: string, - age?: number, - }, -}; - -const foo: ?SomethingComplex = null; -foo; diff --git a/modules/nuclide-commons/spec/fixtures/symbol-definition-preview-sample.py b/modules/nuclide-commons/spec/fixtures/symbol-definition-preview-sample.py deleted file mode 100644 index ca7deddb..00000000 --- a/modules/nuclide-commons/spec/fixtures/symbol-definition-preview-sample.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2015-present, Facebook, Inc. -# All rights reserved. -# -# This source code is licensed under the license found in the LICENSE file in -# the root directory of this source tree. - - -def foo(bar=27): - return bar * 3 - - -def baz(test={ - 'one': 'two' -}): - return test['one'] - - -print(foo()) -print(baz()) diff --git a/modules/nuclide-commons/spec/fixtures/throw.js b/modules/nuclide-commons/spec/fixtures/throw.js deleted file mode 100644 index 54c55e8c..00000000 --- a/modules/nuclide-commons/spec/fixtures/throw.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -throw new Error('Errored!'); diff --git a/modules/nuclide-commons/spec/fixtures/toBeMocked.js b/modules/nuclide-commons/spec/fixtures/toBeMocked.js deleted file mode 100644 index 009f7899..00000000 --- a/modules/nuclide-commons/spec/fixtures/toBeMocked.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -export function importedFunction(arg: any): any { - return 0; -} diff --git a/modules/nuclide-commons/spec/fixtures/toBeTested.js b/modules/nuclide-commons/spec/fixtures/toBeTested.js deleted file mode 100644 index 8eda9295..00000000 --- a/modules/nuclide-commons/spec/fixtures/toBeTested.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import {importedFunction} from './toBeMocked'; - -export function functionToTest(): any { - return importedFunction(42); -} diff --git a/modules/nuclide-commons/spec/fsPromise-spec.js b/modules/nuclide-commons/spec/fsPromise-spec.js deleted file mode 100644 index 9c90aa7d..00000000 --- a/modules/nuclide-commons/spec/fsPromise-spec.js +++ /dev/null @@ -1,147 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import nuclideUri from '../nuclideUri'; -import fsPromise from '../fsPromise'; -import {generateFixture} from '../test-helpers'; - -describe('fsPromise test suite', () => { - describe('findNearestFile()', () => { - let dirPath: string = (null: any); - - beforeEach(() => { - waitsForPromise(async () => { - dirPath = await generateFixture( - 'nearest_test', - new Map([ - ['.some_file', 'just some file'], - ['nested_dir/.another_file', 'just another file'], - ]), - ); - }); - }); - - it('find the file if given the exact directory', () => { - waitsForPromise(async () => { - const foundPath = await fsPromise.findNearestFile( - '.some_file', - dirPath, - ); - expect(foundPath).toBe(dirPath); - }); - }); - - it('find the file if given a nested directory', () => { - waitsForPromise(async () => { - const foundPath = await fsPromise.findNearestFile( - '.some_file', - nuclideUri.join(dirPath, 'nested_dir'), - ); - expect(foundPath).toBe(dirPath); - }); - }); - - it('does not find the file if not existing', () => { - waitsForPromise(async () => { - const foundPath = await fsPromise.findNearestFile( - 'non-existent.txt', - nuclideUri.join(dirPath, 'nested_dir'), - ); - expect(foundPath).toBe(null); - }); - }); - }); - - describe('findFurthestFile()', () => { - let dirPath: string = (null: any); - - beforeEach(() => { - waitsForPromise(async () => { - dirPath = await generateFixture( - 'furthest_test', - new Map([ - ['0/.some_file', 'just a file'], - ['0/1/.some_file', 'just b file'], - // Skip one file to test consecutive vs non-consecutive. - // ['0/1/2', 'just c file'], - ['0/1/2/3/.some_file', 'just d file'], - ['0/1/2/3/4/.some_file', 'just f file'], - ]), - ); - }); - }); - - it('find the file if given the exact directory', () => { - waitsForPromise(async () => { - const expectedPath = nuclideUri.join(dirPath, '0'); - const foundPath = await fsPromise.findFurthestFile( - '.some_file', - expectedPath, - ); - expect(foundPath).toBe(expectedPath); - }); - }); - - it('finds the furthest file if given a nested directory', () => { - waitsForPromise(async () => { - const expectedPath = nuclideUri.join(dirPath, '0'); - const startPath = nuclideUri.join(dirPath, '0/1/2/3/4'); - const foundPath = await fsPromise.findFurthestFile( - '.some_file', - startPath, - ); - expect(foundPath).toBe(expectedPath); - }); - }); - - it('terminates search as soon as file is not found if given the stopOnMissing flag', () => { - waitsForPromise(async () => { - const expectedPath = nuclideUri.join(dirPath, '0/1/2/3'); - const startPath = nuclideUri.join(dirPath, '0/1/2/3/4'); - const foundPath = await fsPromise.findFurthestFile( - '.some_file', - startPath, - true /* stopOnMissing */, - ); - expect(foundPath).toBe(expectedPath); - }); - }); - - it('does not find the file if not existing', () => { - waitsForPromise(async () => { - const startPath = nuclideUri.join(dirPath, '0/1/2/3/4'); - const foundPath = await fsPromise.findFurthestFile( - 'non-existent.txt', - startPath, - ); - expect(foundPath).toBe(null); - }); - }); - }); - - describe('getCommonAncestorDirectory', () => { - it('gets the parent directory', () => { - expect( - fsPromise.getCommonAncestorDirectory([ - '/foo/bar.txt', - '/foo/baz/lol.txt', - ]), - ).toBe('/foo'); - expect( - fsPromise.getCommonAncestorDirectory([ - '/foo/bar/abc/def/abc.txt', - '/foo/bar/lol.txt', - ]), - ).toBe('/foo/bar'); - }); - }); -}); diff --git a/modules/nuclide-commons/spec/memoizeUntilChanged-spec.js b/modules/nuclide-commons/spec/memoizeUntilChanged-spec.js deleted file mode 100644 index 858be85d..00000000 --- a/modules/nuclide-commons/spec/memoizeUntilChanged-spec.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import memoizeUntilChanged from '../memoizeUntilChanged'; - -const sum = (a, b) => a + b; - -describe('memoizeUntilChanged', () => { - it('memoizes', () => { - const spy = jasmine.createSpy().andCallFake(sum); - const f = memoizeUntilChanged(spy); - f(1, 2); - const result = f(1, 2); - expect(result).toBe(3); - expect(spy.callCount).toBe(1); - }); - - it('resets when args change', () => { - const spy = jasmine.createSpy().andCallFake(sum); - const f = memoizeUntilChanged(spy); - f(1, 2); - const result = f(1, 3); - expect(result).toBe(4); - expect(spy.callCount).toBe(2); - }); - - it('preserves context', () => { - let that; - const obj = {}; - const f = memoizeUntilChanged(function f() { - that = this; - }); - f.call(obj); - expect(that).toBe(obj); - }); -}); diff --git a/modules/nuclide-commons/spec/nice-spec.js b/modules/nuclide-commons/spec/nice-spec.js deleted file mode 100644 index 346e89ba..00000000 --- a/modules/nuclide-commons/spec/nice-spec.js +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import typeof {niceSafeSpawn as niceSafeSpawnType} from '../nice'; - -import {uncachedRequire} from '../test-helpers'; -import {Observable} from 'rxjs'; - -describe('nice', () => { - let niceSafeSpawn: niceSafeSpawnType = (null: any); - - let whichSpy: JasmineSpy = (null: any); - let spawnSpy: JasmineSpy = (null: any); - let shouldFindNiceCommand: boolean = (null: any); - let shouldFindIoniceCommand: boolean = (null: any); - // All we need here is a unique value to make sure that `nice` returns whatever `safeSpawn` - // returns - const fakeSafeSpawnReturn: child_process$ChildProcess = ({}: any); - - beforeEach(() => { - shouldFindNiceCommand = true; - shouldFindIoniceCommand = true; - whichSpy = spyOn(require('../which'), 'default').andCallFake(command => { - if ( - (shouldFindNiceCommand && command === 'nice') || - (shouldFindIoniceCommand && command === 'ionice') - ) { - return command; - } else { - return null; - } - }); - spawnSpy = spyOn(require('../process'), 'spawn').andReturn( - Observable.of(fakeSafeSpawnReturn), - ); - ({niceSafeSpawn} = (uncachedRequire(require, '../nice'): any)); - }); - - it('should spawn `nice` and return whatever spawn returns', () => { - waitsForPromise(async () => { - const execOptions = {}; - const result = await niceSafeSpawn('echo', ['hi'], execOptions); - expect(spawnSpy).toHaveBeenCalledWith( - 'ionice', - ['-n', '7', 'nice', 'echo', 'hi'], - execOptions, - ); - expect(result).toBe(fakeSafeSpawnReturn); - }); - }); - - it('should spawn the command normally if nice and ionice cannot be found', () => { - waitsForPromise(async () => { - shouldFindNiceCommand = false; - shouldFindIoniceCommand = false; - const execOptions = {}; - const result = await niceSafeSpawn('echo', ['hi'], execOptions); - expect(spawnSpy).toHaveBeenCalledWith('echo', ['hi'], execOptions); - expect(result).toBe(fakeSafeSpawnReturn); - }); - }); - - it('should spawn with only nice if ionice cannot be found', () => { - waitsForPromise(async () => { - shouldFindIoniceCommand = false; - const execOptions = {}; - const result = await niceSafeSpawn('echo', ['hi'], execOptions); - expect(spawnSpy).toHaveBeenCalledWith( - 'nice', - ['echo', 'hi'], - execOptions, - ); - expect(result).toBe(fakeSafeSpawnReturn); - }); - }); - - it('should spawn with only ionice if nice cannot be found', () => { - waitsForPromise(async () => { - // I don't know when we would have ionice but not nice, but we may as well support this case. - shouldFindNiceCommand = false; - const execOptions = {}; - const result = await niceSafeSpawn('echo', ['hi'], execOptions); - expect(spawnSpy).toHaveBeenCalledWith( - 'ionice', - ['-n', '7', 'echo', 'hi'], - execOptions, - ); - expect(result).toBe(fakeSafeSpawnReturn); - }); - }); - - it('should call which only once per command and cache the result', () => { - waitsForPromise(async () => { - await niceSafeSpawn('echo', []); - await niceSafeSpawn('echo', []); - expect(whichSpy).toHaveBeenCalledWith('nice'); - expect(whichSpy).toHaveBeenCalledWith('ionice'); - expect(whichSpy.callCount).toBe(2); - }); - }); -}); diff --git a/modules/nuclide-commons/spec/nuclideUri-spec.js b/modules/nuclide-commons/spec/nuclideUri-spec.js deleted file mode 100644 index 956fab5d..00000000 --- a/modules/nuclide-commons/spec/nuclideUri-spec.js +++ /dev/null @@ -1,518 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import nuclideUri, {__TEST__} from '../nuclideUri'; -// eslint-disable-next-line rulesdir/prefer-nuclide-uri -import path from 'path'; - -describe('nuclide-uri', () => { - const localUri = '/usr/local/file'; - const badRemoteUriNoPath = 'nuclide://fb.com'; - const atomUri = 'atom://bla/bla'; - const remoteUri = nuclideUri.createRemoteUri('fb.com', '/usr/local'); - const remoteUriWithSpaces = nuclideUri.createRemoteUri('fb.com', '/a b/c d'); - const remoteUriWithHashes = nuclideUri.createRemoteUri( - 'fb.co.uk', - '/ab/#c.d #', - ); - - it('isRemote', () => { - expect(nuclideUri.isRemote('/')).toBe(false); - expect(nuclideUri.isRemote(remoteUri)).toBe(true); - expect(nuclideUri.isRemote(atomUri)).toBe(false); - }); - - it('isLocal', () => { - expect(nuclideUri.isLocal('/')).toBe(true); - expect(nuclideUri.isLocal(remoteUri)).toBe(false); - expect(nuclideUri.isLocal('C:\\abc')).toBe(true); - expect(nuclideUri.isLocal(atomUri)).toBe(false); - }); - - it('createRemoteUri', () => { - expect(remoteUri).toBe('nuclide://fb.com/usr/local'); - expect(remoteUriWithSpaces).toBe('nuclide://fb.com/a b/c d'); - }); - - it('join', () => { - expect(nuclideUri.join.bind(null, badRemoteUriNoPath, '../foo')).toThrow(); - expect(nuclideUri.join('/usr/local', 'bin')).toBe('/usr/local/bin'); - expect(nuclideUri.join(remoteUri, 'bin')).toBe( - 'nuclide://fb.com/usr/local/bin', - ); - expect(nuclideUri.join('/usr/local', '..')).toBe('/usr'); - expect(nuclideUri.join(remoteUri, '..')).toBe('nuclide://fb.com/usr'); - expect(() => nuclideUri.join(atomUri)).toThrow(); - }); - - describe('parsing remote', () => { - it('handles simple paths', () => { - expect(nuclideUri.getHostname(remoteUri)).toBe('fb.com'); - expect(nuclideUri.getPath(remoteUri)).toBe('/usr/local'); - }); - - it('does not encode space characters', () => { - expect(nuclideUri.getHostname(remoteUriWithSpaces)).toBe('fb.com'); - expect(nuclideUri.getPath(remoteUriWithSpaces)).toBe('/a b/c d'); - }); - - it('treats hash symbols as literals, part of the path', () => { - const parsedUri = nuclideUri.parse(remoteUriWithHashes); - expect(parsedUri.hostname).toBe('fb.co.uk'); - expect(parsedUri.path).toBe('/ab/#c.d #'); - }); - - it('throws when given an Atom URI', () => { - expect(() => nuclideUri.getHostname(atomUri)).toThrow(); - expect(() => nuclideUri.getPath(atomUri)).toThrow(); - expect(() => nuclideUri.parse(atomUri)).toThrow(); - }); - }); - - it('parsing local', () => { - expect(() => nuclideUri.getHostname(localUri)).toThrow(); - expect(nuclideUri.getPath(localUri)).toBe(localUri); - expect(() => nuclideUri.parseRemoteUri(localUri)).toThrow(); - }); - - it('basename', () => { - expect(nuclideUri.basename('/')).toBe(''); - expect(nuclideUri.basename('/abc')).toBe('abc'); - expect(nuclideUri.basename('/abc/')).toBe('abc'); - expect(nuclideUri.basename('/abc/def')).toBe('def'); - expect(nuclideUri.basename('/abc/def/')).toBe('def'); - - expect(nuclideUri.basename('nuclide://host/')).toBe(''); - expect(nuclideUri.basename('nuclide://host/abc')).toBe('abc'); - expect(nuclideUri.basename('nuclide://host/abc/')).toBe('abc'); - expect(nuclideUri.basename('nuclide://host/abc/def')).toBe('def'); - expect(nuclideUri.basename('nuclide://host/abc/def/')).toBe('def'); - expect(nuclideUri.basename('nuclide://host/a c/d f')).toBe('d f'); - - expect(nuclideUri.basename('C:\\')).toBe(''); - expect(nuclideUri.basename('C:\\abc')).toBe('abc'); - expect(nuclideUri.basename('C:\\abc\\')).toBe('abc'); - expect(nuclideUri.basename('C:\\abc\\def')).toBe('def'); - expect(nuclideUri.basename('C:\\abc\\def\\')).toBe('def'); - expect(nuclideUri.basename('\\abc\\def')).toBe('def'); - expect(nuclideUri.basename('\\abc\\def\\')).toBe('def'); - - expect(() => nuclideUri.basename(atomUri)).toThrow(); - }); - - it('dirname', () => { - expect(nuclideUri.dirname('/')).toBe('/'); - expect(nuclideUri.dirname('/abc')).toBe('/'); - expect(nuclideUri.dirname('/abc/')).toBe('/'); - expect(nuclideUri.dirname('/abc/def')).toBe('/abc'); - expect(nuclideUri.dirname('/abc/def/')).toBe('/abc'); - - expect(nuclideUri.dirname('nuclide://host/')).toBe('nuclide://host/'); - expect(nuclideUri.dirname('nuclide://host/abc')).toBe('nuclide://host/'); - expect(nuclideUri.dirname('nuclide://host/abc/')).toBe('nuclide://host/'); - expect(nuclideUri.dirname('nuclide://host/abc/def')).toBe( - 'nuclide://host/abc', - ); - expect(nuclideUri.dirname('nuclide://host/abc/def/')).toBe( - 'nuclide://host/abc', - ); - expect(nuclideUri.dirname('nuclide://host/a c/d f')).toBe( - 'nuclide://host/a c', - ); - - expect(nuclideUri.dirname('C:\\')).toBe('C:\\'); - expect(nuclideUri.dirname('C:\\abc')).toBe('C:\\'); - expect(nuclideUri.dirname('C:\\abc\\')).toBe('C:\\'); - expect(nuclideUri.dirname('C:\\abc\\def')).toBe('C:\\abc'); - expect(nuclideUri.dirname('C:\\abc\\def\\')).toBe('C:\\abc'); - expect(nuclideUri.dirname('\\abc\\def')).toBe('\\abc'); - expect(nuclideUri.dirname('\\abc\\def\\')).toBe('\\abc'); - - expect(() => nuclideUri.dirname(atomUri)).toThrow(); - }); - - it('extname', () => { - expect(nuclideUri.extname('/abc')).toBe(''); - expect(nuclideUri.extname('/abc.')).toBe('.'); - expect(nuclideUri.extname('/abc.txt')).toBe('.txt'); - expect(nuclideUri.extname('/abc/def.html')).toBe('.html'); - expect(nuclideUri.extname('/abc/def/')).toBe(''); - expect(nuclideUri.extname('/abc/def.dir/')).toBe('.dir'); - - expect(nuclideUri.extname('nuclide://host/')).toBe(''); - expect(nuclideUri.extname('nuclide://host/abc')).toBe(''); - expect(nuclideUri.extname('nuclide://host/abc.txt')).toBe('.txt'); - expect(nuclideUri.extname('nuclide://host/abc.')).toBe('.'); - expect(nuclideUri.extname('nuclide://host/abc/')).toBe(''); - expect(nuclideUri.extname('nuclide://host/abc/def')).toBe(''); - expect(nuclideUri.extname('nuclide://host/abc/def.js')).toBe('.js'); - - expect(nuclideUri.extname('C:\\')).toBe(''); - expect(nuclideUri.extname('C:\\abc')).toBe(''); - expect(nuclideUri.extname('C:\\abc\\')).toBe(''); - expect(nuclideUri.extname('C:\\abc.')).toBe('.'); - expect(nuclideUri.extname('C:\\abc.js')).toBe('.js'); - expect(nuclideUri.extname('C:\\abc\\def')).toBe(''); - expect(nuclideUri.extname('C:\\abc\\def\\')).toBe(''); - expect(nuclideUri.extname('C:\\abc\\def.')).toBe('.'); - expect(nuclideUri.extname('C:\\abc\\def.html')).toBe('.html'); - expect(nuclideUri.extname('\\abc\\def')).toBe(''); - expect(nuclideUri.extname('\\abc\\def.dir\\')).toBe('.dir'); - expect(nuclideUri.extname('\\abc\\def.')).toBe('.'); - expect(nuclideUri.extname('\\abc\\def.xml')).toBe('.xml'); - - expect(() => nuclideUri.extname(atomUri)).toThrow(); - }); - - it('getParent', () => { - expect(nuclideUri.getParent(localUri)).toBe('/usr/local'); - expect(nuclideUri.getParent(remoteUri)).toBe('nuclide://fb.com/usr'); - expect(() => nuclideUri.getParent(atomUri)).toThrow(); - }); - - it('contains', () => { - expect(nuclideUri.contains('/usr/local', localUri)).toBe(true); - expect(nuclideUri.contains('nuclide://fb.com/usr', remoteUri)).toBe(true); - expect(nuclideUri.contains('/foo/bar/', '/foo/bar/abc.txt')).toBe(true); - expect(nuclideUri.contains('/foo/bar', '/foo/bar/')).toBe(true); - expect(nuclideUri.contains('/foo/bar/', '/foo/bar/')).toBe(true); - expect(nuclideUri.contains('/foo/bar/', '/foo/bar')).toBe(true); - expect(() => nuclideUri.contains(atomUri, '/foo/bar')).toThrow(); - expect(() => nuclideUri.contains('/foo/bar', atomUri)).toThrow(); - }); - - it('collapse', () => { - expect(nuclideUri.collapse(['/a', '/b'])).toEqual(['/a', '/b']); - expect(nuclideUri.collapse(['/a/b/c/d', '/a', '/a/b'])).toEqual(['/a']); - expect( - nuclideUri.collapse(['/a/c', '/a/c/d', '/a/b', '/a/b/c/d/e']), - ).toEqual(['/a/c', '/a/b']); - expect(nuclideUri.collapse(['/a/be', '/a/b'])).toEqual(['/a/be', '/a/b']); - expect( - nuclideUri.collapse([ - 'nuclide://fb.com/usr/local', - 'nuclide://fb.com/usr/local/test', - 'nuclide://facebook.com/usr/local/test', - ]), - ).toEqual([ - 'nuclide://fb.com/usr/local', - 'nuclide://facebook.com/usr/local/test', - ]); - }); - - it('normalize', () => { - expect(nuclideUri.normalize(localUri)).toBe(localUri); - expect(nuclideUri.normalize(remoteUri)).toBe(remoteUri); - expect(nuclideUri.normalize.bind(null, badRemoteUriNoPath)).toThrow(); - expect(nuclideUri.normalize('/usr/local/..')).toBe('/usr'); - expect(nuclideUri.normalize('nuclide://fb.com/usr/local/..')).toBe( - 'nuclide://fb.com/usr', - ); - expect(nuclideUri.normalize('/a b/c d/..')).toBe('/a b'); - expect(() => nuclideUri.normalize(atomUri)).toThrow(); - }); - - it('relative', () => { - expect(() => nuclideUri.relative(localUri, remoteUri)).toThrow(); - expect(nuclideUri.relative(nuclideUri.dirname(remoteUri), remoteUri)).toBe( - 'local', - ); - expect(nuclideUri.relative(remoteUri, nuclideUri.dirname(remoteUri))).toBe( - '..', - ); - expect( - nuclideUri.relative( - nuclideUri.dirname(remoteUriWithSpaces), - remoteUriWithSpaces, - ), - ).toBe('c d'); - expect( - nuclideUri.relative( - remoteUriWithSpaces, - nuclideUri.dirname(remoteUriWithSpaces), - ), - ).toBe('..'); - expect(nuclideUri.relative(nuclideUri.dirname(localUri), localUri)).toBe( - 'file', - ); - expect(nuclideUri.relative(localUri, nuclideUri.dirname(localUri))).toBe( - '..', - ); - expect(() => nuclideUri.relative(atomUri, 'foo')).toThrow(); - }); - - it('nuclideUriToDisplayString', () => { - expect(nuclideUri.nuclideUriToDisplayString(localUri)).toBe(localUri); - expect(nuclideUri.nuclideUriToDisplayString(remoteUri)).toBe( - 'fb.com:/usr/local', - ); - expect(() => nuclideUri.nuclideUriToDisplayString(atomUri)).toThrow(); - }); - - describe('isRoot', () => { - it('plain posix root', () => expect(nuclideUri.isRoot('/')).toBe(true)); - it('double root', () => expect(nuclideUri.isRoot('//')).toBe(false)); - it('/abc', () => expect(nuclideUri.isRoot('/abc')).toBe(false)); - it('abc', () => expect(nuclideUri.isRoot('abc')).toBe(false)); - it('abc/def', () => expect(nuclideUri.isRoot('abc/def')).toBe(false)); - it('remote root', () => - expect(nuclideUri.isRoot('nuclide://host/')).toBe(true)); - it('remote root with port', () => - expect(nuclideUri.isRoot('nuclide://host/')).toBe(true)); - it('remote non-root', () => - expect(nuclideUri.isRoot('nuclide://host/abc')).toBe(false)); - it('remote non-root no port', () => { - expect(nuclideUri.isRoot('nuclide://host/abc')).toBe(false); - }); - it('win diskless root', () => expect(nuclideUri.isRoot('\\')).toBe(true)); - it('win diskless double root', () => - expect(nuclideUri.isRoot('\\\\')).toBe(false)); - it('win diskless non-root', () => - expect(nuclideUri.isRoot('\\abc')).toBe(false)); - it('win diskful root', () => expect(nuclideUri.isRoot('C:\\')).toBe(true)); - it('win diskful double root', () => - expect(nuclideUri.isRoot('C:\\\\')).toBe(false)); - it('win diskful non-root', () => - expect(nuclideUri.isRoot('C:\\abc')).toBe(false)); - - it('win relative', () => expect(nuclideUri.isRoot('abc\\def')).toBe(false)); - - it('throws on Atom URIs', () => - expect(() => nuclideUri.basename(atomUri)).toThrow()); - }); - - it('adds a proper suffix when needed', () => { - expect(nuclideUri.ensureTrailingSeparator('/')).toBe('/'); - expect(nuclideUri.ensureTrailingSeparator('/abc')).toBe('/abc/'); - expect(nuclideUri.ensureTrailingSeparator('/abc/')).toBe('/abc/'); - expect(nuclideUri.ensureTrailingSeparator('/abc/def')).toBe('/abc/def/'); - expect(nuclideUri.ensureTrailingSeparator('/abc/def/')).toBe('/abc/def/'); - expect(nuclideUri.ensureTrailingSeparator('nuclide://host')).toBe( - 'nuclide://host/', - ); - expect(nuclideUri.ensureTrailingSeparator('nuclide://host/')).toBe( - 'nuclide://host/', - ); - expect(nuclideUri.ensureTrailingSeparator('nuclide://host/abc')).toBe( - 'nuclide://host/abc/', - ); - expect(nuclideUri.ensureTrailingSeparator('nuclide://host/abc/def')).toBe( - 'nuclide://host/abc/def/', - ); - expect(nuclideUri.ensureTrailingSeparator('nuclide://host/abc/def/')).toBe( - 'nuclide://host/abc/def/', - ); - expect(nuclideUri.ensureTrailingSeparator('C:\\')).toBe('C:\\'); - expect(nuclideUri.ensureTrailingSeparator('C:\\abc')).toBe('C:\\abc\\'); - expect(nuclideUri.ensureTrailingSeparator('C:\\abc\\')).toBe('C:\\abc\\'); - expect(nuclideUri.ensureTrailingSeparator('C:\\abc\\def')).toBe( - 'C:\\abc\\def\\', - ); - expect(nuclideUri.ensureTrailingSeparator('C:\\abc\\def\\')).toBe( - 'C:\\abc\\def\\', - ); - expect(nuclideUri.ensureTrailingSeparator('\\abc\\def')).toBe( - '\\abc\\def\\', - ); - expect(nuclideUri.ensureTrailingSeparator('\\abc\\def\\')).toBe( - '\\abc\\def\\', - ); - expect(() => nuclideUri.ensureTrailingSeparator(atomUri)).toThrow(); - }); - - it('properly removes suffix when needed', () => { - expect(nuclideUri.trimTrailingSeparator('/')).toBe('/'); - expect(nuclideUri.trimTrailingSeparator('//')).toBe('/'); - expect(nuclideUri.trimTrailingSeparator('/abc')).toBe('/abc'); - expect(nuclideUri.trimTrailingSeparator('/abc/')).toBe('/abc'); - expect(nuclideUri.trimTrailingSeparator('/abc/def')).toBe('/abc/def'); - expect(nuclideUri.trimTrailingSeparator('/abc/def/')).toBe('/abc/def'); - expect(nuclideUri.trimTrailingSeparator('nuclide://host/')).toBe( - 'nuclide://host/', - ); - expect(nuclideUri.trimTrailingSeparator('nuclide://host//')).toBe( - 'nuclide://host/', - ); - expect(nuclideUri.trimTrailingSeparator('nuclide://host/')).toBe( - 'nuclide://host/', - ); - expect(nuclideUri.trimTrailingSeparator('nuclide://host//')).toBe( - 'nuclide://host/', - ); - expect(nuclideUri.trimTrailingSeparator('nuclide://host/abc')).toBe( - 'nuclide://host/abc', - ); - expect(nuclideUri.trimTrailingSeparator('nuclide://host/abc/')).toBe( - 'nuclide://host/abc', - ); - expect(nuclideUri.trimTrailingSeparator('nuclide://host/abc/def')).toBe( - 'nuclide://host/abc/def', - ); - expect(nuclideUri.trimTrailingSeparator('nuclide://host/abc/def/')).toBe( - 'nuclide://host/abc/def', - ); - expect(nuclideUri.trimTrailingSeparator('C:\\')).toBe('C:\\'); - expect(nuclideUri.trimTrailingSeparator('C:\\\\')).toBe('C:\\'); - expect(nuclideUri.trimTrailingSeparator('C:\\abc')).toBe('C:\\abc'); - expect(nuclideUri.trimTrailingSeparator('C:\\abc\\')).toBe('C:\\abc'); - expect(nuclideUri.trimTrailingSeparator('C:\\abc\\def')).toBe( - 'C:\\abc\\def', - ); - expect(nuclideUri.trimTrailingSeparator('C:\\abc\\def\\')).toBe( - 'C:\\abc\\def', - ); - expect(nuclideUri.trimTrailingSeparator('\\')).toBe('\\'); - expect(nuclideUri.trimTrailingSeparator('\\\\')).toBe('\\'); - expect(nuclideUri.trimTrailingSeparator('\\abc\\def')).toBe('\\abc\\def'); - expect(nuclideUri.trimTrailingSeparator('\\abc\\def\\')).toBe('\\abc\\def'); - expect(() => nuclideUri.trimTrailingSeparator(atomUri)).toThrow(); - }); - - it('isAbsolute', () => { - expect(nuclideUri.isAbsolute('/abc')).toBe(true); - expect(nuclideUri.isAbsolute('/abc/def')).toBe(true); - expect(nuclideUri.isAbsolute('nuclide://host/')).toBe(true); - expect(nuclideUri.isAbsolute('nuclide://host/abc')).toBe(true); - expect(nuclideUri.isAbsolute('nuclide://host/abc/def')).toBe(true); - - expect(nuclideUri.isAbsolute('C:\\abc')).toBe(true); - expect(nuclideUri.isAbsolute('C:\\abc\\def')).toBe(true); - expect(nuclideUri.isAbsolute('\\abc')).toBe(true); - expect(nuclideUri.isAbsolute('\\abc\\def')).toBe(true); - - expect(nuclideUri.isAbsolute('abc')).toBe(false); - expect(nuclideUri.isAbsolute('abc/def')).toBe(false); - - expect(nuclideUri.isAbsolute('abc\\def')).toBe(false); - expect(() => nuclideUri.isAbsolute(atomUri)).toThrow(); - }); - - it('resolve', () => { - expect(nuclideUri.resolve('/abc')).toBe('/abc'); - expect(nuclideUri.resolve('/abc', '..')).toBe('/'); - expect(nuclideUri.resolve('/abc', '..', '..')).toBe('/'); - expect(nuclideUri.resolve('/abc', '../..')).toBe('/'); - - expect(nuclideUri.resolve('/abc/def')).toBe('/abc/def'); - expect(nuclideUri.resolve('/abc/def', 'ghi')).toBe('/abc/def/ghi'); - expect(nuclideUri.resolve('/abc/def', '..', 'ghi')).toBe('/abc/ghi'); - expect(nuclideUri.resolve('/abc/def', '../ghi')).toBe('/abc/ghi'); - expect(nuclideUri.resolve('/abc/def', '/ghi')).toBe('/ghi'); - - expect(nuclideUri.resolve('nuclide://host/')).toBe('nuclide://host/'); - expect(nuclideUri.resolve('nuclide://host/', '..')).toBe('nuclide://host/'); - expect(nuclideUri.resolve('nuclide://host/abc')).toBe('nuclide://host/abc'); - expect(nuclideUri.resolve('nuclide://host/abc', '..')).toBe( - 'nuclide://host/', - ); - expect(nuclideUri.resolve('nuclide://host/abc', '..', '..')).toBe( - 'nuclide://host/', - ); - expect(nuclideUri.resolve('nuclide://host/abc', '../..')).toBe( - 'nuclide://host/', - ); - expect(nuclideUri.resolve('nuclide://host/abc/def', 'ghi')).toBe( - 'nuclide://host/abc/def/ghi', - ); - expect(nuclideUri.resolve('nuclide://host/abc/def', '../ghi')).toBe( - 'nuclide://host/abc/ghi', - ); - expect(nuclideUri.resolve('nuclide://host/abc/def', '..', 'ghi')).toBe( - 'nuclide://host/abc/ghi', - ); - expect(nuclideUri.resolve('nuclide://host/abc/def', '/ghi')).toBe( - 'nuclide://host/ghi', - ); - - expect(nuclideUri.resolve('C:\\abc')).toBe('C:\\abc'); - expect(nuclideUri.resolve('C:\\abc', '..')).toBe('C:\\'); - expect(nuclideUri.resolve('C:\\abc', '..', '..')).toBe('C:\\'); - expect(nuclideUri.resolve('C:\\abc', '..\\..')).toBe('C:\\'); - expect(nuclideUri.resolve('C:\\abc', 'def')).toBe('C:\\abc\\def'); - expect(nuclideUri.resolve('C:\\abc', '..\\def')).toBe('C:\\def'); - expect(nuclideUri.resolve('C:\\abc', '..', 'def')).toBe('C:\\def'); - - expect(nuclideUri.resolve('\\abc', 'def')).toBe('\\abc\\def'); - expect(nuclideUri.resolve('\\abc', '..\\def')).toBe('\\def'); - expect(nuclideUri.resolve('\\abc', '..', 'def')).toBe('\\def'); - expect(() => nuclideUri.resolve(atomUri, '..')).toThrow(); - }); - - describe('expandHomeDir()', () => { - it('expands ~ to HOME', () => { - expect(nuclideUri.expandHomeDir('~')).toBe(process.env.HOME); - }); - - it('expands ~/ to HOME', () => { - const HOME = process.env.HOME; - expect(HOME).not.toBeNull(); - expect(nuclideUri.expandHomeDir('~/abc')).toBe( - path.posix.join(HOME, 'abc'), - ); - }); - - it('keeps ~def to ~def', () => { - expect(nuclideUri.expandHomeDir('~def')).toBe('~def'); - }); - - it('throws on Atom URIs', () => { - expect(() => nuclideUri.expandHomeDir(atomUri)).toThrow(); - }); - }); - - it('detects Windows and Posix paths properly', () => { - expect(__TEST__._pathModuleFor('/')).toEqual(path.posix); - expect(__TEST__._pathModuleFor('/abc')).toEqual(path.posix); - expect(__TEST__._pathModuleFor('/abc/def')).toEqual(path.posix); - expect(__TEST__._pathModuleFor('/abc.txt')).toEqual(path.posix); - expect(__TEST__._pathModuleFor('nuclide://host')).toEqual(path.posix); - expect(__TEST__._pathModuleFor('nuclide://host/')).toEqual(path.posix); - expect(__TEST__._pathModuleFor('nuclide://host/abc')).toEqual(path.posix); - expect(__TEST__._pathModuleFor('nuclide://host/abc/def')).toEqual( - path.posix, - ); - expect(__TEST__._pathModuleFor('nuclide://host/abc/def.txt')).toEqual( - path.posix, - ); - expect(__TEST__._pathModuleFor('C:\\')).toEqual(path.win32); - expect(__TEST__._pathModuleFor('C:\\abc')).toEqual(path.win32); - expect(__TEST__._pathModuleFor('C:\\abc\\def')).toEqual(path.win32); - expect(__TEST__._pathModuleFor('C:\\abc\\def.txt')).toEqual(path.win32); - expect(__TEST__._pathModuleFor('D:\\abc\\aaa bbb')).toEqual(path.win32); - expect(__TEST__._pathModuleFor('\\abc\\def')).toEqual(path.win32); - - // Default to Posix - expect(__TEST__._pathModuleFor('abcdef')).toEqual(path.posix); - }); - - it('properly converts file URIs to local paths', () => { - expect(nuclideUri.uriToNuclideUri('\\abc\\def')).toEqual(null); - expect(nuclideUri.uriToNuclideUri('file://somehost/file/path')).toEqual( - '/file/path', - ); - expect(nuclideUri.uriToNuclideUri('file://C:\\some\\file\\path')).toEqual( - 'C:\\some\\file\\path', - ); - }); - - it('properly handles backslash-containing remote URIs', () => { - expect(nuclideUri.getPath('nuclide://host/aaa\\bbb.txt')).toBe( - '/aaa\\bbb.txt', - ); - expect(nuclideUri.getPath('nuclide://host/dir/aaa\\bbb.txt')).toBe( - '/dir/aaa\\bbb.txt', - ); - expect(nuclideUri.getPath('nuclide://host/one\\two\\file.txt')).toBe( - '/one\\two\\file.txt', - ); - }); -}); diff --git a/modules/nuclide-commons/spec/observable-spec.js b/modules/nuclide-commons/spec/observable-spec.js deleted file mode 100644 index 59d41785..00000000 --- a/modules/nuclide-commons/spec/observable-spec.js +++ /dev/null @@ -1,506 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import { - bufferUntil, - diffSets, - cacheWhileSubscribed, - macrotask, - microtask, - nextAnimationFrame, - reconcileSetDiffs, - splitStream, - takeWhileInclusive, - throttle, - toggle, - concatLatest, -} from '../observable'; -import {Disposable} from 'event-kit'; -import {Observable, Subject} from 'rxjs'; - -const setsAreEqual = (a, b) => - a.size === b.size && Array.from(a).every(b.has.bind(b)); -const diffsAreEqual = (a, b) => - setsAreEqual(a.added, b.added) && setsAreEqual(a.removed, b.removed); -const createDisposable = () => { - const disposable = new Disposable(() => {}); - spyOn(disposable, 'dispose'); - return disposable; -}; - -describe('nuclide-commons/observable', () => { - describe('splitStream', () => { - it('splits streams', () => { - waitsForPromise(async () => { - const input = ['foo\nbar', '\n', '\nba', 'z', '\nblar']; - const output = await splitStream(Observable.from(input)) - .toArray() - .toPromise(); - expect(output).toEqual(['foo\n', 'bar\n', '\n', 'baz\n', 'blar']); - }); - }); - }); - - describe('takeWhileInclusive', () => { - it('completes the stream when something matches the predicate', () => { - const source = new Subject(); - const result = takeWhileInclusive(source, x => x !== 2); - const next: (n: number) => mixed = jasmine.createSpy(); - const complete: () => mixed = jasmine.createSpy(); - result.subscribe({next, complete}); - source.next(1); - source.next(2); - source.next(3); - expect(complete).toHaveBeenCalled(); - expect(next.calls.map(call => call.args[0])).toEqual([1, 2]); - }); - }); - - describe('cacheWhileSubscribed', () => { - let input: Subject = (null: any); - let output: Observable = (null: any); - - function subscribeArray(arr: Array): rxjs$ISubscription { - return output.subscribe(x => arr.push(x)); - } - beforeEach(() => { - input = new Subject(); - output = cacheWhileSubscribed(input); - }); - - it('should provide cached values to late subscribers', () => { - const arr1 = []; - const arr2 = []; - - input.next(0); - const sub1 = subscribeArray(arr1); - input.next(1); - input.next(2); - const sub2 = subscribeArray(arr2); - - sub1.unsubscribe(); - sub2.unsubscribe(); - expect(arr1).toEqual([1, 2]); - expect(arr2).toEqual([2]); - }); - - it('should not store stale events when everyone is unsubscribed', () => { - const arr1 = []; - const arr2 = []; - - input.next(0); - const sub1 = subscribeArray(arr1); - input.next(1); - sub1.unsubscribe(); - - input.next(2); - - const sub2 = subscribeArray(arr2); - input.next(3); - sub2.unsubscribe(); - - expect(arr1).toEqual([1]); - expect(arr2).toEqual([3]); - }); - }); - - describe('diffSets', () => { - it('emits a diff for the first item', () => { - waitsForPromise(async () => { - const source = new Subject(); - const diffsPromise = diffSets(source).toArray().toPromise(); - source.next(new Set([1, 2, 3])); - source.complete(); - const diffs = await diffsPromise; - expect(diffs.length).toBe(1); - expect( - diffsAreEqual(diffs[0], { - added: new Set([1, 2, 3]), - removed: new Set(), - }), - ).toBe(true); - }); - }); - - it('correctly identifies removed items', () => { - waitsForPromise(async () => { - const source = new Subject(); - const diffsPromise = diffSets(source).toArray().toPromise(); - source.next(new Set([1, 2, 3])); - source.next(new Set([1, 2])); - source.complete(); - const diffs = await diffsPromise; - expect(setsAreEqual(diffs[1].removed, new Set([3]))).toBe(true); - }); - }); - - it('correctly identifies removed items when a hash function is used', () => { - waitsForPromise(async () => { - const source = new Subject(); - const diffsPromise = diffSets(source, x => x.key).toArray().toPromise(); - const firstItems = [{key: 1}, {key: 2}, {key: 3}]; - const secondItems = [{key: 1}, {key: 2}]; - source.next(new Set(firstItems)); - source.next(new Set(secondItems)); - source.complete(); - const diffs = await diffsPromise; - expect(setsAreEqual(diffs[1].removed, new Set([firstItems[2]]))).toBe( - true, - ); - }); - }); - - it('correctly identifies added items', () => { - waitsForPromise(async () => { - const source = new Subject(); - const diffsPromise = diffSets(source).toArray().toPromise(); - source.next(new Set([1, 2])); - source.next(new Set([1, 2, 3])); - source.complete(); - const diffs = await diffsPromise; - expect(setsAreEqual(diffs[1].added, new Set([3]))).toBe(true); - }); - }); - - it('correctly identifies added items when a hash function is used', () => { - waitsForPromise(async () => { - const source = new Subject(); - const diffsPromise = diffSets(source, x => x.key).toArray().toPromise(); - const firstItems = [{key: 1}, {key: 2}]; - const secondItems = [{key: 1}, {key: 2}, {key: 3}]; - source.next(new Set(firstItems)); - source.next(new Set(secondItems)); - source.complete(); - const diffs = await diffsPromise; - expect(setsAreEqual(diffs[1].added, new Set([secondItems[2]]))).toBe( - true, - ); - }); - }); - - it("doesn't emit a diff when nothing changes", () => { - waitsForPromise(async () => { - const source = new Subject(); - const diffsPromise = diffSets(source).toArray().toPromise(); - source.next(new Set([1, 2, 3])); - source.next(new Set([1, 2, 3])); - source.complete(); - const diffs = await diffsPromise; - // Make sure we only get one diff (from the implicit initial empty set). - expect(diffs.length).toBe(1); - }); - }); - - it("doesn't emit a diff when nothing changes and a hash function is used", () => { - waitsForPromise(async () => { - const source = new Subject(); - const diffsPromise = diffSets(source, x => x.key).toArray().toPromise(); - const firstItems = [{key: 1}, {key: 2}, {key: 3}]; - const secondItems = [{key: 1}, {key: 2}, {key: 3}]; - source.next(new Set(firstItems)); - source.next(new Set(secondItems)); - source.complete(); - const diffs = await diffsPromise; - // Make sure we only get one diff (from the implicit initial empty set). - expect(diffs.length).toBe(1); - }); - }); - }); - - describe('reconcileSetDiffs', () => { - it("calls the add action for each item that's added", () => { - const diffs = new Subject(); - const addAction = jasmine.createSpy().andReturn(new Disposable(() => {})); - reconcileSetDiffs(diffs, addAction); - diffs.next({ - added: new Set(['a', 'b']), - removed: new Set(), - }); - expect(addAction.calls.map(call => call.args[0])).toEqual(['a', 'b']); - }); - - it("disposes for each item that's removed", () => { - const diffs = new Subject(); - const disposables = { - a: createDisposable(), - b: createDisposable(), - }; - const addAction = item => disposables[item]; - reconcileSetDiffs(diffs, addAction); - diffs.next({ - added: new Set(['a', 'b']), - removed: new Set(), - }); - diffs.next({ - added: new Set(), - removed: new Set(['a', 'b']), - }); - expect(disposables.a.dispose).toHaveBeenCalled(); - expect(disposables.b.dispose).toHaveBeenCalled(); - }); - - it('disposes for all items when disposed', () => { - const diffs = new Subject(); - const disposables = { - a: createDisposable(), - b: createDisposable(), - }; - const addAction = item => disposables[item]; - const reconciliationDisposable = reconcileSetDiffs(diffs, addAction); - diffs.next({ - added: new Set(['a', 'b']), - removed: new Set(), - }); - reconciliationDisposable.dispose(); - expect(disposables.a.dispose).toHaveBeenCalled(); - expect(disposables.b.dispose).toHaveBeenCalled(); - }); - - it("disposes for each item that's removed when a hash function is used", () => { - const diffs = new Subject(); - const disposables = { - a: createDisposable(), - b: createDisposable(), - }; - const addAction = item => disposables[item.key]; - reconcileSetDiffs(diffs, addAction, x => x.key); - diffs.next({ - added: new Set([{key: 'a'}, {key: 'b'}]), - removed: new Set(), - }); - diffs.next({ - added: new Set(), - removed: new Set([{key: 'a'}, {key: 'b'}]), - }); - expect(disposables.a.dispose).toHaveBeenCalled(); - expect(disposables.b.dispose).toHaveBeenCalled(); - }); - }); - - describe('toggle', () => { - let toggler: Subject = (null: any); - let source: Observable = (null: any); - let output: Observable = (null: any); - let outputArray: Array = (null: any); - - beforeEach(() => { - toggler = new Subject(); - // Deferred so individual 'it' blocks can set the source on the fly. - output = toggle(Observable.defer(() => source), toggler); - }); - - describe('with a standard source', () => { - let realSource: Subject = (null: any); - - beforeEach(() => { - source = realSource = new Subject(); - outputArray = []; - output.subscribe(x => outputArray.push(x)); - }); - - it("should not emit anything before the toggler is set to 'true'", () => { - realSource.next(5); - expect(outputArray).toEqual([]); - }); - - it("should start emitting events when the toggler is set to 'true'", () => { - toggler.next(true); - realSource.next(5); - expect(outputArray).toEqual([5]); - }); - - it("should stop emitting events when the toggler is set to 'false'", () => { - toggler.next(true); - toggler.next(false); - realSource.next(4); - expect(outputArray).toEqual([]); - }); - }); - - // These ones are set apart from the rest because we want a cold observable to explicitly test - // that toggling off unsubscribes and then resubscribes. - describe('subscription behavior', () => { - beforeEach(() => { - source = Observable.of(1, 2, 3); - outputArray = []; - output.subscribe(x => outputArray.push(x)); - }); - - it('should unsubscribe and resusbscribe when toggled off and back on', () => { - expect(outputArray).toEqual([]); - - toggler.next(true); - - expect(outputArray).toEqual([1, 2, 3]); - - toggler.next(false); - toggler.next(true); - - expect(outputArray).toEqual([1, 2, 3, 1, 2, 3]); - }); - - it('should not re-subscribe on duplicate toggler values', () => { - toggler.next(true); - toggler.next(true); - expect(outputArray).toEqual([1, 2, 3]); - }); - }); - }); - - describe('concatLatest', () => { - it('should work with empty input', () => { - waitsForPromise(async () => { - const output = await concatLatest().toArray().toPromise(); - expect(output).toEqual([]); - }); - }); - - it('should work with several observables', () => { - waitsForPromise(async () => { - const output = await concatLatest( - Observable.of([], [1]), - Observable.of([2]), - Observable.of([3], [3, 4]), - ) - .toArray() - .toPromise(); - expect(output).toEqual([[], [1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]); - }); - }); - }); - - describe('throttle', () => { - it('emits the leading item immeditately by default', () => { - const source = Observable.of(1, 2).merge(Observable.never()); - const spy = jasmine.createSpy(); - throttle(source, Observable.never()).subscribe(spy); - expect(spy).toHaveBeenCalledWith(1); - }); - - it("doesn't emit the leading item twice", () => { - const source = Observable.of(1).merge(Observable.never()); - const notifier = Observable.of(null); // emits immediately on subscription. - const spy = jasmine.createSpy(); - throttle(source, notifier).subscribe(spy); - expect(spy.callCount).toBe(1); - }); - - it('throttles', () => { - const source = new Subject(); - const notifier = new Subject(); - const spy = jasmine.createSpy(); - throttle(source, notifier).subscribe(spy); - source.next(1); - spy.reset(); - source.next(2); - expect(spy).not.toHaveBeenCalled(); - notifier.next(); - expect(spy).toHaveBeenCalledWith(2); - spy.reset(); - source.next(3); - expect(spy).not.toHaveBeenCalled(); - source.next(4); - expect(spy).not.toHaveBeenCalled(); - notifier.next(); - expect(spy).toHaveBeenCalledWith(4); - expect(spy.callCount).toBe(1); - }); - - it('subscribes to the source once per subscription', () => { - const spy = jasmine.createSpy(); - const source = Observable.create(spy); - throttle(source, Observable.of(null)).subscribe(); - expect(spy.callCount).toBe(1); - }); - }); - - describe('nextAnimationFrame', () => { - let oldRequestAnimationFrame; - let oldCancelAnimationFrame; - beforeEach(() => { - oldRequestAnimationFrame = window.requestAnimationFrame; - oldCancelAnimationFrame = window.cancelAnimationFrame; - window.requestAnimationFrame = jasmine.createSpy('requestAnimationFrame'); - window.cancelAnimationFrame = jasmine.createSpy('cancelAnimationFrame'); - }); - - afterEach(() => { - window.requestAnimationFrame = oldRequestAnimationFrame; - window.cancelAnimationFrame = oldCancelAnimationFrame; - }); - - it('schedules next using requestAnimationFrame', () => { - const sub = nextAnimationFrame.subscribe(); - expect(window.requestAnimationFrame).toHaveBeenCalled(); - sub.unsubscribe(); - }); - - it('uses cancelAnimationFrame when unsubscribed', () => { - const sub = nextAnimationFrame.subscribe(); - expect(window.cancelAnimationFrame).not.toHaveBeenCalled(); - sub.unsubscribe(); - expect(window.cancelAnimationFrame).toHaveBeenCalled(); - }); - }); - - describe('bufferUntil', () => { - it('buffers based on the predicate', () => { - waitsForPromise(async () => { - const chunks = await bufferUntil( - Observable.of(1, 2, 3, 4), - x => x % 2 === 0, - ) - .toArray() - .toPromise(); - expect(chunks).toEqual([[1, 2], [3, 4]]); - }); - }); - - it('provides the current buffer', () => { - waitsForPromise(async () => { - const chunks = await bufferUntil( - Observable.of(1, 2, 3, 4), - (x, buffer) => buffer.length === 2, - ) - .toArray() - .toPromise(); - expect(chunks).toEqual([[1, 2], [3, 4]]); - }); - }); - }); - - describe('microtask', () => { - it('is cancelable', () => { - waitsForPromise(async () => { - const spy = jasmine.createSpy(); - const sub = microtask.subscribe(spy); - let resolve; - const promise = new Promise(r => (resolve = r)); - sub.unsubscribe(); - process.nextTick(() => { - expect(spy).not.toHaveBeenCalled(); - resolve(); - }); - return promise; - }); - }); - }); - - describe('macrotask', () => { - it('is cancelable', () => { - spyOn(global, 'clearImmediate').andCallThrough(); - const sub = macrotask.subscribe(() => {}); - sub.unsubscribe(); - expect(clearImmediate).toHaveBeenCalled(); - }); - }); -}); diff --git a/modules/nuclide-commons/spec/process-spec.js b/modules/nuclide-commons/spec/process-spec.js deleted file mode 100644 index ad4fd9c2..00000000 --- a/modules/nuclide-commons/spec/process-spec.js +++ /dev/null @@ -1,785 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {ProcessExitMessage} from '../process'; - -import EventEmitter from 'events'; -import {sleep} from '../promise'; -import child_process from 'child_process'; -import invariant from 'assert'; -import {Observable, Scheduler, Subject} from 'rxjs'; - -import { - spawn, - getOutputStream, - killProcess, - killUnixProcessTree, - logStreamErrors, - observeProcess, - observeProcessRaw, - parsePsOutput, - preventStreamsFromThrowing, - ProcessSystemError, - runCommand, - runCommandDetailed, - scriptifyCommand, - exitEventToMessage, -} from '../process'; - -describe('commons-node/process', () => { - let origPlatform; - - beforeEach(() => { - origPlatform = process.platform; - // Use a fake platform so the platform's PATH is not used in case the test is run on a platform - // that requires special handling (like OS X). - Object.defineProperty(process, 'platform', {value: 'MockMock'}); - }); - - afterEach(() => { - Object.defineProperty(process, 'platform', {value: origPlatform}); - }); - - describe('process.killProcess', () => { - it('should only kill the process when `killTree` is false', () => { - waitsForPromise(async () => { - const proc = { - kill: jasmine.createSpy(), - }; - spyOn(console, 'error'); // suppress error printing - spyOn(console, 'log'); // suppress log printing - await killProcess((proc: any), false); - expect(proc.kill).toHaveBeenCalled(); - }); - }); - - it('should kill the process tree when `killTree` is true', () => { - waitsForPromise(async () => { - jasmine.useRealClock(); - // Create a tree that's more than level child deep. - const proc = child_process.spawn('bash', [ - '-c', - '( (sleep 1000)& sleep 1000 )& wait', - ]); - spyOn(console, 'error'); // suppress error printing - spyOn(console, 'log'); // suppress log printing - spyOn(process, 'kill').andCallThrough(); - await sleep(250); // Give some time for the processes to spawn. - await killUnixProcessTree(proc); - expect(process.kill.callCount).toBeGreaterThan(2); - }); - }); - - it('should kill the process tree on windows when `killTree` is true', () => { - waitsForPromise(async () => { - const proc = { - pid: 123, - }; - spyOn(console, 'error'); // suppress error printing - spyOn(console, 'log'); // suppress log printing - Object.defineProperty(process, 'platform', {value: 'win32'}); - spyOn(child_process, 'exec'); - await killProcess((proc: any), true); - expect(child_process.exec.calls.length).toBe(1); - expect(child_process.exec.calls[0].args[0]).toBe( - `taskkill /pid ${proc.pid} /T /F`, - ); - }); - }); - }); - - describe('process.parsePsOutput', () => { - it('parse `ps` unix output', () => { - const unixPsOut = - ' PPID PID COMM\n' + - ' 0 1 /sbin/launchd\n' + - ' 1 42 command with spaces'; - const processList = parsePsOutput(unixPsOut); - expect(processList).toEqual([ - {command: '/sbin/launchd', pid: 1, parentPid: 0}, - {command: 'command with spaces', pid: 42, parentPid: 1}, - ]); - }); - - it('parse `ps` windows output', () => { - const windowsProcessOut = - 'ParentProcessId ProcessId Name\r\n' + - ' 0 4 System Process\r\n' + - ' 4 228 smss.exe'; - - const processList = parsePsOutput(windowsProcessOut); - expect(processList).toEqual([ - {command: 'System Process', pid: 4, parentPid: 0}, - {command: 'smss.exe', pid: 228, parentPid: 4}, - ]); - }); - }); - - describe('getOutputStream', () => { - it('captures stdout, stderr and exitCode', () => { - waitsForPromise(async () => { - const child = child_process.spawn(process.execPath, [ - '-e', - 'console.error("stderr"); console.log("std out"); process.exit(0);', - ]); - const results = await getOutputStream(child).toArray().toPromise(); - expect(results).toEqual([ - {kind: 'stderr', data: 'stderr\n'}, - {kind: 'stdout', data: 'std out\n'}, - {kind: 'exit', exitCode: 0, signal: null}, - ]); - }); - }); - - it('errors on nonzero exit codes by default', () => { - waitsForPromise(async () => { - const child = child_process.spawn(process.execPath, [ - '-e', - 'console.error("stderr"); console.log("std out"); process.exit(42);', - ]); - const results = await getOutputStream(child) - // $FlowIssue: Add materialize to type defs - .materialize() - .toArray() - .toPromise(); - expect(results.map(notification => notification.kind)).toEqual([ - 'N', - 'N', - 'E', - ]); - const {error} = results[2]; - expect(error.name).toBe('ProcessExitError'); - expect(error.exitCode).toBe(42); - expect(error.stderr).toBe('stderr\n'); - }); - }); - - it('accumulates the first `exitErrorBufferSize` bytes of stderr for the exit error', () => { - waitsForPromise(async () => { - let error; - const child = child_process.spawn(process.execPath, [ - '-e', - 'console.error("stderr"); process.exit(42);', - ]); - try { - await getOutputStream(child, { - exitErrorBufferSize: 2, - isExitError: () => true, - }) - .toArray() - .toPromise(); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - invariant(error != null); - expect(error.stderr).toBe('st'); - }); - }); - }); - - describe('spawn', () => { - it('errors when the process does', () => { - waitsForPromise(async () => { - spyOn(console, 'error'); // suppress error printing - spyOn(console, 'log'); // suppress log printing - const processStream = spawn('fakeCommand'); - let error; - try { - await processStream.toPromise(); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - invariant(error); - expect(error.code).toBe('ENOENT'); - expect(error.name).toBe('ProcessSystemError'); - }); - }); - - // Node delays the emission of the error until after the process is returned so that you have a - // chance to subscribe to the error event. Observables aren't bound by the same limitations as - // event-emitter APIs, so we can do better and not emit the process if there was an error - // spawning it. - it('errors before emitting the process', () => { - waitsForPromise(async () => { - spyOn(console, 'error'); // suppress error printing - spyOn(console, 'log'); // suppress log printing - let proc; - await spawn('fakeCommand') - .do(p => { - proc = p; - }) - .catch(err => { - expect(proc).toBeUndefined(); - expect(err.code).toBe('ENOENT'); - expect(err.name).toBe('ProcessSystemError'); - return Observable.empty(); - }) - .toPromise(); - }); - }); - - it('leaves an error handler when you unsubscribe', () => { - waitsForPromise(async () => { - spyOn(console, 'error'); // suppress error printing - spyOn(console, 'log'); // suppress log printing - let resolve; - const promise = new Promise(r => { - resolve = r; - }); - const sub = spawn('cat') - // If we subscribe synchronously, and it emits synchronously, `sub` won't have been - // assigned yet in our `subscribe()` callback, so we use the async scheduler. - .subscribeOn(Scheduler.async) - .subscribe(proc => { - // As soon as we have a process, unsubscribe. This will happen before the error is - // thrown. - sub.unsubscribe(); - - // Make sure that the error handler is still registered. If it isn't, and the process - // errors, node will consider the error unhandled and we'll get a redbox. - expect(proc.listenerCount('error')).toBe(1); - - resolve(); - }); - await promise; - }); - }); - - it('can be retried', () => { - waitsForPromise(async () => { - spyOn(console, 'error'); // suppress error printing - spyOn(console, 'log'); // suppress log printing - spyOn(child_process, 'spawn'); - try { - await spawn('fakeCommand') - .retryWhen(errors => - errors.scan((errorCount, err) => { - // If this is the third time the process has errored (i.e. the have already been - // two errors before), stop retrying. (We try 3 times because because Rx 3 and 4 - // have bugs with retrying shared observables that would give false negatives for - // this test if we only tried twice.) - if (errorCount === 2) { - throw err; - } - return errorCount + 1; - }, 0), - ) - .toPromise(); - } catch (err) {} - expect(child_process.spawn.callCount).toBe(3); - }); - }); - - it('can be timed out', () => { - waitsForPromise(async () => { - let error; - let proc; - try { - await spawn('sleep', ['10000'], {timeout: 1}) - .do(p => { - proc = p; - spyOn(proc, 'kill'); - }) - .toPromise(); - } catch (err) { - error = err; - } - invariant(proc != null); - invariant(error != null); - expect(error.name).toBe('ProcessTimeoutError'); - expect(proc.kill).toHaveBeenCalled(); - }); - }); - }); - - describe('observeProcess', () => { - it('errors when the process does', () => { - waitsForPromise(async () => { - spyOn(console, 'error'); // suppress error printing - spyOn(console, 'log'); // suppress log printing - const processStream = observeProcess('fakeCommand', []); - let error; - try { - await processStream.toPromise(); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - invariant(error); - expect(error.code).toBe('ENOENT'); - expect(error.name).toBe('ProcessSystemError'); - }); - }); - - it('errors on nonzero exit codes by default', () => { - waitsForPromise(async () => { - const results = await observeProcess(process.execPath, [ - '-e', - 'console.error("stderr"); console.log("std out"); process.exit(42);', - ]) - // $FlowIssue: Add materialize to type defs - .materialize() - .toArray() - .toPromise(); - expect(results.map(notification => notification.kind)).toEqual([ - 'N', - 'N', - 'E', - ]); - const {error} = results[2]; - expect(error.name).toBe('ProcessExitError'); - expect(error.exitCode).toBe(42); - expect(error.stderr).toBe('stderr\n'); - }); - }); - - it("doesn't get an exit message when there's an exit error", () => { - waitsForPromise(async () => { - const results = await observeProcess(process.execPath, [ - '-e', - 'process.exit(42);', - ]) - // $FlowIssue: Add materialize to type defs - .materialize() - .toArray() - .toPromise(); - expect(results.length).toBe(1); - expect(results[0].kind).toBe('E'); - }); - }); - - it('accumulates the first `exitErrorBufferSize` bytes of stderr for the exit error', () => { - waitsForPromise(async () => { - let error; - try { - await observeProcess( - process.execPath, - ['-e', 'console.error("stderr"); process.exit(42);'], - {exitErrorBufferSize: 2, isExitError: () => true}, - ) - .toArray() - .toPromise(); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - invariant(error != null); - expect(error.stderr).toBe('st'); - }); - }); - }); - - describe('observeProcessRaw', () => { - it("doesn't split on line breaks", () => { - spyOn(console, 'error'); - spyOn(console, 'log'); // suppress log printing - waitsForPromise({timeout: 1000}, async () => { - const event = await observeProcessRaw(process.execPath, [ - '-e', - 'process.stdout.write("stdout1\\nstdout2\\n"); process.exit(1)', - ]) - .take(1) - .toPromise(); - invariant(event.kind === 'stdout'); - expect(event.data).toBe('stdout1\nstdout2\n'); - }); - }); - }); - - describe('runCommand', () => { - beforeEach(() => { - // Suppress console spew. - spyOn(console, 'error'); - spyOn(console, 'log'); // suppress log printing - }); - - if (origPlatform === 'win32') { - return; - } - - it('sends the stdin to the process', () => { - waitsForPromise(async () => { - const output = await runCommand('cat', [], { - input: 'hello', - }).toPromise(); - expect(output).toBe('hello'); - }); - }); - - it('sends a stream of stdin to the process', () => { - waitsForPromise(async () => { - const input = new Subject(); - const outputPromise = runCommand('cat', [], { - input, - }).toPromise(); - input.next('hello'); - input.next(' '); - input.next('world'); - input.complete(); - expect(await outputPromise).toBe('hello world'); - }); - }); - - it('enforces maxBuffer', () => { - waitsForPromise(async () => { - let error; - try { - await runCommand('yes', [], {maxBuffer: 100}).toPromise(); - } catch (err) { - error = err; - } - invariant(error != null); - expect(error.message).toContain('maxBuffer'); - }); - }); - - it('returns stdout of the running process', () => { - waitsForPromise(async () => { - const val = await runCommand('echo', ['-n', 'foo'], { - env: process.env, - }).toPromise(); - expect(val).toEqual('foo'); - }); - }); - - it("throws an error if the process can't be spawned", () => { - waitsForPromise(async () => { - let error; - try { - await runCommand('fakeCommand').toPromise(); - } catch (err) { - error = err; - } - invariant(error != null); - expect(error.code).toBe('ENOENT'); - expect(error.name).toBe('ProcessSystemError'); - }); - }); - - it('throws an error if the exit code !== 0', () => { - waitsForPromise(async () => { - let error; - try { - await runCommand(process.execPath, [ - '-e', - 'process.exit(1)', - ]).toPromise(); - } catch (err) { - error = err; - } - invariant(error != null); - expect(error.name).toBe('ProcessExitError'); - expect(error.exitCode).toBe(1); - }); - }); - - it('includes stdout and stderr in ProcessExitErrors', () => { - waitsForPromise(async () => { - let error; - try { - await runCommand(process.execPath, [ - '-e', - 'process.stderr.write("oopsy"); process.stdout.write("daisy"); process.exit(1)', - ]).toPromise(); - } catch (err) { - error = err; - } - invariant(error != null); - expect(error.name).toBe('ProcessExitError'); - expect(error.stderr).toBe('oopsy'); - expect(error.stdout).toBe('daisy'); - }); - }); - - it('accumulates the stderr if the process exits with a non-zero code', () => { - waitsForPromise(async () => { - let error; - try { - await runCommand(process.execPath, [ - '-e', - 'process.stderr.write("oopsy"); process.exit(1)', - ]).toPromise(); - } catch (err) { - error = err; - } - invariant(error != null); - expect(error.stderr).toBe('oopsy'); - }); - }); - - // Previously we had a bug where we mutated the seed and subsequent subscriptions would use the - // mutated value. - it("doesn't share a mutable seed (regression test)", () => { - waitsForPromise(async () => { - const observable = runCommand(process.execPath, [ - '-e', - 'process.stdout.write("hello"); process.exit(0)', - ]); - await observable.toPromise(); - expect(await observable.toPromise()).toBe('hello'); - }); - }); - - describe('checkOutput compatibility', () => { - if (origPlatform !== 'win32') { - it('returns stdout of the running process', () => { - waitsForPromise(async () => { - const val = await runCommand('echo', ['-n', 'foo'], { - env: process.env, - }).toPromise(); - expect(val).toEqual('foo'); - }); - }); - it('throws an error if the exit code !== 0', () => { - waitsForPromise({shouldReject: true}, async () => { - await runCommand(process.execPath, [ - '-e', - 'process.exit(1)', - ]).toPromise(); - }); - }); - } - }); - }); - - describe('runCommandDetailed', () => { - beforeEach(() => { - // Suppress console spew. - spyOn(console, 'error'); - spyOn(console, 'log'); // suppress log printing - }); - - if (origPlatform === 'win32') { - return; - } - - it('sends the stdin to the process', () => { - waitsForPromise(async () => { - const output = await runCommandDetailed('cat', [], { - input: 'hello', - }).toPromise(); - expect(output.stdout).toBe('hello'); - }); - }); - - it('enforces maxBuffer', () => { - waitsForPromise(async () => { - let error; - try { - await runCommandDetailed('yes', [], {maxBuffer: 100}).toPromise(); - } catch (err) { - error = err; - } - invariant(error != null); - expect(error.message).toContain('maxBuffer'); - }); - }); - - it('returns stdout, stderr, and the exit code of the running process', () => { - waitsForPromise(async () => { - const val = await runCommandDetailed(process.execPath, [ - '-e', - 'process.stdout.write("out"); process.stderr.write("err"); process.exit(0)', - ]).toPromise(); - expect(val).toEqual({stdout: 'out', stderr: 'err', exitCode: 0}); - }); - }); - - it("throws an error if the process can't be spawned", () => { - waitsForPromise(async () => { - let error; - try { - await runCommandDetailed('fakeCommand').toPromise(); - } catch (err) { - error = err; - } - invariant(error != null); - expect(error.code).toBe('ENOENT'); - expect(error.name).toBe('ProcessSystemError'); - }); - }); - - it('throws an error if the exit code !== 0', () => { - waitsForPromise(async () => { - let error; - try { - await runCommandDetailed(process.execPath, [ - '-e', - 'process.exit(1)', - ]).toPromise(); - } catch (err) { - error = err; - } - invariant(error != null); - expect(error.name).toBe('ProcessExitError'); - expect(error.exitCode).toBe(1); - }); - }); - - it('accumulates the stderr if the process exits with a non-zero code', () => { - waitsForPromise(async () => { - let error; - try { - await runCommandDetailed(process.execPath, [ - '-e', - 'process.stderr.write("oopsy"); process.exit(1)', - ]).toPromise(); - } catch (err) { - error = err; - } - invariant(error != null); - expect(error.stderr).toBe('oopsy'); - }); - }); - }); - - describe('exitEventToMessage', () => { - it('exitCode', () => { - expect(exitEventToMessage(makeExitMessage(1))).toBe('exit code 1'); - }); - - it('signal', () => { - expect( - exitEventToMessage({kind: 'exit', exitCode: null, signal: 'SIGTERM'}), - ).toBe('signal SIGTERM'); - }); - }); - - describe('preventStreamsFromThrowing', () => { - let proc: child_process$ChildProcess; - beforeEach(() => { - proc = ({ - stdin: new EventEmitter(), - stdout: new EventEmitter(), - stderr: new EventEmitter(), - }: any); - spyOn(proc.stdin, 'addListener').andCallThrough(); - spyOn(proc.stdout, 'addListener').andCallThrough(); - spyOn(proc.stderr, 'addListener').andCallThrough(); - spyOn(proc.stdin, 'removeListener').andCallThrough(); - spyOn(proc.stdout, 'removeListener').andCallThrough(); - spyOn(proc.stderr, 'removeListener').andCallThrough(); - }); - - it('adds listeners', () => { - preventStreamsFromThrowing(proc); - expect(proc.stdin.addListener).toHaveBeenCalledWith( - 'error', - jasmine.any(Function), - ); - expect(proc.stdout.addListener).toHaveBeenCalledWith( - 'error', - jasmine.any(Function), - ); - expect(proc.stderr.addListener).toHaveBeenCalledWith( - 'error', - jasmine.any(Function), - ); - }); - - it('removes listeners when disposed', () => { - const disposable = preventStreamsFromThrowing(proc); - disposable.dispose(); - expect(proc.stdin.removeListener).toHaveBeenCalledWith( - 'error', - jasmine.any(Function), - ); - expect(proc.stdout.removeListener).toHaveBeenCalledWith( - 'error', - jasmine.any(Function), - ); - expect(proc.stderr.removeListener).toHaveBeenCalledWith( - 'error', - jasmine.any(Function), - ); - }); - }); - - describe('logStreamErrors', () => { - let proc: child_process$ChildProcess; - beforeEach(() => { - proc = ({ - stdin: new EventEmitter(), - stdout: new EventEmitter(), - stderr: new EventEmitter(), - }: any); - - // Add a no-op listener so the error events aren't thrown. - proc.stdin.on('error', () => {}); - proc.stdout.on('error', () => {}); - proc.stderr.on('error', () => {}); - }); - - it('logs errors', () => { - logStreamErrors(proc, 'test', [], {}); - spyOn(console, 'error'); - proc.stderr.emit('error', new Error('Test error')); - // eslint-disable-next-line no-console - expect(console.error).toHaveBeenCalled(); - }); - - it("doesn't log when disposed", () => { - const disposable = logStreamErrors(proc, 'test', [], {}); - spyOn(console, 'error'); - disposable.dispose(); - proc.stderr.emit('error', new Error('Test error')); - // eslint-disable-next-line no-console - expect(console.error).not.toHaveBeenCalled(); - }); - }); - - describe('ProcessSystemError', () => { - it('contains the correct properties', () => { - const proc = (({}: any): child_process$ChildProcess); - const originalError = { - errno: 2, - code: 'ETEST', - path: 'path value', - syscall: 'syscall value', - }; - const err = new ProcessSystemError(originalError, proc); - expect(err.errno).toBe(2); - expect(err.code).toBe('ETEST'); - expect(err.path).toBe('path value'); - expect(err.syscall).toBe('syscall value'); - expect(err.process).toBe(proc); - }); - }); - - describe('scriptifyCommand', () => { - if (process.platform === 'linux') { - it('escapes correctly on linux', () => { - waitsForPromise(async () => { - const output = await runCommand( - ...scriptifyCommand('echo', [ - 'a\\b c\\\\d e\\\\\\f g\\\\\\\\h "dubs" \'singles\'', - 'one two', - ]), - ).toPromise(); - expect(output.trim()).toBe( - 'a\\b c\\\\d e\\\\\\f g\\\\\\\\h "dubs" \'singles\' one two', - ); - }); - }); - } - }); -}); - -function makeExitMessage(exitCode: number): ProcessExitMessage { - return { - kind: 'exit', - exitCode, - signal: null, - }; -} diff --git a/modules/nuclide-commons/spec/promise-spec.js b/modules/nuclide-commons/spec/promise-spec.js deleted file mode 100644 index 59da50b4..00000000 --- a/modules/nuclide-commons/spec/promise-spec.js +++ /dev/null @@ -1,666 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -/* eslint-disable prefer-promise-reject-errors */ - -import { - asyncFind, - denodeify, - serializeAsyncCall, - asyncLimit, - asyncFilter, - asyncObjFilter, - asyncSome, - lastly, - retryLimit, - RequestSerializer, - TimedOutError, - timeoutPromise, -} from '../promise'; -import invariant from 'assert'; -import {expectAsyncFailure} from '../test-helpers'; - -describe('promises::asyncFind()', () => { - it('Empty list of items should resolve to null.', () => { - let isResolved = false; - let observedResult; - let isRejected = false; - let observedError; - - const args = []; - const test = value => { - throw new Error('Should not be called.'); - }; - - runs(() => { - asyncFind(args, test) - .then(result => { - observedResult = result; - isResolved = true; - }) - .catch(error => { - observedError = error; - isRejected = true; - }); - }); - - waitsFor(() => isResolved || isRejected); - - runs(() => { - expect(isResolved).toBe(true); - expect(observedResult).toBe(null); - expect(isRejected).toBe(false); - expect(observedError).toBe(undefined); - }); - }); - - it('Last item in list resolves.', () => { - let isResolved = false; - let observedResult; - let isRejected = false; - let observedError; - - const args = ['foo', 'bar', 'baz']; - const test = value => { - if (value === 'foo') { - return null; - } else if (value === 'bar') { - return Promise.resolve(null); - } else { - return Promise.resolve('win'); - } - }; - - runs(() => { - asyncFind(args, test) - .then(result => { - observedResult = result; - isResolved = true; - }) - .catch(error => { - observedError = error; - isRejected = true; - }); - }); - - waitsFor(() => isResolved || isRejected); - - runs(() => { - expect(isResolved).toBe(true); - expect(observedResult).toBe('win'); - expect(isRejected).toBe(false); - expect(observedError).toBe(undefined); - }); - }); -}); - -describe('promises::denodeify()', () => { - /** - * Vararg function that assumes that all elements except the last are - * numbers, as the last argument is a callback function. All of the - * other arguments are multiplied together. If the result is not NaN, - * then the callback is called with the product. Otherwise, the callback - * is called with an error. - * - * This function exhibits some of the quirky behavior of Node APIs that - * accept a variable number of arguments in the middle of the parameter list - * rather than at the end. The type signature of this function cannot be - * expressed in Flow. - */ - function asyncProduct(...factors): void { - const callback = factors.pop(); - const product = factors.reduce((previousValue, currentValue) => { - return previousValue * currentValue; - }, 1); - - if (isNaN(product)) { - callback(new Error('product was NaN')); - } else { - callback(null, product); - } - } - - it('resolves Promise when callback succeeds', () => { - const denodeifiedAsyncProduct = denodeify(asyncProduct); - waitsForPromise(async () => { - const trivialProduct = await denodeifiedAsyncProduct(); - expect(trivialProduct).toBe(1); - - const product = await denodeifiedAsyncProduct(1, 2, 3, 4, 5); - expect(product).toBe(120); - }); - }); - - it('rejects Promise when callback fails', () => { - const denodeifiedAsyncProduct = denodeify(asyncProduct); - waitsForPromise(async () => { - await expectAsyncFailure( - denodeifiedAsyncProduct('a', 'b'), - (error: Error) => { - expect(error.message).toBe('product was NaN'); - }, - ); - }); - }); - - function checksReceiver(expectedReceiver, callback) { - if (this === expectedReceiver) { - callback(null, 'winner'); - } else { - callback(new Error('unexpected receiver')); - } - } - - it('result of denodeify propagates receiver as expected', () => { - const denodeifiedChecksReceiver = denodeify(checksReceiver); - - waitsForPromise(async () => { - const receiver = {denodeifiedChecksReceiver}; - const result = await receiver.denodeifiedChecksReceiver(receiver); - expect(result).toBe('winner'); - }); - - waitsForPromise(async () => { - const receiver = {denodeifiedChecksReceiver}; - await expectAsyncFailure( - receiver.denodeifiedChecksReceiver(null), - (error: Error) => { - expect(error.message).toBe('unexpected receiver'); - }, - ); - }); - }); -}); - -describe('promises::serializeAsyncCall()', () => { - it('Returns the same result when called after scheduled', () => { - let i = 0; - const asyncFunSpy = jasmine.createSpy('async'); - const oneAsyncCallAtATime = serializeAsyncCall(() => { - i++; - const resultPromise = waitPromise(10, i); - asyncFunSpy(); - return resultPromise; - }); - // Start an async, and resolve to 1 in 10 ms. - const result1Promise = oneAsyncCallAtATime(); - // Schedule the next async, and resolve to 2 in 20 ms. - const result2Promise = oneAsyncCallAtATime(); - // Reuse scheduled promise and resolve to 2 in 20 ms. - const result3Promise = oneAsyncCallAtATime(); - - advanceClock(11); - // Wait for the promise to call the next chain - // That isn't synchrnously guranteed because it happens on `process.nextTick`. - waitsFor(() => asyncFunSpy.callCount === 2); - waitsForPromise(async () => { - advanceClock(11); - const results = await Promise.all([ - result1Promise, - result2Promise, - result3Promise, - ]); - expect(results).toEqual([1, 2, 2]); - }); - }); - - it('Calls and returns (even if errors) the same number of times if serially called', () => { - waitsForPromise(async () => { - let i = 0; - const oneAsyncCallAtATime = serializeAsyncCall(() => { - i++; - if (i === 4) { - return Promise.reject('ERROR'); - } - return waitPromise(10, i); - }); - const result1Promise = oneAsyncCallAtATime(); - advanceClock(11); - const result1 = await result1Promise; - - const result2Promise = oneAsyncCallAtATime(); - advanceClock(11); - const result2 = await result2Promise; - - const result3Promise = oneAsyncCallAtATime(); - advanceClock(11); - const result3 = await result3Promise; - - const errorPromoise = oneAsyncCallAtATime(); - advanceClock(11); - await expectAsyncFailure(errorPromoise, error => { - expect(error).toBe('ERROR'); - }); - - const result5Promise = oneAsyncCallAtATime(); - advanceClock(11); - const result5 = await result5Promise; - expect([result1, result2, result3, result5]).toEqual([1, 2, 3, 5]); - }); - }); -}); - -describe('promises::asyncLimit()', () => { - beforeEach(() => { - jasmine.useRealClock(); - }); - - it('runs in series if limit is 1', () => { - waitsForPromise(async () => { - const { - result, - parallelismHistory, - } = await captureParallelismHistory(asyncLimit, [ - [1, 2, 3], - 1, - item => waitPromise(10, item + 1), - ]); - expect(parallelismHistory).toEqual([1, 1, 1]); - expect(result).toEqual([2, 3, 4]); - }); - }); - - it('runs with the specified limit, until finishing', () => { - waitsForPromise(async () => { - const { - result, - parallelismHistory, - } = await captureParallelismHistory(asyncLimit, [ - [1, 2, 3, 4, 5, 6, 7, 8, 9], - 3, - item => waitPromise(10 + item, item - 1), - ]); - expect(result).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8]); - expect(parallelismHistory).toEqual([1, 2, 3, 3, 3, 3, 3, 3, 3]); - }); - }); - - it('works when the limit is bigger than the array length', () => { - waitsForPromise(async () => { - const result = await asyncLimit([1, 2, 3], 10, item => - waitPromise(10, item * 2), - ); - expect(result).toEqual([2, 4, 6]); - }); - }); - - it('a rejected promise rejects the whole call with the error', () => { - waitsForPromise(async () => { - await expectAsyncFailure( - asyncLimit([1], 1, async item => { - throw new Error('rejected iterator promise'); - }), - (error: Error) => { - expect(error.message).toBe('rejected iterator promise'); - }, - ); - }); - }); - - it('works when the array is empty', () => { - waitsForPromise(async () => { - const result = await asyncLimit([], 1, () => Promise.resolve()); - expect(result).toEqual([]); - }); - }); -}); - -describe('promises::asyncFilter()', () => { - beforeEach(() => { - jasmine.useRealClock(); - }); - - // eslint-disable-next-line max-len - it('filters an array with an async iterator and maximum parallelization when no limit is specified', () => { - waitsForPromise(async () => { - const { - result: filtered, - parallelismHistory, - } = await captureParallelismHistory(asyncFilter, [ - [1, 2, 3, 4, 5], - item => waitPromise(10 + item, item > 2), - ]); - expect(filtered).toEqual([3, 4, 5]); - expect(parallelismHistory).toEqual([1, 2, 3, 4, 5]); - }); - }); - - it('filters an array with a limit on parallelization', () => { - waitsForPromise(async () => { - const { - result: filtered, - parallelismHistory, - } = await captureParallelismHistory(asyncFilter, [ - [1, 2, 3, 4, 5], - item => waitPromise(10 + item, item > 2), - 3, - ]); - expect(filtered).toEqual([3, 4, 5]); - // Increasing promise resolve time will gurantee maximum parallelization. - expect(parallelismHistory).toEqual([1, 2, 3, 3, 3]); - }); - }); -}); - -describe('promises::asyncObjFilter()', () => { - beforeEach(() => { - jasmine.useRealClock(); - }); - - // eslint-disable-next-line max-len - it('filters an object with an async iterator and maximum parallelization when no limit is specified', () => { - waitsForPromise(async () => { - const { - result: filtered, - parallelismHistory, - } = await captureParallelismHistory(asyncObjFilter, [ - {a: 1, b: 2, c: 3, d: 4, e: 5}, - (value, key) => waitPromise(5 + value, value > 2), - ]); - expect(filtered).toEqual({c: 3, d: 4, e: 5}); - expect(parallelismHistory).toEqual([1, 2, 3, 4, 5]); - }); - }); - - it('filters an array with a limit on parallelization', () => { - waitsForPromise(async () => { - const { - result: filtered, - parallelismHistory, - } = await captureParallelismHistory(asyncObjFilter, [ - {a: 1, b: 2, c: 3, d: 4, e: 5}, - (value, key) => waitPromise(5 + value, value > 2), - 3, - ]); - expect(filtered).toEqual({c: 3, d: 4, e: 5}); - // Increasing promise resolve time will gurantee maximum parallelization. - expect(parallelismHistory).toEqual([1, 2, 3, 3, 3]); - }); - }); -}); - -describe('promises::asyncSome()', () => { - beforeEach(() => { - jasmine.useRealClock(); - }); - - // eslint-disable-next-line max-len - it('some an array with an async iterator and maximum parallelization when no limit is specified', () => { - waitsForPromise(async () => { - const { - result, - parallelismHistory, - } = await captureParallelismHistory(asyncSome, [ - [1, 2, 3, 4, 5], - item => waitPromise(10, item === 6), - ]); - expect(result).toEqual(false); - expect(parallelismHistory).toEqual([1, 2, 3, 4, 5]); - }); - }); - - it('some an array with a limit on parallelization', () => { - waitsForPromise(async () => { - const { - result, - parallelismHistory, - } = await captureParallelismHistory(asyncSome, [ - [1, 2, 3, 4, 5], - item => waitPromise(10 + item, item === 5), - 3, - ]); - expect(result).toEqual(true); - expect(parallelismHistory).toEqual([1, 2, 3, 3, 3]); - }); - }); -}); - -describe('promises::lastly', () => { - it('executes after a resolved promise', () => { - waitsForPromise(async () => { - const spy = jasmine.createSpy('spy'); - const result = await lastly(Promise.resolve(1), spy); - expect(result).toBe(1); - expect(spy).toHaveBeenCalled(); - }); - }); - - it('executes after a rejected promise', () => { - waitsForPromise(async () => { - const spy = jasmine.createSpy('spy'); - await expectAsyncFailure(lastly(Promise.reject(2), spy), err => { - expect(err).toBe(2); - }); - expect(spy).toHaveBeenCalled(); - }); - }); - - it('works for async functions', () => { - waitsForPromise(async () => { - const spy = jasmine.createSpy('spy'); - const result = await lastly(Promise.resolve(1), async () => { - spy(); - }); - expect(result).toBe(1); - expect(spy).toHaveBeenCalled(); - }); - }); -}); - -describe('promises::retryLimit()', () => { - beforeEach(() => { - jasmine.useRealClock(); - }); - - it('retries and fails 2 times before resolving to an acceptable result where limit = 5', () => { - waitsForPromise(async () => { - let succeedAfter = 2; - let calls = 0; - let validationCalls = 0; - const retrialsResult = await retryLimit( - () => { - return new Promise((resolve, reject) => { - calls++; - if (succeedAfter-- === 0) { - resolve('RESULT'); - } else { - reject('ERROR'); - } - }); - }, - result => { - validationCalls++; - return result === 'RESULT'; - }, - 5, - ); - expect(calls).toBe(3); - expect(validationCalls).toBe(1); - expect(retrialsResult).toBe('RESULT'); - }); - }); - - it('retries and fails consistently', () => { - waitsForPromise(async () => { - let calls = 0; - let validationCalls = 0; - const failRetriesPromise = retryLimit( - () => { - calls++; - return Promise.reject('ERROR'); - }, - result => { - validationCalls++; - return result != null; - }, - 2, - ); - await expectAsyncFailure(failRetriesPromise, error => { - expect(error).toBe('ERROR'); - }); - expect(calls).toBe(2); - expect(validationCalls).toBe(0); - }); - }); - - it('accepts a null response', () => { - waitsForPromise(async () => { - let succeedAfter = 2; - let calls = 0; - let validationCalls = 0; - const retryResult = await retryLimit( - () => { - calls++; - if (succeedAfter-- === 0) { - return Promise.resolve(null); - } else { - return Promise.resolve('NOT_GOOD'); - } - }, - result => { - validationCalls++; - return result == null; - }, - 5, - ); - expect(retryResult).toBe(null); - expect(calls).toBe(3); - expect(validationCalls).toBe(3); - }); - }); - - it('no valid response is ever got', () => { - waitsForPromise(async () => { - const nonValidRetriesPromise = retryLimit( - () => { - return Promise.resolve('A'); - }, - result => { - return result === 'B'; - }, - 2, - ); - await expectAsyncFailure(nonValidRetriesPromise, error => { - expect(error.message).toBe('No valid response found!'); - }); - }); - }); -}); - -describe('promises::RequestSerializer()', () => { - let requestSerializer: RequestSerializer = (null: any); - - beforeEach(() => { - jasmine.useRealClock(); - requestSerializer = new RequestSerializer(); - }); - - it('gets outdated result for old promises resolving after newer calls', () => { - waitsForPromise(async () => { - const oldPromise = requestSerializer.run(waitPromise(10, 'OLD')); - const newPromise = requestSerializer.run(waitPromise(5, 'NEW')); - const {status: oldStatus} = await oldPromise; - expect(oldStatus).toBe('outdated'); - const newResult = await newPromise; - invariant(newResult.status === 'success'); - expect(newResult.result).toBe('NEW'); - }); - }); - - it('waitForLatestResult: waits for the latest result', () => { - waitsForPromise(async () => { - requestSerializer.run(waitPromise(5, 'OLD')); - requestSerializer.run(waitPromise(10, 'NEW')); - const latestResult = await requestSerializer.waitForLatestResult(); - expect(latestResult).toBe('NEW'); - }); - }); - - it('waitForLatestResult: waits even if the first run did not kick off', () => { - waitsForPromise(async () => { - const latestResultPromise = requestSerializer.waitForLatestResult(); - requestSerializer.run(waitPromise(10, 'RESULT')); - const latestResult = await latestResultPromise; - expect(latestResult).toBe('RESULT'); - }); - }); - - it('waitForLatestResult: does not wait for the first, if the second resolves faster', () => { - waitsForPromise(async () => { - requestSerializer.run(waitPromise(1000000, 'OLD')); // This will never resolve. - requestSerializer.run(waitPromise(10, 'NEW')); - const latestResult = await requestSerializer.waitForLatestResult(); - expect(latestResult).toBe('NEW'); - }); - }); -}); - -describe('timeoutPromise', () => { - it('should resolve normally if within the timeout', () => { - waitsForPromise(async () => { - const inputPromise = new Promise(resolve => resolve('foo')); - const outputPromise = timeoutPromise(inputPromise, 1000); - expect(await outputPromise).toBe('foo'); - }); - }); - - it('should reject if the given promise rejects', () => { - waitsForPromise(async () => { - const inputPromise = new Promise((resolve, reject) => reject('foo')); - const outputPromise = timeoutPromise(inputPromise, 1000).catch( - value => `rejected with ${value}`, - ); - expect(await outputPromise).toBe('rejected with foo'); - }); - }); - - it('should reject if the given promise takes too long', () => { - waitsForPromise(async () => { - const inputPromise = new Promise(resolve => setTimeout(resolve, 2000)); - const outputPromise = timeoutPromise(inputPromise, 1000).catch( - value => value, - ); - advanceClock(1500); - expect(await outputPromise).toEqual(new TimedOutError(1000)); - }); - }); -}); - -async function captureParallelismHistory( - asyncFunction: (...args: Array) => Promise, - args: Array, -): Promise<{result: mixed, parallelismHistory: Array}> { - const parallelismHistory = []; - let parralelism = 0; - const result = await asyncFunction( - ...args.map(arg => { - if (typeof arg !== 'function') { - return arg; - } - const func = arg; - return async item => { - ++parralelism; - parallelismHistory.push(parralelism); - const value = await func(item); - --parralelism; - return value; - }; - }), - ); - return {result, parallelismHistory}; -} - -function waitPromise(timeoutMs: number, value: any): Promise { - return new Promise((resolve, reject) => { - setTimeout(() => resolve(value), timeoutMs); - }); -} diff --git a/modules/nuclide-commons/spec/range-spec.js b/modules/nuclide-commons/spec/range-spec.js deleted file mode 100644 index e2cef1f7..00000000 --- a/modules/nuclide-commons/spec/range-spec.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import invariant from 'assert'; -import {default as TextBuffer, Range} from 'simple-text-buffer'; -import {wordAtPositionFromBuffer} from '../range'; - -describe('wordAtPositionFromBuffer', () => { - it('matches a word in a buffer', () => { - const buffer = new TextBuffer('word1 word2 word3\n'); - const match = wordAtPositionFromBuffer(buffer, {row: 0, column: 6}, /\S+/g); - expect(match).not.toBeNull(); - invariant(match != null); - expect(match.wordMatch.length).toBe(1); - expect(match.wordMatch[0]).toBe('word2'); - expect(match.range).toEqual(new Range([0, 6], [0, 11])); - }); - - it('should not include endpoints', () => { - const buffer = new TextBuffer('word1 word2 word3\n'); - const match = wordAtPositionFromBuffer(buffer, {row: 0, column: 5}, /\S+/g); - expect(match).toBeNull(); - }); -}); diff --git a/modules/nuclide-commons/spec/shell-quote-spec.js b/modules/nuclide-commons/spec/shell-quote-spec.js deleted file mode 100644 index f542088c..00000000 --- a/modules/nuclide-commons/spec/shell-quote-spec.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import {parse, quote} from '../_shell-quote'; - -/** - * The rest of shell-quote has been verified to work correctly. - * We just need to test the comment parsing. - */ - -describe('shell-quote', () => { - describe('parse', () => { - it('parses comments correctly', () => { - expect(parse('beep#boop')).toEqual(['beep#boop']); - expect(parse('beep #boop')).toEqual(['beep', {comment: 'boop'}]); - expect(parse('beep # boop')).toEqual(['beep', {comment: 'boop'}]); - expect(parse('beep # > boop')).toEqual(['beep', {comment: '> boop'}]); - expect(parse('beep # "> boop"')).toEqual(['beep', {comment: '"> boop"'}]); - expect(parse('beep "#"')).toEqual(['beep', '#']); - expect(parse('beep #"#"#')).toEqual(['beep', {comment: '"#"#'}]); - expect(parse('beep > boop # > foo')).toEqual([ - 'beep', - {op: '>'}, - 'boop', - {comment: '> foo'}, - ]); - }); - }); - - describe('quote', () => { - expect(quote(['X#(){}*|][!'])).toBe('X\\#\\(\\)\\{\\}\\*\\|\\]\\[\\!'); - }); -}); diff --git a/modules/nuclide-commons/spec/stream-spec.js b/modules/nuclide-commons/spec/stream-spec.js deleted file mode 100644 index 1ff083bf..00000000 --- a/modules/nuclide-commons/spec/stream-spec.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import {observeStream, observeRawStream, writeToStream} from '../stream'; -import fsPromise from '../fsPromise'; -import Stream from 'stream'; -import fs from 'fs'; - -describe('commons-node/stream', () => { - it('observeStream', () => { - waitsForPromise(async () => { - const input = ['foo\nbar', '\n', '\nba', 'z', '\nblar']; - const stream = new Stream.PassThrough(); - const promise = observeStream(stream).toArray().toPromise(); - input.forEach(value => { - stream.write(value, 'utf8'); - }); - stream.end(); - const output = await promise; - expect(output.join('')).toEqual(input.join('')); - }); - }); - - it('observeStream - error', () => { - waitsForPromise(async () => { - const stream = new Stream.PassThrough(); - const input = ['foo\nbar', '\n', '\nba', 'z', '\nblar']; - const output = []; - const promise = new Promise((resolve, reject) => { - observeStream(stream).subscribe( - v => output.push(v), - e => resolve(e), - () => {}, - ); - }); - const error = new Error('Had an error'); - - input.forEach(value => { - stream.write(value, 'utf8'); - }); - stream.emit('error', error); - - const result = await promise; - expect(output).toEqual(input); - expect(result).toBe(error); - }); - }); - - it('writeToStream', () => { - waitsForPromise(async () => { - const tempPath = await fsPromise.tempfile(); - const fixturePath = 'spec/fixtures/lyrics'; - const stream = fs.createWriteStream(tempPath, {highWaterMark: 10}); - // Read faster than we write to test buffering - const observable = observeRawStream( - fs.createReadStream(fixturePath, {highWaterMark: 100}), - ); - - await writeToStream(observable, stream).toPromise(); - - const writtenFile = await fsPromise.readFile(tempPath); - const fixtureFile = await fsPromise.readFile(fixturePath); - expect(writtenFile).toEqual(fixtureFile); - }); - }); -}); diff --git a/modules/nuclide-commons/spec/string-spec.js b/modules/nuclide-commons/spec/string-spec.js deleted file mode 100644 index a3e5bc54..00000000 --- a/modules/nuclide-commons/spec/string-spec.js +++ /dev/null @@ -1,291 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import { - capitalize, - countOccurrences, - indent, - maybeToString, - pluralize, - relativeDate, - removeCommonPrefix, - removeCommonSuffix, - shellParse, - shorten, - splitOnce, -} from '../string'; - -describe('relativeDate', () => { - it('works', () => { - const SECOND = 1000; - const MINUTE = 60 * SECOND; - const HOUR = 60 * MINUTE; - const DAY = 24 * HOUR; - const WEEK = 7 * DAY; - const YEAR = DAY * 365; - const MONTH = YEAR / 12; - - const reference = 157765000000; // 01.01.1975 00:00 - const now = new Date().getTime(); - - // test long format - expect(relativeDate(0)).toEqual(Math.round(now / YEAR) + ' years ago'); - expect(relativeDate(reference * SECOND, reference)).toEqual('just now'); - expect(relativeDate(reference - 41 * SECOND, reference)).toEqual( - 'just now', - ); - expect(relativeDate(reference - 42 * SECOND, reference)).toEqual( - 'a minute ago', - ); - expect(relativeDate(reference - MINUTE, reference)).toEqual('a minute ago'); - expect(relativeDate(reference - MINUTE * 1.5, reference)).toEqual( - '2 minutes ago', - ); - expect(relativeDate(reference - MINUTE * 59, reference)).toEqual( - '59 minutes ago', - ); - expect(relativeDate(reference - HOUR, reference)).toEqual('an hour ago'); - expect(relativeDate(reference - HOUR * 1.5, reference)).toEqual( - '2 hours ago', - ); - expect(relativeDate(reference - HOUR * 16, reference)).toEqual( - '16 hours ago', - ); - expect(relativeDate(reference - HOUR * 23, reference)).toEqual( - '23 hours ago', - ); - expect(relativeDate(reference - DAY * 1.8, reference)).toEqual('yesterday'); - expect(relativeDate(reference - DAY * 3, reference)).toEqual('3 days ago'); - expect(relativeDate(reference - DAY * 6, reference)).toEqual('6 days ago'); - expect(relativeDate(reference - WEEK, reference)).toEqual('a week ago'); - expect(relativeDate(reference - WEEK * 2, reference)).toEqual( - '2 weeks ago', - ); - expect(relativeDate(reference - WEEK * 4, reference)).toEqual( - '4 weeks ago', - ); - expect(relativeDate(reference - MONTH * 1.2, reference)).toEqual( - 'a month ago', - ); - expect(relativeDate(reference - YEAR + HOUR, reference)).toEqual( - '12 months ago', - ); - expect(relativeDate(reference - YEAR, reference)).toEqual('a year ago'); - expect(relativeDate(reference - YEAR * 2, reference)).toEqual( - '2 years ago', - ); - expect(relativeDate(0, reference)).toEqual('5 years ago'); - - // test short format - expect(relativeDate(0, undefined, /* short */ true)).toEqual( - Math.round(now / YEAR) + 'y', - ); - expect( - relativeDate(reference * SECOND, reference, /* short */ true), - ).toEqual('now'); - expect( - relativeDate(reference - 41 * SECOND, reference, /* short */ true), - ).toEqual('now'); - expect( - relativeDate(reference - 42 * SECOND, reference, /* short */ true), - ).toEqual('1m'); - expect( - relativeDate(reference - MINUTE, reference, /* short */ true), - ).toEqual('1m'); - expect( - relativeDate(reference - MINUTE * 1.5, reference, /* short */ true), - ).toEqual('2m'); - expect( - relativeDate(reference - MINUTE * 59, reference, /* short */ true), - ).toEqual('59m'); - expect(relativeDate(reference - HOUR, reference, /* short */ true)).toEqual( - '1h', - ); - expect( - relativeDate(reference - HOUR * 1.5, reference, /* short */ true), - ).toEqual('2h'); - expect( - relativeDate(reference - HOUR * 16, reference, /* short */ true), - ).toEqual('16h'); - expect( - relativeDate(reference - HOUR * 23, reference, /* short */ true), - ).toEqual('23h'); - expect( - relativeDate(reference - DAY * 1.8, reference, /* short */ true), - ).toEqual('1d'); - expect( - relativeDate(reference - DAY * 3, reference, /* short */ true), - ).toEqual('3d'); - expect( - relativeDate(reference - DAY * 6, reference, /* short */ true), - ).toEqual('6d'); - expect(relativeDate(reference - WEEK, reference, /* short */ true)).toEqual( - '1w', - ); - expect( - relativeDate(reference - WEEK * 2, reference, /* short */ true), - ).toEqual('2w'); - expect( - relativeDate(reference - WEEK * 4, reference, /* short */ true), - ).toEqual('4w'); - expect( - relativeDate(reference - MONTH * 1.2, reference, /* short */ true), - ).toEqual('1mo'); - expect( - relativeDate(reference - YEAR + HOUR, reference, /* short */ true), - ).toEqual('12mo'); - expect(relativeDate(reference - YEAR, reference, /* short */ true)).toEqual( - '1y', - ); - expect( - relativeDate(reference - YEAR * 2, reference, /* short */ true), - ).toEqual('2y'); - expect(relativeDate(0, reference, /* short */ true)).toEqual('5y'); - }); -}); - -describe('maybeToString', () => { - it("returns 'undefined'", () => { - expect(maybeToString(undefined)).toEqual('undefined'); - }); - - it("returns 'null'", () => { - expect(maybeToString(null)).toEqual('null'); - }); - - it('returns an ordinary string', () => { - expect(maybeToString('foo')).toEqual('foo'); - }); -}); - -describe('countOccurrences', () => { - it('counts the number of characters', () => { - expect(countOccurrences('abcaaa', 'a')).toBe(4); - }); - - it('throws for non-length-1 searches', () => { - expect(() => { - countOccurrences('abc', 'abc'); - }).toThrow(); - }); -}); - -describe('shellParse', () => { - it('parses a list of arguments', () => { - expect(shellParse('1 2 3 "a b c"')).toEqual(['1', '2', '3', 'a b c']); - }); - - it('throws if operators are given', () => { - expect(() => { - shellParse('a | b'); - }).toThrow(Error('Unexpected operator "|" provided to shellParse')); - expect(() => { - shellParse('a > b'); - }).toThrow(Error('Unexpected operator ">" provided to shellParse')); - }); -}); - -describe('removeCommonPrefix', () => { - it('does nothing if there is no common prefix', () => { - expect(removeCommonPrefix('foo', 'bar')).toEqual(['foo', 'bar']); - }); - - it('removes a common prefix', () => { - expect(removeCommonPrefix('foo', 'fbar')).toEqual(['oo', 'bar']); - expect(removeCommonPrefix('asdffoo', 'asdfbar')).toEqual(['foo', 'bar']); - }); - - it('works with the empty string', () => { - expect(removeCommonPrefix('', 'bar')).toEqual(['', 'bar']); - expect(removeCommonPrefix('foo', '')).toEqual(['foo', '']); - expect(removeCommonPrefix('', '')).toEqual(['', '']); - }); - - it('returns empty strings for identical strings', () => { - expect(removeCommonPrefix('foo', 'foo')).toEqual(['', '']); - }); -}); - -describe('removeCommonSuffix', () => { - it('does nothing if there is no common suffix', () => { - expect(removeCommonSuffix('foo', 'bar')).toEqual(['foo', 'bar']); - }); - - it('removes a common suffix', () => { - expect(removeCommonSuffix('foo', 'baro')).toEqual(['fo', 'bar']); - expect(removeCommonSuffix('fooasdf', 'baroasdf')).toEqual(['fo', 'bar']); - }); - - it('works with the empty string', () => { - expect(removeCommonSuffix('', 'bar')).toEqual(['', 'bar']); - expect(removeCommonSuffix('foo', '')).toEqual(['foo', '']); - expect(removeCommonSuffix('', '')).toEqual(['', '']); - }); - - it('returns empty strings for identical strings', () => { - expect(removeCommonSuffix('foo', 'foo')).toEqual(['', '']); - }); -}); - -describe('shorten', () => { - it('works', () => { - expect(shorten('', 1)).toEqual(''); - expect(shorten('test', 3)).toEqual('tes'); - expect(shorten('test', 100)).toEqual('test'); - expect(shorten('test', 1, '...')).toEqual('t...'); - }); -}); - -describe('splitOnce', () => { - it('splits once', () => { - expect(splitOnce('ab-cd-ef', '-')).toEqual(['ab', 'cd-ef']); - }); - it("handles when there's no match", () => { - expect(splitOnce('ab-cd-ef', '_')).toEqual(['ab-cd-ef', null]); - }); -}); - -describe('indent', () => { - it('indents lines', () => { - expect(indent('a\nb')).toBe(' a\n b'); - }); - - it("doesn't indent empty lines", () => { - expect(indent('a\n\nb')).toBe(' a\n\n b'); - }); - - it('uses the provided level', () => { - expect(indent('a\n\nb', 4)).toBe(' a\n\n b'); - }); - - it('uses the provided character', () => { - expect(indent('a\n\nb', 1, '\t')).toBe('\ta\n\n\tb'); - }); -}); - -describe('pluralize', () => { - it('works', () => { - expect(pluralize('test', 0)).toEqual('tests'); - expect(pluralize('test', 1)).toEqual('test'); - expect(pluralize('test', 2)).toEqual('tests'); - expect(pluralize('test', 123)).toEqual('tests'); - }); -}); - -describe('capitalize', () => { - it('works', () => { - expect(capitalize('')).toEqual(''); - expect(capitalize('t')).toEqual('T'); - expect(capitalize('te')).toEqual('Te'); - expect(capitalize('test')).toEqual('Test'); - }); -}); diff --git a/modules/nuclide-commons/spec/symbol-definition-preview-spec.js b/modules/nuclide-commons/spec/symbol-definition-preview-spec.js deleted file mode 100644 index affb390c..00000000 --- a/modules/nuclide-commons/spec/symbol-definition-preview-spec.js +++ /dev/null @@ -1,203 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import nuclideUri from '../nuclideUri'; -import dedent from 'dedent'; -import {Point} from 'simple-text-buffer'; -import {getDefinitionPreview} from '../symbol-definition-preview'; -import invariant from 'invariant'; - -function javascriptFixtureDefinitionWithPoint(point: Point) { - return { - path: nuclideUri.join( - __dirname, - 'fixtures', - 'symbol-definition-preview-sample.js', - ), - language: 'javascript', - position: point, - }; -} - -function pythonFixtureDefinitionWithPoint(point: Point) { - return { - path: nuclideUri.join( - __dirname, - 'fixtures', - 'symbol-definition-preview-sample.py', - ), - language: 'python', - position: point, - }; -} - -describe('getDefinitionPreview', () => { - describe('Constant symbols', () => { - it('returns the only line of a one-line symbol', () => { - waitsForPromise(async () => { - const preview = await getDefinitionPreview( - javascriptFixtureDefinitionWithPoint(new Point(11, 6)), - ); - - expect(preview).not.toBeNull(); - invariant(preview != null); - expect(preview.contents).toEqual('const A_CONSTANT = 42;'); - }); - }); - - it('returns the entire multi-line symbol', () => { - waitsForPromise(async () => { - const preview = await getDefinitionPreview( - javascriptFixtureDefinitionWithPoint(new Point(15, 6)), - ); - - expect(preview).not.toBeNull(); - invariant(preview != null); - expect(preview.contents).toEqual( - dedent`const A_MULTILINE_CONST = \` - hey look I span - multiple - lines - \`;`, - ); - }); - }); - }); - - describe('Type symbols', () => { - it('returns an entire multi-line type', () => { - waitsForPromise(async () => { - const preview = await getDefinitionPreview( - javascriptFixtureDefinitionWithPoint(new Point(21, 5)), - ); - - expect(preview).not.toBeNull(); - invariant(preview != null); - expect(preview.contents).toEqual( - dedent`type Something = { - name: string, - age?: number, - };`, - ); - }); - }); - - it('returns only the property from within a type', () => { - waitsForPromise(async () => { - const preview = await getDefinitionPreview( - javascriptFixtureDefinitionWithPoint(new Point(44, 4)), - ); - - expect(preview).not.toBeNull(); - invariant(preview != null); - expect(preview.contents).toEqual('name: string,'); - }); - }); - - it('returns property and value of a complex type within a type', () => { - waitsForPromise(async () => { - const preview = await getDefinitionPreview( - javascriptFixtureDefinitionWithPoint(new Point(43, 2)), - ); - - expect(preview).not.toBeNull(); - invariant(preview != null); - expect(preview.contents).toEqual( - dedent`properties: { - name: string, - age?: number, - },`, - ); - }); - }); - }); - - describe('Function symbols', () => { - it('returns just one line if parens are balanced on the first line', () => { - waitsForPromise(async () => { - const preview = await getDefinitionPreview( - javascriptFixtureDefinitionWithPoint(new Point(26, 16)), - ); - - expect(preview).not.toBeNull(); - invariant(preview != null); - expect(preview.contents).toEqual( - 'export function aSingleLineFunctionSignature() {', - ); - }); - }); - - it('works without parentheses as with python', () => { - waitsForPromise(async () => { - const preview = await getDefinitionPreview( - pythonFixtureDefinitionWithPoint(new Point(7, 4)), - ); - - expect(preview).not.toBeNull(); - invariant(preview != null); - expect(preview.contents).toEqual('def foo(bar=27):'); - }); - }); - - it('works without parentheses but with braces as with python', () => { - waitsForPromise(async () => { - const preview = await getDefinitionPreview( - pythonFixtureDefinitionWithPoint(new Point(11, 4)), - ); - - expect(preview).not.toBeNull(); - invariant(preview != null); - expect(preview.contents).toEqual( - dedent`def baz(test={ - 'one': 'two' - }):`, - ); - }); - }); - - it('doesnt dedent beyond the current lines indentation level', () => { - waitsForPromise(async () => { - const preview = await getDefinitionPreview( - javascriptFixtureDefinitionWithPoint(new Point(36, 18)), - ); - - expect(preview).not.toBeNull(); - invariant(preview != null); - expect(preview.contents).toEqual( - dedent` - export function aPoorlyIndentedFunction( - aReallyReallyLongArgumentNameThatWouldRequireThisToBreakAcrossMultipleLines: Something, - ): number { - `, - ); - }); - }); - - it('reads until the indentation returns to initial and parens are balanced', () => { - waitsForPromise(async () => { - const preview = await getDefinitionPreview( - javascriptFixtureDefinitionWithPoint(new Point(30, 16)), - ); - - expect(preview).not.toBeNull(); - invariant(preview != null); - expect(preview.contents).toEqual( - dedent` - export function aMultiLineFunctionSignature( - aReallyReallyLongArgumentNameThatWouldRequireThisToBreakAcrossMultipleLines: Something, - ): number { - `, - ); - }); - }); - }); -}); diff --git a/modules/nuclide-commons/spec/test-helpers-spec.js b/modules/nuclide-commons/spec/test-helpers-spec.js deleted file mode 100644 index 17071821..00000000 --- a/modules/nuclide-commons/spec/test-helpers-spec.js +++ /dev/null @@ -1,192 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import typeof * as TestModuleType from './fixtures/toBeTested'; - -import fs from 'fs'; -import glob from 'glob'; -import nuclideUri from '../nuclideUri'; -import { - arePropertiesEqual, - clearRequireCache, - expectAsyncFailure, - generateFixture, - uncachedRequire, -} from '../test-helpers'; - -describe('arePropertiesEqual', () => { - it('correctly compares empty objects', () => { - expect(arePropertiesEqual({}, {})).toBe(true); - }); - - it('correctly compares objects with the same properties', () => { - expect(arePropertiesEqual({foo: 5}, {foo: 5})).toBe(true); - }); - - it('allows one property to be undefined while another does not exist at all', () => { - expect(arePropertiesEqual({foo: undefined}, {})).toBe(true); - }); - - it('returns false when properties are not equal', () => { - expect(arePropertiesEqual({foo: 5}, {foo: 4})).toBe(false); - }); - - it('returns false when one property is undefined and another is defined', () => { - expect(arePropertiesEqual({foo: 5}, {foo: undefined})).toBe(false); - expect(arePropertiesEqual({foo: undefined}, {foo: 5})).toBe(false); - }); - - it('returns false when one property exists but the other does not', () => { - expect(arePropertiesEqual({foo: 5}, {})).toBe(false); - expect(arePropertiesEqual({}, {foo: 5})).toBe(false); - }); -}); - -describe('expectAsyncFailure', () => { - it('fails when provided Promise succeeds', () => { - const verify: any = jasmine.createSpy(); - waitsForPromise({shouldReject: true}, () => { - return expectAsyncFailure( - Promise.resolve('resolved, not rejected!'), - verify, - ); - }); - runs(() => { - expect(verify.callCount).toBe(0); - }); - }); - - it('fails when provided Promise fails but with wrong error message', () => { - let callCount = 0; - function verify(error) { - ++callCount; - const expectedMessage = 'I failed badly.'; - if (error.message !== expectedMessage) { - throw Error(`Expected '${expectedMessage}', but was ${error.message}.`); - } - } - - waitsForPromise({shouldReject: true}, () => { - return expectAsyncFailure(Promise.reject(Error('I failed.')), verify); - }); - runs(() => { - expect(callCount).toBe(1); - }); - }); - - it('succeeds when provided Promise fails in the expected way', () => { - let callCount = 0; - function verify(error) { - ++callCount; - const expectedMessage = 'I failed badly.'; - if (error.message !== expectedMessage) { - throw Error(`Expected '${expectedMessage}', but was ${error.message}.`); - } - } - - waitsForPromise({shouldReject: false}, () => { - return expectAsyncFailure( - Promise.reject(Error('I failed badly.')), - verify, - ); - }); - runs(() => { - expect(callCount).toBe(1); - }); - }); -}); - -describe('generateFixture', () => { - it('should create the directory hierarchy', () => { - waitsForPromise(async () => { - const fixturePath = await generateFixture( - 'fixture-to-generate', - new Map([['foo.js', undefined], ['bar/baz.txt', 'some text']]), - ); - - expect(nuclideUri.isAbsolute(fixturePath)).toBe(true); - expect(fs.statSync(fixturePath).isDirectory()).toBe(true); - - const fooPath = nuclideUri.join(fixturePath, 'foo.js'); - const bazPath = nuclideUri.join(fixturePath, 'bar/baz.txt'); - - expect(fs.statSync(fooPath).isFile()).toBe(true); - expect(fs.statSync(bazPath).isFile()).toBe(true); - - expect(fs.readFileSync(fooPath, 'utf8')).toBe(''); - expect(fs.readFileSync(bazPath, 'utf8')).toBe('some text'); - }); - }); - - it('should work with lots of files', () => { - waitsForPromise({timeout: 10000}, async () => { - const files = new Map(); - for (let i = 0; i < 10; i++) { - for (let j = 0; j < 1000; j++) { - files.set(`dir_${i}/file_${j}.txt`, `${i} + ${j} = ${i + j}`); - } - } - const fixturePath = await generateFixture('lots-of-files', files); - const fixtureFiles = glob.sync( - nuclideUri.join(fixturePath, 'dir_*/file_*.txt'), - ); - expect(fixtureFiles.length).toBe(10000); - }); - }); - - it('should work with no files', () => { - waitsForPromise(async () => { - const fixturePath = await generateFixture('fixture-empty', new Map()); - expect(nuclideUri.isAbsolute(fixturePath)).toBe(true); - expect(fs.statSync(fixturePath).isDirectory()).toBe(true); - expect(fs.readdirSync(fixturePath)).toEqual([]); - }); - }); - - it('works with no files arg', () => { - waitsForPromise(async () => { - const fixturePath = await generateFixture('fixture-empty'); - expect(nuclideUri.isAbsolute(fixturePath)).toBe(true); - expect(fs.statSync(fixturePath).isDirectory()).toBe(true); - expect(fs.readdirSync(fixturePath)).toEqual([]); - }); - }); -}); - -describe('Mocking Imports test suite', () => { - // Tests ToBeTested.functionToTest while mocking imported function toBeMocked. - it('Mocking imported dependencies', () => { - // 1 - First mock all functions imported by the module under test - const mock = spyOn( - require('./fixtures/toBeMocked'), - 'importedFunction', - ).andReturn(45); - - // 2 - Do an uncachedRequire of the module to test - // Note the 'import typeof * as ... ' above to get type checking - // for the functions to be tested. - // You may want to put steps 1 & 2 in your beforeEach. - const moduleToTest: TestModuleType = (uncachedRequire( - require, - './fixtures/toBeTested', - ): any); - - // 3 - Perform your test - const result = moduleToTest.functionToTest(); - expect(mock).toHaveBeenCalledWith(42); - expect(result).toEqual(45); - - // 4 - Reset the require cache so your mocks don't get used for other tests. - // You may want to put this in your afterEach. - clearRequireCache(require, './fixtures/toBeTested'); - }); -}); diff --git a/modules/nuclide-commons/spec/which-spec.js b/modules/nuclide-commons/spec/which-spec.js deleted file mode 100644 index 230ee102..00000000 --- a/modules/nuclide-commons/spec/which-spec.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import which from '../which'; -import {Observable} from 'rxjs'; - -describe('which', () => { - let runCommand: JasmineSpy; - let runCommandReturn = ''; - - beforeEach(() => { - runCommandReturn = ''; - runCommand = spyOn(require('../process'), 'runCommand').andCallFake(() => - Observable.of(runCommandReturn), - ); - }); - - afterEach(() => { - jasmine.unspy(require('../process'), 'runCommand'); - }); - - describe('on windows', () => { - const real_platform: string = process.platform; - const eol = '\r\n'; - const os = require('os'); - const real_eol = os.EOL; - beforeEach(() => { - Object.defineProperty(process, 'platform', {value: 'win32'}); - os.EOL = eol; - }); - afterEach(() => { - Object.defineProperty(process, 'platform', {value: real_platform}); - os.EOL = real_eol; - }); - - it('calls where on Windows', () => { - const param: string = ''; - which(param); - expect(runCommand).toHaveBeenCalledWith('where', ['']); - }); - - it('returns the first match', () => { - waitsForPromise(async () => { - runCommandReturn = 'hello' + os.EOL + 'hello.exe' + os.EOL; - const ret = await which('bla'); - expect(ret).toEqual('hello'); - }); - }); - }); - - describe('on linux', () => { - const real_platform: string = process.platform; - const eol = '\n'; - const os = require('os'); - const real_eol = os.EOL; - beforeEach(() => { - Object.defineProperty(process, 'platform', {value: 'linux'}); - os.EOL = eol; - }); - afterEach(() => { - Object.defineProperty(process, 'platform', {value: real_platform}); - os.EOL = real_eol; - }); - - it('calls which', () => { - const param: string = ''; - which(param); - expect(runCommand).toHaveBeenCalledWith('which', [param]); - }); - - it('returns the first match', () => { - waitsForPromise(async () => { - runCommandReturn = 'hello' + os.EOL + '/bin/hello' + os.EOL; - const ret = await which('bla'); - expect(ret).toEqual('hello'); - }); - }); - }); -}); diff --git a/modules/nuclide-commons/stream.js b/modules/nuclide-commons/stream.js index 35180107..482a040b 100644 --- a/modules/nuclide-commons/stream.js +++ b/modules/nuclide-commons/stream.js @@ -1,3 +1,33 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.observeStream = observeStream; +exports.observeRawStream = observeRawStream; +exports.writeToStream = writeToStream; + +var _stream = _interopRequireDefault(require('stream')); + +var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); + +var _UniversalDisposable; + +function _load_UniversalDisposable() { + return _UniversalDisposable = _interopRequireDefault(require('./UniversalDisposable')); +} + +var _event; + +function _load_event() { + return _event = require('./event'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Observe a stream like stdout or stderr. + */ /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,69 +36,47 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import Stream from 'stream'; -import {Observable} from 'rxjs'; - -import UniversalDisposable from './UniversalDisposable'; -import {attachEvent} from './event'; - -/** - * Observe a stream like stdout or stderr. - */ -export function observeStream(stream: stream$Readable): Observable { +function observeStream(stream) { return observeRawStream(stream).map(data => data.toString()); } -export function observeRawStream(stream: stream$Readable): Observable { - const error = Observable.fromEvent(stream, 'error').flatMap(Observable.throw); - return Observable.fromEvent(stream, 'data') - .merge(error) - .takeUntil(Observable.fromEvent(stream, 'end')); +function observeRawStream(stream) { + const error = _rxjsBundlesRxMinJs.Observable.fromEvent(stream, 'error').flatMap(_rxjsBundlesRxMinJs.Observable.throw); + return _rxjsBundlesRxMinJs.Observable.fromEvent(stream, 'data').merge(error).takeUntil(_rxjsBundlesRxMinJs.Observable.fromEvent(stream, 'end')); } /** * Write an observed readable stream into a writeable stream. Effectively a pipe() for observables. * Returns an observable accumulating the number of bytes processed. */ -export function writeToStream( - source: Observable, - destStream: stream$Writable, -): Observable { - return Observable.create(observer => { +function writeToStream(source, destStream) { + return _rxjsBundlesRxMinJs.Observable.create(observer => { let byteCount = 0; - const byteCounterStream = new Stream.Transform({ + const byteCounterStream = new _stream.default.Transform({ transform(chunk, encoding, cb) { byteCount += chunk.byteLength; observer.next(byteCount); cb(null, chunk); - }, + } }); byteCounterStream.pipe(destStream); - return new UniversalDisposable( - attachEvent(destStream, 'error', err => { - observer.error(err); - }), - attachEvent(destStream, 'close', () => { - observer.complete(); - }), - source.subscribe( - buffer => { - byteCounterStream.write(buffer); - }, - err => { - observer.error(err); - }, - () => { - byteCounterStream.end(); - }, - ), - ); + return new (_UniversalDisposable || _load_UniversalDisposable()).default((0, (_event || _load_event()).attachEvent)(destStream, 'error', err => { + observer.error(err); + }), (0, (_event || _load_event()).attachEvent)(destStream, 'close', () => { + observer.complete(); + }), source.subscribe(buffer => { + byteCounterStream.write(buffer); + }, err => { + observer.error(err); + }, () => { + byteCounterStream.end(); + })); }).share(); -} +} \ No newline at end of file diff --git a/modules/nuclide-commons/string.js b/modules/nuclide-commons/string.js index e43e265d..f927ad87 100644 --- a/modules/nuclide-commons/string.js +++ b/modules/nuclide-commons/string.js @@ -1,3 +1,29 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.URL_REGEX = undefined; +exports.stringifyError = stringifyError; +exports.maybeToString = maybeToString; +exports.relativeDate = relativeDate; +exports.countOccurrences = countOccurrences; +exports.shellParse = shellParse; +exports.shellQuote = shellQuote; +exports.removeCommonPrefix = removeCommonPrefix; +exports.removeCommonSuffix = removeCommonSuffix; +exports.shorten = shorten; +exports.splitOnce = splitOnce; +exports.indent = indent; +exports.pluralize = pluralize; +exports.capitalize = capitalize; + +var _shellQuote; + +function _load_shellQuote() { + return _shellQuote = require('./_shell-quote'); +} + /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. @@ -6,20 +32,17 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @flow + * * @format */ -import invariant from 'assert'; -import {parse, quote} from './_shell-quote'; - -export function stringifyError(error: Error): string { +function stringifyError(error) { return `name: ${error.name}, message: ${error.message}, stack: ${error.stack}.`; } // As of Flow v0.28, Flow does not alllow implicit string coercion of null or undefined. Use this to // make it explicit. -export function maybeToString(str: ?string): string { +function maybeToString(str) { // We don't want to encourage the use of this function directly because it coerces anything to a // string. We get stricter typechecking by using maybeToString, so it should generally be // preferred. @@ -38,43 +61,11 @@ const WEEK = 7 * DAY; const YEAR = DAY * 365; const MONTH = YEAR / 12; -const shortFormats = [ - [0.7 * MINUTE, 'now'], - [1.5 * MINUTE, '1m'], - [60 * MINUTE, 'm', MINUTE], - [1.5 * HOUR, '1h'], - [DAY, 'h', HOUR], - [2 * DAY, '1d'], - [7 * DAY, 'd', DAY], - [1.5 * WEEK, '1w'], - [MONTH, 'w', WEEK], - [1.5 * MONTH, '1mo'], - [YEAR, 'mo', MONTH], - [1.5 * YEAR, '1y'], - [Number.MAX_VALUE, 'y', YEAR], -]; - -const longFormats = [ - [0.7 * MINUTE, 'just now'], - [1.5 * MINUTE, 'a minute ago'], - [60 * MINUTE, 'minutes ago', MINUTE], - [1.5 * HOUR, 'an hour ago'], - [DAY, 'hours ago', HOUR], - [2 * DAY, 'yesterday'], - [7 * DAY, 'days ago', DAY], - [1.5 * WEEK, 'a week ago'], - [MONTH, 'weeks ago', WEEK], - [1.5 * MONTH, 'a month ago'], - [YEAR, 'months ago', MONTH], - [1.5 * YEAR, 'a year ago'], - [Number.MAX_VALUE, 'years ago', YEAR], -]; - -export function relativeDate( - input_: number | Date, - reference_?: number | Date, - useShortVariant?: boolean = false, -): string { +const shortFormats = [[0.7 * MINUTE, 'now'], [1.5 * MINUTE, '1m'], [60 * MINUTE, 'm', MINUTE], [1.5 * HOUR, '1h'], [DAY, 'h', HOUR], [2 * DAY, '1d'], [7 * DAY, 'd', DAY], [1.5 * WEEK, '1w'], [MONTH, 'w', WEEK], [1.5 * MONTH, '1mo'], [YEAR, 'mo', MONTH], [1.5 * YEAR, '1y'], [Number.MAX_VALUE, 'y', YEAR]]; + +const longFormats = [[0.7 * MINUTE, 'just now'], [1.5 * MINUTE, 'a minute ago'], [60 * MINUTE, 'minutes ago', MINUTE], [1.5 * HOUR, 'an hour ago'], [DAY, 'hours ago', HOUR], [2 * DAY, 'yesterday'], [7 * DAY, 'days ago', DAY], [1.5 * WEEK, 'a week ago'], [MONTH, 'weeks ago', WEEK], [1.5 * MONTH, 'a month ago'], [YEAR, 'months ago', MONTH], [1.5 * YEAR, 'a year ago'], [Number.MAX_VALUE, 'years ago', YEAR]]; + +function relativeDate(input_, reference_, useShortVariant = false) { let input = input_; let reference = reference_; if (input instanceof Date) { @@ -93,11 +84,7 @@ export function relativeDate( for (const [limit, relativeFormat, remainder] of formats) { if (delta < limit) { if (typeof remainder === 'number') { - return ( - Math.round(delta / remainder) + - (useShortVariant ? '' : ' ') + - relativeFormat - ); + return Math.round(delta / remainder) + (useShortVariant ? '' : ' ') + relativeFormat; } else { return relativeFormat; } @@ -111,8 +98,10 @@ export function relativeDate( * Count the number of occurrences of `char` in `str`. * `char` must be a string of length 1. */ -export function countOccurrences(haystack: string, char: string) { - invariant(char.length === 1, 'char must be a string of length 1'); +function countOccurrences(haystack, char) { + if (!(char.length === 1)) { + throw new Error('char must be a string of length 1'); + } let count = 0; const code = char.charCodeAt(0); @@ -128,18 +117,14 @@ export function countOccurrences(haystack: string, char: string) { * shell-quote's parse allows pipe operators and comments. * Generally users don't care about this, so throw if we encounter any operators. */ -export function shellParse(str: string, env?: Object): Array { - const result = parse(str, env); +function shellParse(str, env) { + const result = (0, (_shellQuote || _load_shellQuote()).parse)(str, env); for (let i = 0; i < result.length; i++) { if (typeof result[i] !== 'string') { if (result[i].op != null) { - throw new Error( - `Unexpected operator "${result[i].op}" provided to shellParse`, - ); + throw new Error(`Unexpected operator "${result[i].op}" provided to shellParse`); } else { - throw new Error( - `Unexpected comment "${result[i].comment}" provided to shellParse`, - ); + throw new Error(`Unexpected comment "${result[i].comment}" provided to shellParse`); } } } @@ -150,11 +135,11 @@ export function shellParse(str: string, env?: Object): Array { * Technically you can pass in { operator: string } here, * but we don't use that in most APIs. */ -export function shellQuote(args: Array): string { - return quote(args); +function shellQuote(args) { + return (0, (_shellQuote || _load_shellQuote()).quote)(args); } -export function removeCommonPrefix(a: string, b: string): [string, string] { +function removeCommonPrefix(a, b) { let i = 0; while (a[i] === b[i] && i < a.length && i < b.length) { i++; @@ -162,57 +147,39 @@ export function removeCommonPrefix(a: string, b: string): [string, string] { return [a.substring(i), b.substring(i)]; } -export function removeCommonSuffix(a: string, b: string): [string, string] { +function removeCommonSuffix(a, b) { let i = 0; - while ( - a[a.length - 1 - i] === b[b.length - 1 - i] && - i < a.length && - i < b.length - ) { + while (a[a.length - 1 - i] === b[b.length - 1 - i] && i < a.length && i < b.length) { i++; } return [a.substring(0, a.length - i), b.substring(0, b.length - i)]; } -export function shorten( - str: string, - maxLength: number, - suffix?: string, -): string { - return str.length < maxLength - ? str - : str.slice(0, maxLength) + (suffix || ''); +function shorten(str, maxLength, suffix) { + return str.length < maxLength ? str : str.slice(0, maxLength) + (suffix || ''); } /** * Like String.split, but only splits once. */ -export function splitOnce(str: string, separator: string): [string, ?string] { +function splitOnce(str, separator) { const index = str.indexOf(separator); - return index === -1 - ? [str, null] - : [str.slice(0, index), str.slice(index + separator.length)]; + return index === -1 ? [str, null] : [str.slice(0, index), str.slice(index + separator.length)]; } /** * Indents each line by the specified number of characters. */ -export function indent( - str: string, - level: number = 2, - char: string = ' ', -): string { +function indent(str, level = 2, char = ' ') { return str.replace(/^([^\n])/gm, char.repeat(level) + '$1'); } -export function pluralize(noun: string, count: number) { +function pluralize(noun, count) { return count === 1 ? noun : noun + 's'; } -export function capitalize(str: string): string { - return str.length === 0 - ? str - : str.charAt(0).toUpperCase().concat(str.slice(1)); +function capitalize(str) { + return str.length === 0 ? str : str.charAt(0).toUpperCase().concat(str.slice(1)); } // Originally copied from: @@ -222,4 +189,4 @@ export function capitalize(str: string): string { // Then optimized with https://www.npmjs.com/package/regexp-tree. // Added a single matching group for use with String.split. // eslint-disable-next-line max-len -export const URL_REGEX = /(https?:\/\/(?:www\.)?[-\w@:%.+~#=]{2,256}\.[a-z]{2,6}\b[-\w@:%+.~#?&/=!]*|www\.[-\w@:%.+~#=]{2,256}\.[a-z]{2,6}\b[-\w@:%+.~#?&/=!]*)/; +const URL_REGEX = exports.URL_REGEX = /(https?:\/\/(?:www\.)?[-\w@:%.+~#=]{2,256}\.[a-z]{2,6}\b[-\w@:%+.~#?&/=!]*|www\.[-\w@:%.+~#=]{2,256}\.[a-z]{2,6}\b[-\w@:%+.~#?&/=!]*)/; \ No newline at end of file diff --git a/modules/nuclide-commons/symbol-definition-preview.js b/modules/nuclide-commons/symbol-definition-preview.js index 9371c3cf..3560a059 100644 --- a/modules/nuclide-commons/symbol-definition-preview.js +++ b/modules/nuclide-commons/symbol-definition-preview.js @@ -1,101 +1,114 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import type {NuclideUri} from './nuclideUri'; -import mimeTypes from 'mime-types'; -import fsPromise from './fsPromise'; -import {countOccurrences} from './string'; -import nuclideUri from './nuclideUri'; - -type Definition = { - path: NuclideUri, - position: atom$Point, -}; - -const MAX_PREVIEW_LINES = 10; -const MAX_FILESIZE = 100000; -const WHITESPACE_REGEX = /^\s*/; -function getIndentLevel(line: string) { - return WHITESPACE_REGEX.exec(line)[0].length; -} +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getDefinitionPreview = undefined; + +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + +let getDefinitionPreview = exports.getDefinitionPreview = (() => { + var _ref = (0, _asyncToGenerator.default)(function* (definition) { + // ensure filesize not too big before reading in whole file + const stats = yield (_fsPromise || _load_fsPromise()).default.stat(definition.path); + if (stats.size > MAX_FILESIZE) { + return null; + } + + // if file is image, return base-64 encoded contents + const fileBuffer = yield (_fsPromise || _load_fsPromise()).default.readFile(definition.path); -export async function getDefinitionPreview( - definition: Definition, -): Promise { - // ensure filesize not too big before reading in whole file - const stats = await fsPromise.stat(definition.path); - if (stats.size > MAX_FILESIZE) { - return null; - } - - // if file is image, return base-64 encoded contents - const fileBuffer = await fsPromise.readFile(definition.path); - - const mime = - mimeTypes.contentType(nuclideUri.extname(definition.path)) || 'text/plain'; - if (mime.startsWith('image/')) { - return {mime, contents: fileBuffer.toString('base64'), encoding: 'base64'}; - } - - const contents = fileBuffer.toString('utf8'); - const lines = contents.split('\n'); - - const start = definition.position.row; - const initialIndentLevel = getIndentLevel(lines[start]); - - const buffer = []; - for ( - let i = start, - openParenCount = 0, - closedParenCount = 0, - openCurlyCount = 0, - closedCurlyCount = 0; - i < start + MAX_PREVIEW_LINES && i < lines.length; - i++ - ) { - const line = lines[i]; - const indentLevel = getIndentLevel(line); - openParenCount += countOccurrences(line, '('); - closedParenCount += countOccurrences(line, ')'); - openCurlyCount += countOccurrences(line, '{'); - closedCurlyCount += countOccurrences(line, '}'); - - buffer.push(line.substr(Math.min(indentLevel, initialIndentLevel))); // dedent - - // heuristic for the end of a function signature: - if (indentLevel <= initialIndentLevel) { - // we've returned back to the original indentation level - if (openParenCount > 0 && openParenCount === closedParenCount) { - // if we're in a fn definition, make sure we have balanced pairs of parens - break; - } else if (line.trim().endsWith(';')) { - // c-style statement ending - break; - } else if ( + const mime = (_mimeTypes || _load_mimeTypes()).default.contentType((_nuclideUri || _load_nuclideUri()).default.extname(definition.path)) || 'text/plain'; + if (mime.startsWith('image/')) { + return { mime, contents: fileBuffer.toString('base64'), encoding: 'base64' }; + } + + const contents = fileBuffer.toString('utf8'); + const lines = contents.split('\n'); + + const start = definition.position.row; + const initialIndentLevel = getIndentLevel(lines[start]); + + const buffer = []; + for (let i = start, openParenCount = 0, closedParenCount = 0, openCurlyCount = 0, closedCurlyCount = 0; i < start + MAX_PREVIEW_LINES && i < lines.length; i++) { + const line = lines[i]; + const indentLevel = getIndentLevel(line); + openParenCount += (0, (_string || _load_string()).countOccurrences)(line, '('); + closedParenCount += (0, (_string || _load_string()).countOccurrences)(line, ')'); + openCurlyCount += (0, (_string || _load_string()).countOccurrences)(line, '{'); + closedCurlyCount += (0, (_string || _load_string()).countOccurrences)(line, '}'); + + buffer.push(line.substr(Math.min(indentLevel, initialIndentLevel))); // dedent + + // heuristic for the end of a function signature: + if (indentLevel <= initialIndentLevel) { + // we've returned back to the original indentation level + if (openParenCount > 0 && openParenCount === closedParenCount) { + // if we're in a fn definition, make sure we have balanced pairs of parens + break; + } else if (line.trim().endsWith(';')) { + // c-style statement ending + break; + } else if ( // end of a property definition line.trim().endsWith(',') && // including complex types as values openCurlyCount === closedCurlyCount && // but still not before function signatures are closed - openParenCount === closedParenCount - ) { - break; + openParenCount === closedParenCount) { + break; + } } } - } - return {mime, contents: buffer.join('\n'), encoding: 'utf8'}; + return { mime, contents: buffer.join('\n'), encoding: 'utf8' }; + }); + + return function getDefinitionPreview(_x) { + return _ref.apply(this, arguments); + }; +})(); + +var _mimeTypes; + +function _load_mimeTypes() { + return _mimeTypes = _interopRequireDefault(require('mime-types')); +} + +var _fsPromise; + +function _load_fsPromise() { + return _fsPromise = _interopRequireDefault(require('./fsPromise')); +} + +var _string; + +function _load_string() { + return _string = require('./string'); +} + +var _nuclideUri; + +function _load_nuclideUri() { + return _nuclideUri = _interopRequireDefault(require('./nuclideUri')); } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const MAX_PREVIEW_LINES = 10; /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +const MAX_FILESIZE = 100000; +const WHITESPACE_REGEX = /^\s*/; +function getIndentLevel(line) { + return WHITESPACE_REGEX.exec(line)[0].length; +} \ No newline at end of file diff --git a/modules/nuclide-commons/test-helpers.js b/modules/nuclide-commons/test-helpers.js index f9f02f7f..3a82a3ac 100644 --- a/modules/nuclide-commons/test-helpers.js +++ b/modules/nuclide-commons/test-helpers.js @@ -1,29 +1,11 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import type {Observable} from 'rxjs'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.generateFixture = exports.expectObservableToStartWith = exports.expectAsyncFailure = undefined; -import invariant from 'assert'; -import fs from 'fs'; -import temp from 'temp'; -import fsPromise from './fsPromise'; -import nuclideUri from './nuclideUri'; -import {asyncLimit} from './promise'; - -invariant( - (typeof atom !== 'undefined' && atom.inSpecMode()) || - process.env.NODE_ENV === 'test', - 'Test helpers should only be used in spec mode', -); +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); /** * Verifies that a Promise fails with an Error with specific expectations. When @@ -38,19 +20,20 @@ invariant( * rejection of `promise`. If these expectations are not met, then * `verify()` must throw an exception. */ -export async function expectAsyncFailure( - promise: Promise, - verify: (error: Error) => void, -): Promise { - try { - await promise; - return Promise.reject( - new Error('Promise should have failed, but did not.'), - ); - } catch (e) { - verify(e); - } -} +let expectAsyncFailure = exports.expectAsyncFailure = (() => { + var _ref = (0, _asyncToGenerator.default)(function* (promise, verify) { + try { + yield promise; + return Promise.reject(new Error('Promise should have failed, but did not.')); + } catch (e) { + verify(e); + } + }); + + return function expectAsyncFailure(_x, _x2) { + return _ref.apply(this, arguments); + }; +})(); /** * This is useful for mocking a module that the module under test requires. @@ -61,11 +44,144 @@ export async function expectAsyncFailure( * The require parameter is needed because require is bound differently in each * file, and we need to execute this in the caller's context. */ -export function clearRequireCache(require: Object, module: string): void { + + +/** + * Warning: Callsites *must* await the resulting promise, or test failures may go unreported or + * misattributed. + */ +let expectObservableToStartWith = exports.expectObservableToStartWith = (() => { + var _ref2 = (0, _asyncToGenerator.default)(function* (source, expected) { + const actual = yield source.take(expected.length).toArray().toPromise(); + expect(actual).toEqual(expected); + }); + + return function expectObservableToStartWith(_x3, _x4) { + return _ref2.apply(this, arguments); + }; +})(); + +/** + * Takes of Map of file/file-content pairs, and creates a temp dir that matches + * the file structure of the Map. Example: + * + * generateFixture('myfixture', new Map([ + * ['foo.js'], + * ['bar/baz.txt', 'some text'], + * ])); + * + * Creates: + * + * /tmp/myfixture_1/foo.js (empty file) + * /tmp/myfixture_1/bar/baz.txt (with 'some text') + */ + + +let generateFixture = exports.generateFixture = (() => { + var _ref3 = (0, _asyncToGenerator.default)(function* (fixtureName, files) { + (_temp || _load_temp()).default.track(); + + const MAX_CONCURRENT_FILE_OPS = 100; + const tempDir = yield (_fsPromise || _load_fsPromise()).default.tempdir(fixtureName); + + if (files == null) { + return tempDir; + } + + // Map -> Array with full paths + const fileTuples = Array.from(files, function (tuple) { + // It's our own array - it's ok to mutate it + tuple[0] = (_nuclideUri || _load_nuclideUri()).default.join(tempDir, tuple[0]); + return tuple; + }); + + // Dedupe the dirs that we have to make. + const dirsToMake = fileTuples.map(function ([filename]) { + return (_nuclideUri || _load_nuclideUri()).default.dirname(filename); + }).filter(function (dirname, i, arr) { + return arr.indexOf(dirname) === i; + }); + + yield (0, (_promise || _load_promise()).asyncLimit)(dirsToMake, MAX_CONCURRENT_FILE_OPS, function (dirname) { + return (_fsPromise || _load_fsPromise()).default.mkdirp(dirname); + }); + + yield (0, (_promise || _load_promise()).asyncLimit)(fileTuples, MAX_CONCURRENT_FILE_OPS, function ([filename, contents]) { + // We can't use fsPromise/fs-plus because it does too much extra work. + // They call `mkdirp` before `writeFile`. We know that the target dir + // exists, so we can optimize by going straight to `fs`. When you're + // making 10k files, this adds ~500ms. + return new Promise(function (resolve, reject) { + _fs.default.writeFile(filename, contents || '', function (err) { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + }); + + return tempDir; + }); + + return function generateFixture(_x5, _x6) { + return _ref3.apply(this, arguments); + }; +})(); + +exports.clearRequireCache = clearRequireCache; +exports.uncachedRequire = uncachedRequire; +exports.spyOnGetterValue = spyOnGetterValue; +exports.arePropertiesEqual = arePropertiesEqual; + +var _fs = _interopRequireDefault(require('fs')); + +var _temp; + +function _load_temp() { + return _temp = _interopRequireDefault(require('temp')); +} + +var _fsPromise; + +function _load_fsPromise() { + return _fsPromise = _interopRequireDefault(require('./fsPromise')); +} + +var _nuclideUri; + +function _load_nuclideUri() { + return _nuclideUri = _interopRequireDefault(require('./nuclideUri')); +} + +var _promise; + +function _load_promise() { + return _promise = require('./promise'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +if (!(typeof atom !== 'undefined' && atom.inSpecMode() || process.env.NODE_ENV === 'test')) { + throw new Error('Test helpers should only be used in spec mode'); +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +function clearRequireCache(require, module) { delete require.cache[require.resolve(module)]; } -export function uncachedRequire(require: Object, module: string): mixed { +function uncachedRequire(require, module) { clearRequireCache(require, module); // $FlowIgnore return require(module); @@ -82,7 +198,7 @@ export function uncachedRequire(require: Object, module: string): mixed { * - The getter returns a function (otherwise, it doesn't make sense to spy on * it) */ -export function spyOnGetterValue(object: Object, f: string): JasmineSpy { +function spyOnGetterValue(object, f) { const value = object[f]; delete object[f]; object[f] = value; @@ -93,7 +209,7 @@ export function spyOnGetterValue(object: Object, f: string): JasmineSpy { * Checks if the two objects have equal properties. This considers a property * set to undefined to be equivalent to a property that was not set at all. */ -export function arePropertiesEqual(obj1: Object, obj2: Object): boolean { +function arePropertiesEqual(obj1, obj2) { const allProps = new Set(); function addAllProps(obj) { for (const prop of Object.keys(obj)) { @@ -107,85 +223,4 @@ export function arePropertiesEqual(obj1: Object, obj2: Object): boolean { } } return true; -} - -/** - * Warning: Callsites *must* await the resulting promise, or test failures may go unreported or - * misattributed. - */ -export async function expectObservableToStartWith( - source: Observable, - expected: Array, -): Promise { - const actual: Array = await source - .take(expected.length) - .toArray() - .toPromise(); - expect(actual).toEqual(expected); -} - -/** - * Takes of Map of file/file-content pairs, and creates a temp dir that matches - * the file structure of the Map. Example: - * - * generateFixture('myfixture', new Map([ - * ['foo.js'], - * ['bar/baz.txt', 'some text'], - * ])); - * - * Creates: - * - * /tmp/myfixture_1/foo.js (empty file) - * /tmp/myfixture_1/bar/baz.txt (with 'some text') - */ -export async function generateFixture( - fixtureName: string, - files: ?Map, -): Promise { - temp.track(); - - const MAX_CONCURRENT_FILE_OPS = 100; - const tempDir = await fsPromise.tempdir(fixtureName); - - if (files == null) { - return tempDir; - } - - // Map -> Array with full paths - const fileTuples = Array.from(files, tuple => { - // It's our own array - it's ok to mutate it - tuple[0] = nuclideUri.join(tempDir, tuple[0]); - return tuple; - }); - - // Dedupe the dirs that we have to make. - const dirsToMake = fileTuples - .map(([filename]) => nuclideUri.dirname(filename)) - .filter((dirname, i, arr) => arr.indexOf(dirname) === i); - - await asyncLimit(dirsToMake, MAX_CONCURRENT_FILE_OPS, dirname => - fsPromise.mkdirp(dirname), - ); - - await asyncLimit( - fileTuples, - MAX_CONCURRENT_FILE_OPS, - ([filename, contents]) => { - // We can't use fsPromise/fs-plus because it does too much extra work. - // They call `mkdirp` before `writeFile`. We know that the target dir - // exists, so we can optimize by going straight to `fs`. When you're - // making 10k files, this adds ~500ms. - return new Promise((resolve, reject) => { - fs.writeFile(filename, contents || '', err => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); - }, - ); - - return tempDir; -} +} \ No newline at end of file diff --git a/modules/nuclide-commons/tokenized-text.js b/modules/nuclide-commons/tokenized-text.js index 41b8ced0..055d4ce7 100644 --- a/modules/nuclide-commons/tokenized-text.js +++ b/modules/nuclide-commons/tokenized-text.js @@ -1,69 +1,63 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -export type TokenKind = - | 'keyword' - | 'class-name' - | 'constructor' - | 'method' - | 'param' - | 'string' - | 'whitespace' - | 'plain' - | 'type'; - -export type TextToken = { - kind: TokenKind, - value: string, -}; - -export type TokenizedText = Array; - -export function keyword(value: string): TextToken { +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.keyword = keyword; +exports.className = className; +exports.constructor = constructor; +exports.method = method; +exports.param = param; +exports.string = string; +exports.whitespace = whitespace; +exports.plain = plain; +exports.type = type; +function keyword(value) { return _buildToken('keyword', value); -} - -export function className(value: string): TextToken { +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +function className(value) { return _buildToken('class-name', value); } -export function constructor(value: string): TextToken { +function constructor(value) { return _buildToken('constructor', value); } -export function method(value: string): TextToken { +function method(value) { return _buildToken('method', value); } -export function param(value: string): TextToken { +function param(value) { return _buildToken('param', value); } -export function string(value: string): TextToken { +function string(value) { return _buildToken('string', value); } -export function whitespace(value: string): TextToken { +function whitespace(value) { return _buildToken('whitespace', value); } -export function plain(value: string): TextToken { +function plain(value) { return _buildToken('plain', value); } -export function type(value: string): TextToken { +function type(value) { return _buildToken('type', value); } -function _buildToken(kind: TokenKind, value: string): TextToken { - return {kind, value}; -} +function _buildToken(kind, value) { + return { kind, value }; +} \ No newline at end of file diff --git a/modules/nuclide-commons/which.js b/modules/nuclide-commons/which.js index abd320e7..4ff4b39f 100644 --- a/modules/nuclide-commons/which.js +++ b/modules/nuclide-commons/which.js @@ -1,19 +1,26 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ +'use strict'; -import os from 'os'; -import nuclideUri from './nuclideUri'; +Object.defineProperty(exports, "__esModule", { + value: true +}); -import {runCommand} from './process'; +var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); + +var _os = _interopRequireDefault(require('os')); + +var _nuclideUri; + +function _load_nuclideUri() { + return _nuclideUri = _interopRequireDefault(require('./nuclideUri')); +} + +var _process; + +function _load_process() { + return _process = require('./process'); +} + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Provides a cross-platform way to check whether a binary is available. @@ -22,23 +29,41 @@ import {runCommand} from './process'; * remember) so we can use this for now. */ -function sanitizePathForWindows(path: string): string { - if (nuclideUri.basename(path) === path) { +function sanitizePathForWindows(path) { + if ((_nuclideUri || _load_nuclideUri()).default.basename(path) === path) { // simple binary in $PATH like `flow` return path; } else { - return `${nuclideUri.dirname(path)}:${nuclideUri.basename(path)}`; + return `${(_nuclideUri || _load_nuclideUri()).default.dirname(path)}:${(_nuclideUri || _load_nuclideUri()).default.basename(path)}`; } -} +} /** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + * @format + */ + +exports.default = (() => { + var _ref = (0, _asyncToGenerator.default)(function* (path) { + const isWindows = process.platform === 'win32'; + const whichCommand = isWindows ? 'where' : 'which'; + const searchPath = isWindows ? sanitizePathForWindows(path) : path; + try { + const result = yield (0, (_process || _load_process()).runCommand)(whichCommand, [searchPath]).toPromise(); + return result.split(_os.default.EOL)[0]; + } catch (e) { + return null; + } + }); -export default (async function which(path: string): Promise { - const isWindows = process.platform === 'win32'; - const whichCommand = isWindows ? 'where' : 'which'; - const searchPath = isWindows ? sanitizePathForWindows(path) : path; - try { - const result = await runCommand(whichCommand, [searchPath]).toPromise(); - return result.split(os.EOL)[0]; - } catch (e) { - return null; + function which(_x) { + return _ref.apply(this, arguments); } -}); + + return which; +})(); \ No newline at end of file diff --git a/modules/nuclide-jasmine/.eslintrc b/modules/nuclide-jasmine/.eslintrc deleted file mode 100644 index 29ad3c73..00000000 --- a/modules/nuclide-jasmine/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "rulesdir/modules-dependencies": [1, {"allowDevDependencies": true}] - } -} diff --git a/modules/nuclide-jasmine/LICENSE b/modules/nuclide-jasmine/LICENSE deleted file mode 100644 index 28731505..00000000 --- a/modules/nuclide-jasmine/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -BSD License - -For nuclide-jasmine software - -Copyright (c) 2017-present, Facebook, Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/modules/nuclide-jasmine/PATENTS b/modules/nuclide-jasmine/PATENTS deleted file mode 100644 index d6e41fc7..00000000 --- a/modules/nuclide-jasmine/PATENTS +++ /dev/null @@ -1,33 +0,0 @@ -Additional Grant of Patent Rights Version 2 - -"Software" means the nuclide-jasmine software contributed by Facebook, Inc. - -Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software -("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable -(subject to the termination provision below) license under any Necessary -Claims, to make, have made, use, sell, offer to sell, import, and otherwise -transfer the Software. For avoidance of doubt, no license is granted under -Facebook’s rights in any patent claims that are infringed by (i) modifications -to the Software made by you or any third party or (ii) the Software in -combination with any software or other technology. - -The license granted hereunder will terminate, automatically and without notice, -if you (or any of your subsidiaries, corporate affiliates or agents) initiate -directly or indirectly, or take a direct financial interest in, any Patent -Assertion: (i) against Facebook or any of its subsidiaries or corporate -affiliates, (ii) against any party if such Patent Assertion arises in whole or -in part from any software, technology, product or service of Facebook or any of -its subsidiaries or corporate affiliates, or (iii) against any party relating -to the Software. Notwithstanding the foregoing, if Facebook or any of its -subsidiaries or corporate affiliates files a lawsuit alleging patent -infringement against you in the first instance, and you respond by filing a -patent infringement counterclaim in that lawsuit against that party that is -unrelated to the Software, the license granted hereunder will not terminate -under section (i) of this paragraph due to such counterclaim. - -A "Necessary Claim" is a claim of a patent owned by Facebook that is -necessarily infringed by the Software standing alone. - -A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, -or contributory infringement or inducement to infringe any patent, including a -cross-claim or counterclaim. diff --git a/modules/nuclide-jasmine/bin/jasmine-node-transpiled.js b/modules/nuclide-jasmine/bin/jasmine-node-transpiled.js deleted file mode 100755 index 3230d27d..00000000 --- a/modules/nuclide-jasmine/bin/jasmine-node-transpiled.js +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env node -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ - -/* eslint-disable no-console */ - -// Forwards the arguments from this script to ./run-jasmine-tests and runs it -// under a timeout. This is used to help find tests that are not terminating -// on their own. - -const child_process = require('child_process'); - -const TIMEOUT_IN_MILLIS = 5 * 60 * 1000; - -const args = [ - require.resolve('./run-jasmine-tests'), - '--forceexit', - '--captureExceptions', -].concat( - process.argv.slice(2) -); - -const cmd = ['cd', process.cwd(), '&& node'].concat(args).join(' '); - -const timeoutId = setTimeout(() => { - console.error('TEST TIMED OUT when running: %s', cmd); - process.abort(); -}, TIMEOUT_IN_MILLIS); - -// Use "inherit" for "stdio" so jasmine-node inherits our TTY, and can properly -// determine whether to show colors or not. -child_process - .spawn('node', args, {stdio: 'inherit'}) - .on('close', code => { - clearTimeout(timeoutId); - if (code === 0) { - console.log('TEST PASSED when running: %s', cmd); - } else { - console.error('TEST FAILED (exit code: %s) when running: %s', code, cmd); - } - process.exit(code); - }) - .on('error', err => { - console.error('TEST FAILED when running: %s', cmd); - console.error(err.toString()); - process.exit(1); - }); diff --git a/modules/nuclide-jasmine/bin/run-jasmine-tests.js b/modules/nuclide-jasmine/bin/run-jasmine-tests.js deleted file mode 100755 index ce821b79..00000000 --- a/modules/nuclide-jasmine/bin/run-jasmine-tests.js +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env node -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ -/* eslint-disable no-console */ - -// jasmine-node test runner with Atom test globals and babel transpiling support. - -// TODO(#21523621): Use a regular require once Yarn workspaces are enforced -// eslint-disable-next-line rulesdir/modules-dependencies -require('../../nuclide-node-transpiler'); - -// Set this up before we call jasmine-node. jasmine-node does this same trick, -// but neglects to respect the exit code, so we beat it the to the punch. -process.once('exit', code => { - const temp = require('temp'); - if (code === 0) { - // jasmine-node is swallowing temp's exit handler, so force a cleanup. - try { - temp.cleanupSync(); - } catch (err) { - if (err && err.message !== 'not tracking') { - console.log(`temp.cleanup() failed. ${err}`); - } - } - } else { - // When the test fails, we keep the temp contents for debugging. - temp.track(false); - } - process.exit(code); -}); - -// Load waitsForPromise into global. -global.waitsForPromise = require('../lib/waitsForPromise').default; -global.window = global; - -require('../lib/focused'); -require('../lib/unspy'); -require('../lib/faketimer'); - -try { - // This loads the CLI for jasmine-node. - require('jasmine-node/bin/jasmine-node'); -} catch (e) { - // Note that the process.exit(1) works now because of the "exit" handler - // installed at the start of this script. - console.error(e.toString()); - console.error(e.stack); - - process.exit(1); -} diff --git a/modules/nuclide-jasmine/lib/faketimer.js b/modules/nuclide-jasmine/lib/faketimer.js deleted file mode 100644 index 0334965f..00000000 --- a/modules/nuclide-jasmine/lib/faketimer.js +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -/** - * Port of Atom's timer utils (https://fburl.com/104714454) which is useful for unittest. - * Use fakeSetTimeout, fakeClearTimeout, fakeSetInterval and fakeClearInterval to mock Node.js's - * Timer utils, and using advanceClock to advance the fake timer to trigger timed callback. - */ -require('jasmine-node'); // eslint-disable-line rulesdir/no-commonjs - -let now = 0; -let timeoutCount = 0; -let intervalCount = 0; -let timeouts = []; -let intervalTimeouts = {}; - -function resetTimeouts(): void { - now = 0; - timeoutCount = 0; - intervalCount = 0; - timeouts = []; - intervalTimeouts = {}; -} - -function fakeSetTimeout(callback: () => ?any, ms: number): number { - const id = ++timeoutCount; - timeouts.push([id, now + ms, callback]); - timeouts.sort( - ([, strikeTime0], [, strikeTime1]) => strikeTime0 - strikeTime1, - ); - return id; -} - -function fakeClearTimeout(idToClear: number): void { - timeouts = timeouts.filter(([id]) => id !== idToClear); -} - -function fakeSetInterval(callback: () => ?any, ms: number): number { - const id = ++intervalCount; - const action = () => { - callback(); - intervalTimeouts[id] = fakeSetTimeout(action, ms); - }; - intervalTimeouts[id] = fakeSetTimeout(action, ms); - return id; -} - -function fakeClearInterval(idToClear: number): void { - fakeClearTimeout(intervalTimeouts[idToClear]); -} - -function advanceClock(deltaMs: number): void { - const advanceTo = now + deltaMs; - - while (timeouts.length !== 0 && timeouts[0][1] <= advanceTo) { - const [, strikeTime, callback] = timeouts.shift(); - now = strikeTime; - callback(); - } - - now = advanceTo; -} - -/** - * Allows tests to use the non-fake setTimeout and clearTimeout functions. - */ -function useRealClock(): void { - jasmine.unspy(global, 'setTimeout'); - jasmine.unspy(global, 'clearTimeout'); - jasmine.unspy(Date, 'now'); -} - -/** - * Atom does this half-way mock. - * https://github.com/atom/atom/blob/v1.12.7/spec/spec-helper.coffee#L169-L174 - */ -function useMockClock(): void { - spyOn(global, 'setInterval').andCallFake(fakeSetInterval); - spyOn(global, 'clearInterval').andCallFake(fakeClearInterval); -} - -// Expose the fake timer utils to global to be used by npm spec tests. -global.resetTimeouts = resetTimeouts; -global.fakeSetTimeout = fakeSetTimeout; -global.fakeClearTimeout = fakeClearTimeout; -global.fakeSetInterval = fakeSetInterval; -global.fakeClearInterval = fakeClearInterval; -global.advanceClock = advanceClock; -jasmine.useRealClock = useRealClock; -jasmine.useMockClock = useMockClock; -// $FlowIssue: https://github.com/facebook/flow/issues/285 -Object.defineProperty(global, 'now', {get: () => now}); - -/** - * This hook is a the first initialization code that happens before any jasmine test case is - * executed. This allows to use the fake timing by default and is a direct port from Atom's - * `spec-helper.coffee` - */ -beforeEach(() => { - resetTimeouts(); - spyOn(Date, 'now').andCallFake(() => now); - spyOn(global, 'setTimeout').andCallFake(fakeSetTimeout); - spyOn(global, 'clearTimeout').andCallFake(fakeClearTimeout); -}); diff --git a/modules/nuclide-jasmine/lib/focused.js b/modules/nuclide-jasmine/lib/focused.js deleted file mode 100644 index 66fd4ce5..00000000 --- a/modules/nuclide-jasmine/lib/focused.js +++ /dev/null @@ -1,114 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -/** - * A port of Atom's focused specs. - * https://github.com/atom/jasmine-focused/blob/c922330/src/jasmine-focused.coffee - */ - -import invariant from 'assert'; - -// eslint-disable-next-line rulesdir/no-commonjs -require('jasmine-node'); - -// These are undocumented APIs. The type of jasmine is redefined here, so that -// we don't pollute the real lib def with this nonsense. -const jasmine: { - getEnv(): { - focusPriority?: number, - specFilter?: (spec: any) => boolean, - }, - Env: { - prototype: { - ddescribe?: () => void, - iit?: () => void, - }, - }, -} = - global.jasmine; - -function setGlobalFocusPriority(priority) { - const env = jasmine.getEnv(); - // flowlint-next-line sketchy-null-number:off - if (!env.focusPriority) { - env.focusPriority = 1; - } - if (priority > env.focusPriority) { - env.focusPriority = priority; - } -} - -function fdescribe(description, specDefinitions, priority_) { - const priority = priority_ != null ? priority_ : 1; - setGlobalFocusPriority(priority); - const suite = describe(description, specDefinitions); - invariant(suite != null); - suite.focusPriority = priority; - return suite; -} -global.fdescribe = fdescribe; - -function ffdescribe(description, specDefinitions) { - return fdescribe(description, specDefinitions, 2); -} -global.ffdescribe = ffdescribe; - -function fffdescribe(description, specDefinitions) { - return fdescribe(description, specDefinitions, 3); -} -global.fffdescribe = fffdescribe; - -function fit(description, definition, priority_) { - const priority = priority_ != null ? priority_ : 1; - setGlobalFocusPriority(priority); - const spec = it(description, definition); - invariant(spec != null); - spec.focusPriority = priority; - return spec; -} -global.fit = fit; - -function ffit(description, specDefinitions) { - return fit(description, specDefinitions, 2); -} -global.ffit = ffit; - -function fffit(description, specDefinitions) { - return fit(description, specDefinitions, 3); -} -global.fffit = fffit; - -jasmine.getEnv().specFilter = function(spec) { - const env = jasmine.getEnv(); - const globalFocusPriority = env.focusPriority; - const parent = spec.parentSuite != null ? spec.parentSuite : spec.suite; - // flowlint-next-line sketchy-null-number:off - if (!globalFocusPriority) { - return true; - } else if (spec.focusPriority >= globalFocusPriority) { - return true; - } else if (!parent) { - return false; - } else { - invariant(typeof env.specFilter === 'function'); - return env.specFilter(parent); - } -}; - -// jasmine-node has ddescribe and iit. Remove them in favor of focus. -if (typeof jasmine.Env.prototype.ddescribe === 'function') { - delete jasmine.Env.prototype.ddescribe; -} - -if (typeof jasmine.Env.prototype.iit === 'function') { - delete jasmine.Env.prototype.iit; -} diff --git a/modules/nuclide-jasmine/lib/unspy.js b/modules/nuclide-jasmine/lib/unspy.js deleted file mode 100644 index ea251801..00000000 --- a/modules/nuclide-jasmine/lib/unspy.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -// eslint-disable-next-line rulesdir/no-commonjs -require('jasmine-node'); - -/** - * unspy is a ported utility from Atom's `spec-helper.coffee` that restores the - * jasmine spied function on an object to its original value. - */ -jasmine.unspy = function unspy(object: Object, methodName: string) { - if (!object[methodName].hasOwnProperty('originalValue')) { - throw new Error('Not a spy ' + methodName); - } - object[methodName] = object[methodName].originalValue; -}; diff --git a/modules/nuclide-jasmine/lib/waitsForPromise.js b/modules/nuclide-jasmine/lib/waitsForPromise.js deleted file mode 100644 index c6dd0b7d..00000000 --- a/modules/nuclide-jasmine/lib/waitsForPromise.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import invariant from 'assert'; - -type WaitsForPromiseOptions = { - shouldReject?: boolean, - timeout?: number, -}; - -export default function waitsForPromise( - ...args: Array Promise)> -): void { - let shouldReject; - let timeout; - if (args.length > 1) { - shouldReject = args[0].shouldReject; - timeout = args[0].timeout; - } else { - shouldReject = false; - timeout = 0; - } - - let finished = false; - - runs(() => { - const fn = args[args.length - 1]; - invariant(typeof fn === 'function'); - const promise = fn(); - if (shouldReject) { - promise - .then( - () => { - jasmine - .getEnv() - .currentSpec.fail( - 'Expected promise to be rejected, but it was resolved', - ); - }, - () => { - // Do nothing, it's expected. - }, - ) - .then(() => { - finished = true; - }); - } else { - promise - .then( - () => { - // Do nothing, it's expected. - }, - error => { - const text = error ? error.stack || error.toString() : 'undefined'; - jasmine - .getEnv() - .currentSpec.fail( - `Expected promise to be resolved, but it was rejected with ${text}`, - ); - }, - ) - .then(() => { - finished = true; - }); - } - }); - - waitsFor(timeout, () => finished); -} diff --git a/modules/nuclide-jasmine/package.json b/modules/nuclide-jasmine/package.json deleted file mode 100644 index 5275bf61..00000000 --- a/modules/nuclide-jasmine/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "nuclide-jasmine", - "version": "0.2.0", - "description": "Atom-compatible Jasmine runner that runs outside of Atom", - "license": "BSD-3-Clause", - "homepage": "https://nuclide.io/", - "repository": "https://github.com/facebook/nuclide/tree/master/modules/nuclide-jasmine", - "scripts": { - "test": "node bin/jasmine-node-transpiled spec" - }, - "dependencies": { - "nuclide-node-transpiler": "0.2.0", - "temp": "0.8.3" - }, - "devDependencies": { - "async-to-generator": "1.1.0", - "jasmine-node": "1.14.5" - }, - "private": true -} diff --git a/modules/nuclide-jasmine/spec/faketimer-spec.js b/modules/nuclide-jasmine/spec/faketimer-spec.js deleted file mode 100644 index 71ba2923..00000000 --- a/modules/nuclide-jasmine/spec/faketimer-spec.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -describe('Fake timer test suite', () => { - it('test setTimeout and clearTimeout', () => { - let firstExecuted = false; - - setTimeout(() => { - firstExecuted = true; - }, 10); - - advanceClock(9); - - expect(firstExecuted).toBe(false); - advanceClock(1); - expect(firstExecuted).toBe(true); - - let secondExecuted = false; - let thirdExecuted = false; - - const secondId = setTimeout(() => { - secondExecuted = true; - }, 20); - setTimeout(() => { - thirdExecuted = true; - }, 30); - - advanceClock(19); - clearTimeout(secondId); - - expect(secondExecuted).toBe(false); - expect(thirdExecuted).toBe(false); - - advanceClock(20); - - expect(secondExecuted).toBe(false); - expect(thirdExecuted).toBe(true); - }); - - it('test setInterval and clearInterval', () => { - jasmine.useMockClock(); - - let firstExecuted = false; - - setInterval(() => { - firstExecuted = true; - }, 10); - - advanceClock(9); - - expect(firstExecuted).toBe(false); - advanceClock(1); - expect(firstExecuted).toBe(true); - - let secondExecuted = false; - let thirdExecuted = false; - - const secondId = setInterval(() => { - secondExecuted = true; - }, 20); - setInterval(() => { - thirdExecuted = true; - }, 30); - - advanceClock(19); - clearInterval(secondId); - - expect(secondExecuted).toBe(false); - expect(thirdExecuted).toBe(false); - - advanceClock(20); - - expect(secondExecuted).toBe(false); - expect(thirdExecuted).toBe(true); - }); - - it('test fakeSetTimeout triggered in expected order', () => { - let firstExecuted = false; - let secondExecuted = false; - - setTimeout(() => { - firstExecuted = true; - expect(secondExecuted).toBe(false); - }, 10); - - setTimeout(() => { - secondExecuted = true; - expect(firstExecuted).toBe(true); - }, 20); - - advanceClock(20); - - expect(firstExecuted).toBe(true); - expect(secondExecuted).toBe(true); - }); - - it('test fakeSetInterval and fakeClearInterval', () => { - let firstExecutedCount = 0; - let secondExecutedCount = 0; - - global.fakeSetInterval(() => firstExecutedCount++, 10); - advanceClock(5); - const secondId = global.fakeSetInterval(() => secondExecutedCount++, 10); - - advanceClock(15); - - expect(firstExecutedCount).toBe(2); - expect(secondExecutedCount).toBe(1); - - global.fakeClearInterval(secondId); - - advanceClock(20); - - expect(firstExecutedCount).toBe(4); - expect(secondExecutedCount).toBe(1); - }); - - // Atom's implementation will fail at this test case. (https://github.com/atom/atom/issues/6627) - it('test fakeSetInterval triggered in expected order', () => { - let firstExecutedCount = 0; - let secondExecutedCount = 0; - - global.fakeSetInterval(() => { - firstExecutedCount++; - expect(secondExecutedCount < firstExecutedCount).toBe(true); - }, 10); - - advanceClock(5); - - global.fakeSetInterval(() => secondExecutedCount++, 10); - - advanceClock(40); - - expect(firstExecutedCount).toBe(4); - expect(secondExecutedCount).toBe(4); - }); - - it('test Date.now and global.now', () => { - const now1 = Date.now(); - expect(now1).toEqual(global.now); - advanceClock(100); - const now2 = Date.now(); - expect(now2 - now1).toEqual(100); - expect(now2).toEqual(global.now); - }); -}); diff --git a/modules/nuclide-jasmine/spec/run-jasmine-tests-spec.js b/modules/nuclide-jasmine/spec/run-jasmine-tests-spec.js deleted file mode 100644 index 0a783d36..00000000 --- a/modules/nuclide-jasmine/spec/run-jasmine-tests-spec.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -import waitsForPromise from '../lib/waitsForPromise'; - -function testFlowtypedFunction(arg: number): number { - return arg; -} - -describe('Jasmine transpile test suite', () => { - it('test transpiler worked as exepcted', () => { - const promise = Promise.resolve('test'); - expect(typeof promise).toEqual('object'); - expect(testFlowtypedFunction(1)).toEqual(1); - }); -}); - -describe('Jasmine environment', () => { - it('sets the correct NODE_ENV', () => { - expect(process.env.NODE_ENV).toEqual('test'); - }); -}); - -describe('Jasmine waitsForPromise test suite', () => { - beforeEach(() => jasmine.useRealClock()); - - it('test waitsForPromise worked as expected on a resolved promise', () => { - waitsForPromise(async () => { - const promise = Promise.resolve('test'); - const result = await promise; - expect(result).toEqual('test'); - }); - }); - - it('test waitsForPromise worked as expected on a rejected promise', () => { - waitsForPromise({shouldReject: true}, () => - Promise.reject(new Error('test')), - ); - }); - - it('test waitsForPromise worked as expected on a customized timeout', () => { - // This is more than default timeout of 5 seconds. - waitsForPromise({shouldReject: false, timeout: 7 * 1000}, () => { - return new Promise((resolve, reject) => { - setTimeout(resolve, 6 * 1000); - }); - }); - }); -}); diff --git a/modules/nuclide-node-transpiler/.eslintrc b/modules/nuclide-node-transpiler/.eslintrc deleted file mode 100644 index 29ad3c73..00000000 --- a/modules/nuclide-node-transpiler/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "rulesdir/modules-dependencies": [1, {"allowDevDependencies": true}] - } -} diff --git a/modules/nuclide-node-transpiler/spec/NodeTranspiler-spec.js b/modules/nuclide-node-transpiler/spec/NodeTranspiler-spec.js deleted file mode 100644 index 6e1da5a8..00000000 --- a/modules/nuclide-node-transpiler/spec/NodeTranspiler-spec.js +++ /dev/null @@ -1,160 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ - -const fs = require('fs'); -const vm = require('vm'); -const dedent = require('dedent'); - -const NodeTranspiler = require('../lib/NodeTranspiler'); - -describe('NodeTranspiler', () => { - describe('NodeTranspiler.shouldCompile', () => { - it('matches @flow', () => { - [ - '/** @flow */\n', - dedent` - /** - * @flow - */ - `, - dedent` - /** - * @foo - * @flow - */ - `, - ].forEach(src => { - expect(NodeTranspiler.shouldCompile(src)).toBe(true); - expect(NodeTranspiler.shouldCompile(new Buffer(src))).toBe(true); - }); - }); - - it('ignores everything else', () => { - [ - "'use strict';\n", - '/** @fflow */\n', - '/** flow */\n', - dedent` - 'use strict'; - /** - * @flow - */ - `, - dedent` - 'use strict'; - /** - * @flow - */ - `, - // You have to strip your own shebang before the docblock is parsed! - dedent` - #!/usr/bin/env node - /** - * @flow - */ - `, - ].forEach(src => { - expect(NodeTranspiler.shouldCompile(src)).toBe(false); - expect(NodeTranspiler.shouldCompile(new Buffer(src))).toBe(false); - }); - }); - }); - - describe('NodeTranspiler#getConfigDigest', () => { - it('works with real babel', () => { - const realBabel = require('babel-core'); - const nodeTranspilerReal = new NodeTranspiler(); - - const fakeBabel = { - version: realBabel.version, - transform() { throw new Error('This should not have been called.'); }, - }; - const nodeTranspilerFake = - new NodeTranspiler(fakeBabel.version, () => fakeBabel); - - expect(nodeTranspilerReal.getConfigDigest()) - .toBe(nodeTranspilerFake.getConfigDigest()); - }); - }); - - describe('NodeTranspiler#transform', () => { - it('works on buffers', () => { - const filename = require.resolve('./fixtures/modern-syntax'); - const nodeTranspiler = new NodeTranspiler(); - - const bufferSrc = fs.readFileSync(filename); - expect(Buffer.isBuffer(bufferSrc)).toBe(true); - - const out1 = nodeTranspiler.transform(bufferSrc, filename); - expect(typeof out1).toBe('string'); - - const c1 = {exports: {}}; - vm.runInNewContext(out1, c1); - expect(c1.exports.Foo.bar).toBe('qux'); - }); - - it('works on strings', () => { - const filename = require.resolve('./fixtures/modern-syntax'); - const nodeTranspiler = new NodeTranspiler(); - - const stringSrc = fs.readFileSync(filename, 'utf8'); - expect(typeof stringSrc).toBe('string'); - - const out2 = nodeTranspiler.transform(stringSrc, filename); - expect(typeof out2).toBe('string'); - - const c2 = {exports: {}}; - vm.runInNewContext(out2, c2); - expect(c2.exports.Foo.bar).toBe('qux'); - }); - }); - - describe('NodeTranspiler#_getCacheFilename', () => { - it('works', () => { - const filename = require.resolve('./fixtures/modern-syntax'); - const nodeTranspiler = new NodeTranspiler(); - - const bufferSrc = fs.readFileSync(filename); - expect(Buffer.isBuffer(bufferSrc)).toBe(true); - - const cacheFilename1 = - nodeTranspiler._getCacheFilename(bufferSrc, filename); - const cacheFilename2 = - nodeTranspiler._getCacheFilename(bufferSrc.toString(), filename); - - expect(cacheFilename1).toEqual(cacheFilename2); - }); - }); - - describe('NodeTranspiler#transformWithCache', () => { - it('reads from the cache', () => { - const filename = require.resolve('./fixtures/modern-syntax'); - const nodeTranspiler = new NodeTranspiler(); - - nodeTranspiler._getCacheFilename = src => { - expect(src).toBe('abc'); - return filename; - }; - - const out = nodeTranspiler.transformWithCache('abc', filename); - const expected = fs.readFileSync(filename, 'utf8'); - - expect(out).toBe(expected); - }); - }); -}); diff --git a/modules/nuclide-node-transpiler/spec/README.md b/modules/nuclide-node-transpiler/spec/README.md deleted file mode 100644 index 601fdd79..00000000 --- a/modules/nuclide-node-transpiler/spec/README.md +++ /dev/null @@ -1,3 +0,0 @@ -`nuclide-node-transpiler` is a dependency of `nuclide-jasmine`, so it cannot use `nuclide-jasmine` as a test runner. - -Since some of the tests need a clean environment and some tests install the require hook, each test is run in a new node process. diff --git a/modules/nuclide-node-transpiler/spec/bin-transpile-spec.js b/modules/nuclide-node-transpiler/spec/bin-transpile-spec.js deleted file mode 100644 index e3c92896..00000000 --- a/modules/nuclide-node-transpiler/spec/bin-transpile-spec.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ - -const child_process = require('child_process'); -const vm = require('vm'); - -describe('bin-transpile', () => { - it('transpiles one file', () => { - const ps = child_process.spawn( - require.resolve('../bin/transpile.js'), - [require.resolve('./fixtures/modern-syntax')] - ); - - let out = ''; - let err = ''; - ps.stdout.on('data', buf => { out += buf; }); - ps.stderr.on('data', buf => { err += buf; }); - - let ran = false; - ps.on('close', () => { - expect(err).toBe(''); - - const c = {exports: {}}; - vm.runInNewContext(out, c); - expect(c.exports.Foo.bar).toBe('qux'); - - ran = true; - }); - - waitsFor(() => ran); - }); -}); diff --git a/modules/nuclide-node-transpiler/spec/env-spec.js b/modules/nuclide-node-transpiler/spec/env-spec.js deleted file mode 100644 index 07ffaec7..00000000 --- a/modules/nuclide-node-transpiler/spec/env-spec.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ - -const fs = require('fs'); -const path = require('path'); - -describe('env', () => { - it('has correct __DEV__', () => { - // This should exist if we're running a test. - expect(fs.existsSync(path.join(__dirname, '../../../DEVELOPMENT'))).toBe(true); - expect(require('../lib/env').__DEV__).toBe(true); - }); -}); diff --git a/modules/nuclide-node-transpiler/spec/fixtures/modern-syntax.js b/modules/nuclide-node-transpiler/spec/fixtures/modern-syntax.js deleted file mode 100644 index 6beddeb7..00000000 --- a/modules/nuclide-node-transpiler/spec/fixtures/modern-syntax.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -export class Foo { - static bar = 'qux'; -} diff --git a/modules/nuclide-node-transpiler/spec/fixtures/require-hook-test.js b/modules/nuclide-node-transpiler/spec/fixtures/require-hook-test.js deleted file mode 100644 index 8d492df6..00000000 --- a/modules/nuclide-node-transpiler/spec/fixtures/require-hook-test.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ -/* eslint-disable no-console */ - -require('../..'); - -const assert = require('assert'); - -assert.doesNotThrow(() => { - require('./modern-syntax'); -}); - -const ModernSyntax = require('./modern-syntax'); -assert.equal(typeof ModernSyntax.Foo, 'function'); -assert.equal(ModernSyntax.Foo.bar, 'qux'); - -const VanillaSyntax = require('./vanilla-syntax'); -assert.equal(typeof VanillaSyntax.Foo, 'function'); -assert.equal(typeof VanillaSyntax.Foo.bar, 'function'); -assert.equal(VanillaSyntax.Foo.bar(), 'qux'); - -// This may not always be true forever. If the v8 output changes, then remove -// this test. -assert.equal( - VanillaSyntax.Foo.toString(), - "class Foo {\n static bar() {\n return 'qux';\n }\n}" -); -// The transpiled version of "Foo" would've looked like this: -assert.notEqual( - VanillaSyntax.Foo.toString(), - 'function Foo() {\n _classCallCheck(this, Foo);\n }' -); - -console.log('OK'); diff --git a/modules/nuclide-node-transpiler/spec/fixtures/vanilla-syntax.js b/modules/nuclide-node-transpiler/spec/fixtures/vanilla-syntax.js deleted file mode 100644 index 652503ae..00000000 --- a/modules/nuclide-node-transpiler/spec/fixtures/vanilla-syntax.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ - -class Foo { - static bar() { - return 'qux'; - } -} - -module.exports.Foo = Foo; diff --git a/modules/nuclide-node-transpiler/spec/inline-invariant-spec.js b/modules/nuclide-node-transpiler/spec/inline-invariant-spec.js deleted file mode 100644 index 4dad94ea..00000000 --- a/modules/nuclide-node-transpiler/spec/inline-invariant-spec.js +++ /dev/null @@ -1,176 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ - -const babel = require('babel-core'); -const dedent = require('dedent'); - -function transform(source) { - return babel.transform(source, { - plugins: [ - require('babel-plugin-syntax-flow'), - require('../lib/inline-invariant-tr'), - ], - }).code; -} - -describe('inline-invariant transform', () => { - it('works 1', () => { - expect(transform(dedent` - import invariant from ''; - invariant(false); - `)).toEqual(dedent` - if (!false) { - throw new Error('Invariant violation: "false"'); - } - `); - }); - - it('works 2', () => { - expect(transform(dedent` - import invariant from ''; - invariant(false != true); - `)).toEqual(dedent` - if (!(false != true)) { - throw new Error('Invariant violation: "false != true"'); - } - `); - }); - - it('works 3', () => { - expect(transform(dedent` - import invariant from ''; - invariant(foo() ? !!bar : baz.qux()); - `)).toEqual(dedent` - if (!(foo() ? !!bar : baz.qux())) { - throw new Error('Invariant violation: "foo() ? !!bar : baz.qux()"'); - } - `); - }); - - it('works 4', () => { - expect(transform(dedent` - import invariant from ''; - invariant(true, 'it is true'); - `)).toEqual(dedent` - if (!true) { - throw new Error('it is true'); - } - `); - }); - - it('works 5', () => { - expect(transform(dedent` - import {invariant} from ''; - invariant(true, 'it is true'); - `)).toEqual(dedent` - if (!true) { - throw new Error('it is true'); - } - `); - }); - - it('works 6', () => { - expect(transform(dedent` - import invariant from ''; - invariant(true, 'it is true'); - invariant.ok(); - `)).toEqual(dedent` - import invariant from ''; - - if (!true) { - throw new Error('it is true'); - } - - invariant.ok(); - `); - }); - - it('works 7', () => { - expect(transform(dedent` - export { invariant } from '' - `)).toEqual(dedent` - export { invariant } from ''; - `); - }); - - it('works 8', () => { - expect(transform(dedent` - import {default as invariant} from '' - invariant(true); - `)).toEqual(dedent` - if (!true) { - throw new Error('Invariant violation: "true"'); - } - `); - }); - - it('works 9', () => { - expect(transform(dedent` - invariant; - `)).toEqual(dedent` - invariant; - `); - }); - - it('works 10', () => { - expect(transform(dedent` - var invariant = require('invariant'); - `)).toEqual(dedent` - var invariant = require('invariant'); - `); - }); - - it('works 11', () => { - expect(transform(dedent` - var invariant = require('invariant'); - invariant(true); - `)).toEqual(dedent` - var invariant = require('invariant'); - invariant(true); - `); - }); - - it('works 12', () => { - expect(transform(dedent` - import invariant from 'invariant'; - foo; - `)).toEqual('\nfoo;'); - }); - - it('works 13', () => { - expect(() => { - transform(dedent` - import invariant from 'invariant'; - if (invariant(true)) {} - `); - }).toThrow( - new SyntaxError('unknown: `invariant()` must be used as an expression statement.') - ); - }); - - it('works 14', () => { - expect(() => { - transform(dedent` - import invariant from 'invariant'; - invariant(); - `); - }).toThrow( - new SyntaxError('unknown: `invariant()` must at least one argument.') - ); - }); -}); diff --git a/modules/nuclide-node-transpiler/spec/main-spec.js b/modules/nuclide-node-transpiler/spec/main-spec.js deleted file mode 100644 index 450d5a07..00000000 --- a/modules/nuclide-node-transpiler/spec/main-spec.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ - -const child_process = require('child_process'); - -describe('require-hook', () => { - it('works', () => { - // This test runs in a new process because it monkey-patches `require` and - // we don't want to pollute the test environment. - const ret = child_process.spawnSync(process.execPath, [ - require.resolve('./fixtures/require-hook-test'), - ]); - expect(ret.status).toBe(0); - expect(String(ret.stdout).trim()).toBe('OK'); - expect(String(ret.stderr).trim()).toBe(''); - }); -}); diff --git a/modules/nuclide-node-transpiler/spec/path-rules-spec.js b/modules/nuclide-node-transpiler/spec/path-rules-spec.js deleted file mode 100644 index 50cb1524..00000000 --- a/modules/nuclide-node-transpiler/spec/path-rules-spec.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ - -const path = require('path'); -const glob = require('glob'); - -const pathRules = require('../lib/path-rules'); - -describe('path-rules', () => { - describe('pathRules.getIncludedFiles', () => { - it('works', () => { - const includedFiles = pathRules.getIncludedFiles(); - - expect(includedFiles.includes(__filename)).toBe(true); - - const pathToNodeModulesFile = require.resolve('babel-core'); - expect(!includedFiles.includes(pathToNodeModulesFile)).toBe(true); - }); - }); - - describe('pathRules.isIncluded', () => { - it('matches what getIncludedFiles finds', () => { - const expectedFiles = pathRules.getIncludedFiles().sort(); - const allFiles = glob.sync(path.join(__dirname, '../../../**/*.js')).sort(); - - expect(expectedFiles).not.toEqual(allFiles); - - for (let i = allFiles.length - 1; i >= 0; i--) { - if (!pathRules.isIncluded(allFiles[i])) { - allFiles.splice(i, 1); - } - } - - expect(expectedFiles).toEqual(allFiles); - }); - }); -}); diff --git a/modules/nuclide-node-transpiler/spec/use-minified-libs-spec.js b/modules/nuclide-node-transpiler/spec/use-minified-libs-spec.js deleted file mode 100644 index cf7bfaa6..00000000 --- a/modules/nuclide-node-transpiler/spec/use-minified-libs-spec.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ -/* eslint-disable max-len */ - -const babel = require('babel-core'); -const dedent = require('dedent'); - -function transform(source, extraPlugins) { - return babel.transform(source, { - plugins: (extraPlugins || []).concat([ - require('babel-plugin-syntax-flow'), - require('../lib/use-minified-libs-tr'), - ]), - }).code; -} - -describe('use-minified-libs transform', () => { - it('export-all-minified', () => { - expect(transform(dedent` - export * from 'rxjs'; - `)).toEqual(dedent` - export * from 'rxjs/bundles/Rx.min.js'; - `); - }); - - it('export-named-minified', () => { - expect(transform(dedent` - export {Observable} from 'rxjs'; - `)).toEqual(dedent` - export { Observable } from 'rxjs/bundles/Rx.min.js'; - `); - }); - - it('ignore-other', () => { - expect(transform(dedent` - import path from 'path'; - `)).toEqual(dedent` - import path from 'path'; - `); - }); - - it('import-minified', () => { - expect(transform(dedent` - import Rx from 'rxjs'; - import {Observable} from 'rxjs'; - assert(Rx.Observable === Observable); - `)).toEqual(dedent` - import Rx from 'rxjs/bundles/Rx.min.js'; - import { Observable } from 'rxjs/bundles/Rx.min.js'; - assert(Rx.Observable === Observable); - `); - }); - - it('no-type', () => { - expect(transform(dedent` - import type {using} from 'rxjs/observable/using'; - `)).toEqual(dedent` - import type { using } from 'rxjs/observable/using'; - `); - }); - - it('require-minified', () => { - expect(transform(dedent` - const Rx = require('rxjs'); - const {Observable} = require('rxjs'); - assert(Rx.Observable === Observable); - `)).toEqual(dedent` - const Rx = require('rxjs/bundles/Rx.min.js'); - const { Observable } = require('rxjs/bundles/Rx.min.js'); - assert(Rx.Observable === Observable); - `); - }); - - it('with-inline-imports', () => { - expect(transform(dedent` - import Rx from 'rxjs'; - assert(Rx.Observable === Observable); - `, [ - require('babel-plugin-transform-inline-imports-commonjs'), - ])).toEqual(dedent` - 'use strict'; - - var _RxMin; - - function _load_RxMin() { - return _RxMin = _interopRequireDefault(require('rxjs/bundles/Rx.min.js')); - } - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - assert((_RxMin || _load_RxMin()).default.Observable === Observable); - `); - }); - - it('only-entry-module', () => { - expect(() => { - transform(transform(dedent` - import {using} from 'rxjs/observable/using'; - `)); - }).toThrow( - new SyntaxError('unknown: Only importing "rxjs" is supported. rxjs/observable/using') - ); - }); -}); diff --git a/modules/scripts/atom-test-runner.js b/modules/scripts/atom-test-runner.js deleted file mode 100644 index cdcc57f0..00000000 --- a/modules/scripts/atom-test-runner.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ - -/** - * A simple test runner with some additional features: - * 1. loads nuclide-node-transpiler - * 2. cleans up tempfiles on exit - * - * Note that this does *not* load "atomConfig" settings from package.json files. - * Tests will have to mock out Atom configs if they rely on these. - */ - -// TODO(#21523621): Use a regular require once Yarn workspaces are enforced -// eslint-disable-next-line rulesdir/modules-dependencies -require('../nuclide-node-transpiler'); - -module.exports = function(params) { - return params.legacyTestRunner(params) - .then(statusCode => { - return new Promise(resolve => { - const temp = require('temp'); - if (statusCode === 0) { - // Atom intercepts "process.exit" so we have to do our own manual cleanup. - temp.cleanup((err, stats) => { - resolve(statusCode); - if (err && err.message !== 'not tracking') { - // eslint-disable-next-line no-console - console.log(`temp.cleanup() failed. ${err}`); - } - }); - } else { - // When the test fails, we keep the temp contents for debugging. - temp.track(false); - resolve(statusCode); - } - }); - }); -}; diff --git a/modules/scripts/prepublish.sh b/modules/scripts/prepublish.sh deleted file mode 100755 index 640967fc..00000000 --- a/modules/scripts/prepublish.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2015-present, Facebook, Inc. -# All rights reserved. -# -# This source code is licensed under the license found in the LICENSE file in -# the root directory of this source tree. - -set -e - -OWN_DIR=$(dirname "$0") -CALLING_DIR="$(pwd -P)" - -echo "Module prepublish: making copies for flow (1 / 2)..." -find "$CALLING_DIR" \ - -name '*.js' \ - -not -path '*/spec*' -exec cp -n {} {}.flow \; - -echo "Module prepublish: compiling source (2 / 2) ..." -"$OWN_DIR/../nuclide-node-transpiler/bin/release-transpile.js" --overwrite "$CALLING_DIR" -rm -f DEVELOPMENT diff --git a/scripts/apm-publish.sh b/scripts/apm-publish.sh deleted file mode 100755 index 06df610b..00000000 --- a/scripts/apm-publish.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2015-present, Facebook, Inc. -# All rights reserved. -# -# This source code is licensed under the license found in the LICENSE file in -# the root directory of this source tree. - -set -e - -THIS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -VERSION="v$(node -p 'require("./package.json").version')" - -echo "Using Atom version:" -atom -v -echo "Using APM version:" -apm -v - -if ! apm stars >/dev/null; then - echo "Not logged in to apm." - exit 1 -fi -if ! git config --get user.email >/dev/null; then - echo "Git \"user.email\" not set." - exit 1 -fi -if ! git config --get user.name >/dev/null; then - echo "Git \"user.name\" not set." - exit 1 -fi - -# Force a detached HEAD -git checkout "$(git rev-parse HEAD)" - -npm run release-transpile -- --overwrite - -# Add additional files to ignore for publishing. -cat .gitignore.release >> .gitignore -# Remove newly ignored files from the commit. -git ls-files --ignored --exclude-standard -z | xargs -0 git rm --cached - -git add -A && git commit -m "Release ${VERSION}" - -if [[ "$1" != "--dry-run" ]]; then - git tag "${VERSION}" - git push origin "${VERSION}" - - apm publish --tag "${VERSION}" -fi diff --git a/scripts/devDependencies.json b/scripts/devDependencies.json deleted file mode 100644 index 0c4d819d..00000000 --- a/scripts/devDependencies.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "eslint-plugin-dependencies": "2.4.0", - "eslint-plugin-flowtype": "2.30.0", - "eslint-plugin-jasmine": "2.2.0", - "eslint-plugin-jsx-a11y": "5.0.3", - "eslint-plugin-prefer-object-spread": "1.1.0", - "eslint-plugin-prettier": "2.1.0", - "eslint-plugin-react": "6.8.0", - "eslint-plugin-rulesdir": "0.1.0", - "flow-bin": "0.53.1", - "prettier": "1.5.2" -} diff --git a/scripts/sync-nuclide.sh b/scripts/sync-nuclide.sh deleted file mode 100755 index c40e6060..00000000 --- a/scripts/sync-nuclide.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -set -e - -SYNC_PATHS=(flow-libs flow-typed modules ':!modules/big-dig*') -SYNC_BRANCH=nuclide-sync -SYNC_MESSAGE="Sync with facebook/nuclide" - -if [ -n "$(git status --porcelain)" ]; then - echo "Uncommitted changes detected; exiting." - exit 1 -fi - -git branch -f "$SYNC_BRANCH" master -echo "** Checking out branch $SYNC_BRANCH" -git checkout --quiet "$SYNC_BRANCH" - -# Ensure that we have "nuclide" set up as a remote. -echo "** Fetching the latest Nuclide commits" -git remote add nuclide https://github.com/facebook/nuclide 2> /dev/null || true -git fetch nuclide - -LAST_SYNC_MESSAGE=$(git log --pretty=%s | grep "$SYNC_MESSAGE" | head -n 1) -LAST_SYNC_COMMIT="${LAST_SYNC_MESSAGE##*@}" # Everything after the "@". -HEAD_COMMIT=$(git rev-parse nuclide/master) - -if [[ "$HEAD_COMMIT" == "$LAST_SYNC_COMMIT" ]]; then - echo "Already up to date." - exit 0 -fi - -echo "** Last sync was $LAST_SYNC_COMMIT" -echo "** Syncing with $HEAD_COMMIT" -git format-patch --stdout "$LAST_SYNC_COMMIT..nuclide/master" -- "${SYNC_PATHS[@]}" > /tmp/patches -git am --3way /tmp/patches - -echo "** Merging back with master" -git checkout master -git merge --no-ff -m "$SYNC_MESSAGE@$HEAD_COMMIT" "$SYNC_BRANCH" -git branch -D "$SYNC_BRANCH" diff --git a/scripts/test.js b/scripts/test.js deleted file mode 100755 index a934607e..00000000 --- a/scripts/test.js +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env node -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ -/* eslint-disable no-console */ - -/** - * Runs 'npm test' for all packages under modules/. - */ - -const child_process = require('child_process'); -const {getModules} = require('./util'); - -getModules().forEach(dirpath => { - console.log('Running tests for ' + dirpath); - try { - child_process.execFileSync('npm', ['test'], { - cwd: dirpath, - stdio: 'inherit', - }); - } catch (e) { - process.exit(1); - } -}); diff --git a/scripts/update-deps.js b/scripts/update-deps.js deleted file mode 100755 index cf18d2f0..00000000 --- a/scripts/update-deps.js +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env node -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ -/* eslint-disable no-console */ - -/** - * Normally, 'yarn workspaces' takes care of including the deps in modules/. - * However, since APM uses 'npm install', we can't rely on this behavior. - */ - -const assert = require('assert'); -const fs = require('fs'); -const path = require('path'); -const pkgJson = require('../package.json'); -const {getModules} = require('./util'); - -const modulePaths = getModules(); -const moduleNames = new Set(modulePaths.map(p => path.basename(p))); - -function addDependencies(pkgDeps, moduleDeps) { - Object.keys(moduleDeps).forEach(dep => { - // Internal dependencies should be ignored. - if (moduleNames.has(dep)) { - return; - } - const currentDep = pkgDeps[dep]; - const moduleDep = moduleDeps[dep]; - assert( - currentDep == null || currentDep === moduleDep, - `Mismatched dependency ${dep}: ${currentDep} vs ${moduleDep}` - ); - pkgDeps[dep] = moduleDep; - }); -} - -function sortObject(obj) { - const newObject = {}; - Object.keys(obj).sort().forEach(key => { - newObject[key] = obj[key]; - }); - return newObject; -} - -// Core dev dependencies. -const devDependencies = require(path.join(__dirname, 'devDependencies.json')); -addDependencies(pkgJson.devDependencies, devDependencies); - -// Pull in dependencies from modules. -modulePaths.forEach(dirpath => { - const modulePkg = require(path.join(dirpath, 'package.json')); - addDependencies(pkgJson.dependencies, modulePkg.dependencies || {}); - addDependencies(pkgJson.devDependencies, modulePkg.devDependencies || {}); -}); - -// Don't list a dependency twice! -Object.keys(pkgJson.devDependencies).forEach(dep => { - if (pkgJson.dependencies[dep]) { - delete pkgJson.devDependencies[dep]; - } -}); - -pkgJson.dependencies = sortObject(pkgJson.dependencies); -pkgJson.devDependencies = sortObject(pkgJson.devDependencies); - -fs.writeFileSync( - require.resolve('../package.json'), - JSON.stringify(pkgJson, null, 2) + '\n' -); diff --git a/scripts/util.js b/scripts/util.js deleted file mode 100644 index e1005e0c..00000000 --- a/scripts/util.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @noflow - */ -'use strict'; - -/* eslint - comma-dangle: [1, always-multiline], - prefer-object-spread/prefer-object-spread: 0, - rulesdir/no-commonjs: 0, - */ - -const fs = require('fs'); -const path = require('path'); -const MODULES_PATH = path.join(__dirname, '..', 'modules'); - -function getModules() { - return fs.readdirSync(MODULES_PATH) - .map(dirname => { - const dirpath = path.join(MODULES_PATH, dirname); - if ( - fs.statSync(dirpath).isDirectory() && - fs.existsSync(path.join(dirpath, 'package.json')) - ) { - return dirpath; - } - }) - .filter(Boolean); -} - -module.exports = { - getModules, -};