Flow errors #44

Closed
salas-wcd opened this Issue Aug 21, 2015 · 20 comments

Projects

None yet

9 participants

@salas-wcd

Im getting a bunch of flowtype error, is it normal ??

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/Deferred.js:14:15,32: Promise
Required module not found

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/Deferred.js:39:15,15: return
Missing annotation

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/PromiseMap.js:15:16,34: Deferred
Required module not found

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/PromiseMap.js:17:17,36: invariant
Required module not found

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/PromiseMap.js:19:31,39: Promise
Required module not found

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/fetchWithRetries.js:16:28,58: ExecutionEnvironment
Required module not found

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/fetchWithRetries.js:17:15,32: Promise
Required module not found

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/fetchWithRetries.js:19:15,32: sprintf
Required module not found

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/fetchWithRetries.js:20:13,28: fetch
Required module not found

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/fetchWithRetries.js:21:15,32: warning
Required module not found

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/resolveImmediate.js:13:15,32: Promise
Required module not found
@zpao
Member
zpao commented Aug 21, 2015

You probably want to exclude that with your flowconfig. For example, here's what Relay does: https://github.com/facebook/relay/blob/master/src/.flowconfig#L4

I'm going to close out since I think that's the only answer. cc @yungsters in case.

@zpao zpao closed this Aug 21, 2015
@samwgoldman
Member

I think there are some real bugs here. For example, if I track down the source of the first error:

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/Deferred.js:14:15,32: Promise
Required module not found

Inide flow/include/Deferred.js we see this line: var Promise = require("Promise"). That line comes from fbjs/lib/Deferred.js, where it's actually var Promise = require("./Promise")—the relative path got stripped out somehow. If the process that creates the files in flow/include maintained the relative path, there would not be a Flow error there.

@samwgoldman
Member

The error I described above cascades and causes the second error, because Promise is never imported, and is thus not a type:

/Path/to/my/project/node_modules/react/node_modules/fbjs/flow/include/Deferred.js:39:15,15: return
Missing annotation

(The "missing annotation" is in a return this._promise statement, where _promise: Promise.)

The third and forth error have the same cause as the first: relative paths become absolute.

The fifth error is weirder. flow/include/PromiseMap.js has a line import type * as Promise from 'Promise' but no similar line exists in fbjs/lib/PromiseMap.js—indeed that file isn't even typechecked.

I'll have to look deeper into the workflow that generates the files in flow/include.

@samwgoldman
Member

OK, I realize my mistake—the flow/include files are based on the files in src which are pre-transform and use non-relative requires. Sorry for the stream of consciousness here, but I think this is still a fbjs issue—the files in flow/include should have relative paths like the files in lib do.

@samwgoldman
Member

So the issue is that the gulp flow process needs to do module mapping, similar to how gulp lib does, using the babel plugin in scripts/babel/rewrite-modules.

I tried changing the gulp task to the following:

gulp.task('flow', function() {
  var babelOpts = assign({}, babelDefaultOptions, {
    whitelist: []
  });

  return gulp
    .src(paths.lib.src)
    .pipe(gulpModuleMap(moduleMapOpts))
    .pipe(babel(babelOpts))
    .pipe(flatten())
    .pipe(gulp.dest(paths.flowInclude));
});

Note that we don't want to actually transform any of the source code. Unfortunately, we run into errors like this:

