Summary:
## What is `guard`?
`guard` accepts some JavaScript function that can throw a ParserError. If a ParserError is thrown by that JavaScript function, it captures and pushes the error to some global array, and returns null. If no ParserError is thrown, it simply returns the return value of the JavaScript function. This utility is used in the NativeModule spec parser to help it continue parsing even after it detects errors. Why do we want to do this? In the NativeModule spec linter, we want to display all these ParserErrors via ESLint.
## Changes
This diff renames `guard` to `tryParse` because `tryParse` more appropriately captures the intent/function of this utility: the work passed to it "tries" to parse some Flow types. A name like "guard" is a bit more ambiguous: What is it guarding against? What is the work doing? ¯\_(ツ)_/¯
Changelog: [Internal]
Reviewed By: hramos
Differential Revision: D25156185
fbshipit-source-id: 516647770579daa8613dbd67535074823f1aa848
Summary:
## Changes
1. In the NativeModule spec parser, the moduleName is now being extracted from the TurboModuleRegistry.get<Spec>(...) call by examining the Flow ast node. Previously, we used regex parsing, which was unsafe because it could be fooled by TurboModuleRegistry.get<Spec>(...) calls in comments.
2. The logic to parse and validate the TurboModuleRegistry.get<Spec>(...) call is now centralized in the NativeModule Spec Parser (it was removed from the react-native-modules ESLint rule). The linter is now only responsible for three things:
1. Detecting if a JavaScript file contains a TurboModuleRegistry.get<Spec> call or a TurboModule interface, and if so
2. Running the NativeModule spec parser on it.
3. It also validates that the Module spec's filename starts with the prefix "Native".
The React Native Modules linter now completely delegates to the NativeModules Spec parser, without doing any error checking of its own. If an error is reported by the React Native Modules linter, and that error doesn't have anything to do with the "Native" prefix, then it *must* be addressed. Otherwise, it will cause the NativeModule Spec Parser to fail on that particular spec.
Changelog: [Internal]
Reviewed By: hramos
Differential Revision: D25153243
fbshipit-source-id: da74dbb66b1d8dca3a2b1952402222c6696b73d6
Summary:
## Context
We currently run ESLint using `flow-node`. This is a very recent change that was introduced in these two diffs:
- Switch VSCode ESLint plugin using flow-node: D24454702.
- Switch all ESLint scripts to use flow-node: D24379783 (https://github.com/facebook/react-native/commit/ad5802cf916c1cbe3e142385a29810a0d7205c6c).
## Problem
Because `react-native/eslint-plugin-codegen` (written in vanilla JavaScript) requires two files from `react-native-codegen` (written with Flow typings), we force all requires executed while initializing ESLint to compile out Flow types. Issues:
- In the grand scheme of things, this is such a tiny and isolated problem. It shouldn't be the reason why we switch over to using flow node. That's a larger decision that should be discussed outside of this diff.
- On VSCode cold start, in D24454702, I measured that using flow-node adds approximately 320ms to JavaScript file lint time. So, this is just slow.
## Solution
- Switch ESLint back to using regular node:
- Revert the changes to VSCode's ESLint plugin: D24454702
- Revert the changes to the internal ESLint scripts: D24379783 (https://github.com/facebook/react-native/commit/ad5802cf916c1cbe3e142385a29810a0d7205c6c).
- Inside the ESLint plugin, register a temporary require hook to remove Flow types from the NativeModule spec parser, before we require it. We de-register this hook after the requires finish.
## Implementation Notes:
- The `with-babel-register/` is a fork of `babel/register`, except I simplified the implementation based on the assumption that we're using it literally to only compile `react-native-codegen`.
- `with-babel-register/` uses a disk cache, so we only call transformSync when a the input file (1) hasn't been transformed before, or (2) the cache entry was created before the file was last modified.
- I ported over the source-map logic, so that when the NativeModule spec parser throws non-parsing errors, we get the correct stack trace. **Note:** I'm not sure if the source maps will work if there's a babel/register earlier during initialization. However, I don't think this will pose an actual problem, since we don't use a babel/register hook earlier. So, I think we should punt on this investigation.
## Alternative: Why aren't we using babel/register?
Every time you call babel/register, it replaces the last registered hook. We don't want the ESLint plugin to be changing any existing require hooks that people have set up. Abandoned diff with babel/register: D24519349.
Changelog: [Internal]
Reviewed By: cpojer
Differential Revision: D24551549
fbshipit-source-id: bbd7c5be44f74c0e9adbb20fe86e09802410b123
Summary:
Our NativeModule spec parser parses the TurboModuleRegistry.get<Spec>(...) calls to figure out what the name of the NativeModule is. The parser assumes the argument is a string literal. Therefore, we should lint to validate this case.
Changelog: [Internal]
Reviewed By: fkgozali
Differential Revision: D24500412
fbshipit-source-id: 5aa5e9255db5a2e0cd86d6dd96e6787caa673fc4
Summary:
TurboModule specs should have exactly one TurboModuleRegistry.get or TurboModuleRegistry.getEnforcing call. When a JS file contains more than one call into TurboModuleRegistry, this lint rule will report an error on all calls.
Changelog: [Internal]
Reviewed By: fkgozali
Differential Revision: D24499286
fbshipit-source-id: 2c47185165a2a81c4b7b7ad9a7b8458e9aa8c018
Summary:
This diff guts the React Native Modules ESLint rule, and makes it instead call into the NativeModule spec parser. After calling into the parser, the lint rule loops over all collected errors, and reports them.
## Benefits
- There is now one source of truth of what is a "correct" NativeModule spec: The NativeModule spec parser.
- Every change we make to the NativeModule spec parser will reflect in the lint rule. We have a number of changes planned for the NativeModule parser that will change what it means for a NativeModule spec to be correct. These changes now won't have to be duplicated in the ESLint rule.
- The linter will *never* show any false positive errors. If there's an error in the linter, you *need* to fix it. Otherwise, the codegen *will* fail. This is huge. Previously, people were used to ignoring the linter, because it over-reported errors. This behavior won't slide after this stack lands.
NOTE: This will run the NativeModules parser on all our NativeModule specs. We may have to check the specs, or the parser. Therefore, this could take some time to land.
## How does the lint rule work now?
In every JavaScript file, the ESLint rule looks for `CallExpression` AST Nodes. Once it detects a `CallExpression` that corresponds to a `TurboModuleRegistry.get` or `TurboModuleRegistry.getEnforcing` it:
1. Marks the file as a TurboModule spec
2. Validates the `CallExpression` to verify that it is called with the <Spec> type parameters (i.e: like this: TurboModuleRegistry.get<Spec>(...)).
When we're done the visition for the JavaScript file (i.e: in `Program:exit`), if the JavaScript file was a TurboModule spec:
1. Report a lint error if the filename doesn't start with Native.
2. We parse the source using flow-parser, and run the NativeModule spec parser on it. We capture all ParserErrors and report them via ESLint.
## When can I start using this lint rule in VSCode?
I made the ESLint VSCode plugin use flow-node in D24454702. It'll take 3-4 weeks for this change to be shipped to everyone's VSCode. After the update, the linter will automatically start working in VSCode. Until then, we'll only get feedback on Sandcastle/Landcastle for lint rule violations.
Changelog: [Internal]
Reviewed By: fkgozali
Differential Revision: D24379783
fbshipit-source-id: 222778d8a84d7010eb7b3ad71b34a7fe1f52e509
Summary:
Open source this ESLint rule so that we can lint our open source NativeModule specs.
Changelog: [Internal]
Reviewed By: shergin, cpojer
Differential Revision: D23791748
fbshipit-source-id: e44444bc87eaa9dc9b7f2b3ed03151798a35e8a5