SyntaxError: /path/to/fbjs/src/fetch/fetchWithRetries.js: Unexpected token (45:34)
  43 |   initWithRetries?: ?InitWithRetries
  44 | ): Promise {
> 45 |   var {fetchTimeout, retryDelays, ...init} = initWithRetries || {};
     |                                   ^

I confirmed over in the Babel slack channel that Babel ES7 parsing is only enabled if the accompanying transform is also enabled, but for consumption by Flow, we don't want transformations—we just want to run this plugin. @sebmck, can we work around this?

@kittens
Member
kittens commented Aug 26, 2015

Why do you want to run flow over some Babel compiled code? There's currently no way to do this.

On Tue, Aug 25, 2015 at 6:08 PM, Sam Goldman notifications@github.com
wrote:

So the issue is that the gulp flow process needs to do module mapping, similar to how gulp lib does, using the babel plugin in scripts/babel/rewrite-modules.
I tried changing the gulp task to the following:

gulp.task('flow', function() {
  var babelOpts = assign({}, babelDefaultOptions, {
    whitelist: []
  });
  return gulp
    .src(paths.lib.src)
    .pipe(gulpModuleMap(moduleMapOpts))
    .pipe(babel(babelOpts))
    .pipe(flatten())
    .pipe(gulp.dest(paths.flowInclude));
});

Note that we don't want to actually transform any of the source code. Unfortunately, we run into errors like this:

SyntaxError: /path/to/fbjs/src/fetch/fetchWithRetries.js: Unexpected token (45:34)
  43 |   initWithRetries?: ?InitWithRetries
  44 | ): Promise {
> 45 |   var {fetchTimeout, retryDelays, ...init} = initWithRetries || {};
     |                                   ^

I confirmed over in the Babel slack channel that Babel ES7 parsing is only enabled if the accompanying transform is also enabled, but for consumption by Flow, we don't want transformations—we just want to run this plugin. @sebmck, can we work around this?

Reply to this email directly or view it on GitHub:
#44 (comment)

@samwgoldman
Member

@sebmck Thanks for your time. Sorry for being unclear. I'll try to be more explicit below:

There is a build process in this repo that creates files in flow/include, the intended purpose of which is somewhat unclear to me, but it's causing Flow errors for any project that includes fbjs (including indirectly, through React 0.14 betas).

While there is a workaround (tell flow to ignore these files in every project), it's not ideal. More importantly, the errors aren't just Flow being confused about valid code. Flow is complaining about a real issue:

This code is generated using a gulp task, defined here, which flattens all the files in src.

However, those files in src are using some FB-defined module system that allows require "Promise" to find the module that is annotated with @providesModule Promise, so just flattening them isn't enough, we also need to map the modules to use relative paths, as the existing gulp lib build command does.

This module mapping stuff is built as a babel plugin. So, in order to create files which can be analyzed by Flow, we need to module map, and thus go through Babel—but just for the plugin, not for any transforms.

So, I tried to modify the gulp flow build step to use the same module mapper plugin, but not any transforms (whitelist: []). Since the code in src uses ES7 features, this fails at the babel parser step, which disables parsing for ES7 syntax unless the relevant transforms are enabled.

Now, maybe this is all moot, because the code in flow/include is kind of mysterious to me. Maybe the better solution is to omit these files from the npm package, since I don't think they are useful to anyone, except maybe FB?

@zpao
Member
zpao commented Aug 26, 2015

The flow config in you need in your destination project is a bit unruly at the moment.

You need both of these, otherwise you get issues with Deferred.

[lib]
../node_modules/fbjs/flow/include
../node_modules/fbjs/node_modules/promise

If you're using React you'll also need to ignore react node_modules

[ignore]
.*/react/node_modules/.*

You might also need to tell flow to use the Haste module system so that it resolves the modules right.

[options]
module.system=haste

This is probably the main problem that you're having BUT it might also not be right for you. This would be the main problem but it's also tricky because we do use Haste and you probably don't. It might still work though since I would hope Flow does a good job of actually resolving when it needs to.

All of the above code bits came from the Relay flowconfig where this is working which is why I linked to it above. So it is possible but there are probably some issues when fbjs is a nested dependency.

If you are consuming the code here and you are not also a Facebook project, be prepared for a bad time.

I put that in the readme for a reason :) We're still figuring out how to make this work in a general way but we are optimizing for ourselves so that we can ship things like Relay faster.

Maybe the better solution is to omit these files from the npm package, since I don't think they are useful to anyone, except maybe FB?

The original goal was to embed the type annotations in the files themselves via the comment syntax, and we did that initially. But the comment syntax doesn't support the full range of Flow capabilities (namely polymorphic classes, see #23) so we decided to ship the original source which we know Flow does understand.

Perhaps another way around this until inline comments is viable is to instead ship fbjs-flow as a standalone package, only used as a devDep. I'm not sure how that will work when fbjs is a nested dependency and you want to typecheck.

@zpao
Member
zpao commented Aug 26, 2015

@samwgoldman what would be really helpful is if you could create a sample project showing what you're doing and the use case you'd like us to support. Otherwise we're working a bit of a black box and dealing in hypotheticals and assumptions.

@samwgoldman
Member

@zpao Sure. And, for what it's worth, I'm pulling this thread from the perspective of a frequent Flow contributor who wants to make it easier for people to get started using Flow. Right now it's not a great experience, and I want to improve it to improve adoption of Flow. I'll follow up with a repo.

@zpao
Member
zpao commented Aug 26, 2015

Perfect, thanks! (and thanks for the work on Flow, I know the team appreciates all the help and it's great to have somebody coming at this problem from that side)

@ludovicofischer ludovicofischer referenced this issue in chenglou/react-motion Oct 4, 2015
Merged

First pass adding flow annotations. #187

@kassens kassens added a commit to kassens/react-devtools that referenced this issue Oct 9, 2015
@kassens kassens Upgrade to React 0.14.0
- update package.json
- React.findDOMNode » ReactDOM.findDOMNode
- React.addons.createFragment » react-addons-create-fragment
- update `.flowconfig` (see facebook/fbjs#44)
3e76d0b
@kassens kassens referenced this issue in facebook/react-devtools Oct 9, 2015
Merged

Upgrade to React 0.14.2 #256

@kassens kassens added a commit to kassens/react-devtools that referenced this issue Oct 9, 2015
@kassens kassens Upgrade to React 0.14.0
- update package.json
- React.findDOMNode » ReactDOM.findDOMNode
- React.addons.createFragment » react-addons-create-fragment
- update `.flowconfig` (see facebook/fbjs#44)
cf6dd3c
@kassens kassens added a commit to kassens/react-devtools that referenced this issue Oct 9, 2015
@kassens kassens Upgrade to React 0.14.0
- update package.json
- React.findDOMNode » ReactDOM.findDOMNode
- React.addons.createFragment » react-addons-create-fragment
- update `.flowconfig` (see facebook/fbjs#44)
e6c7ad1
@kassens kassens added a commit to kassens/react-devtools that referenced this issue Nov 11, 2015
@kassens kassens Upgrade to React 0.14.2
- update package.json
- React.findDOMNode » ReactDOM.findDOMNode
- React.addons.createFragment » react-addons-create-fragment
- update `.flowconfig` (see facebook/fbjs#44)
6d17c87
@amacneil

For anyone else trying to use flow and completely lost like I just was, if you are using node 5 you need to add these lines to your .flowconfig instead (due to how npm 3 flattens the dependency tree):

[ignore]
.*node_modules/fbjs.*
.*node_modules/webpack.*
@runn1ng runn1ng referenced this issue in facebook/flow Jan 1, 2016
Open

Is the "flux example" up to date? #1211

@runn1ng
runn1ng commented Jan 1, 2016

Hm. I don't like that. I don't want to ignore modules that are using Flow.... intuitively speaking, isn't it the opposite of what I would want?

When a module is using flow, I want to use its declarations and so on, instead of ignoring it.

But maybe I am just lost in this include/ignore/module thing

@spicyj
Member
spicyj commented Jan 2, 2016

In fbjs 0.6, the definitions are included in a way that should work better with Flow. I can't promise how well it works but it may work better than it did previously.

@runn1ng
runn1ng commented Jan 2, 2016

Oh. The flux example is using old react, it seems! Which, then, uses old fbjs, which causes the errors! That might be the reason. I will try to update the flux example with new react, that might fix it

@runn1ng
runn1ng commented Jan 2, 2016

Oh. No. It's because flux explicitly has a dependency on 0.4.0 version of fbjs. Well, let's try to update that...

@runn1ng
runn1ng commented Jan 2, 2016

No. When I explicitly update fbjs to 0.6.0 in the flux example (via changing it in the flux node dependency), it still does the same error, with failing to include Promise :-(

(sorry for so many messages!)

@donaldpipowitch

I use fbjs@0.6.1 and npm@3.5.2, but it has the same errors:

node_modules/fbjs/lib/PromiseMap.js.flow:15
 15: var Deferred = require('Deferred');
                    ^^^^^^^^^^^^^^^^^^^ Deferred. Required module not found

node_modules/fbjs/lib/fetchWithRetries.js.flow:16
 16: var ExecutionEnvironment = require('ExecutionEnvironment');
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ExecutionEnvironment. Required module not found

node_modules/fbjs/lib/fetchWithRetries.js.flow:19
 19: var sprintf = require('sprintf');
                   ^^^^^^^^^^^^^^^^^^ sprintf. Required module not found

node_modules/fbjs/lib/fetchWithRetries.js.flow:20
 20: var fetch = require('fetch');
                 ^^^^^^^^^^^^^^^^ fetch. Required module not found

node_modules/fbjs/lib/fetchWithRetries.js.flow:21
 21: var warning = require('warning');
                   ^^^^^^^^^^^^^^^^^^ warning. Required module not found


Found 5 errors

Ignoring works, but I have to agree with @runn1ng that this isn't the best way...

[ignore]
.*node_modules/fbjs.*
@ctrlplusb

I got mine working like so, making sure to import the Promise lib first:

[libs]
./node_modules/fbjs/node_modules/promise
./node_modules/fbjs/flow/lib
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment