mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[be] Fix remaining lints and enable lint in CI
This commit is contained in:
Vendored
+2
@@ -21,5 +21,7 @@ jobs:
|
||||
working-directory: forget
|
||||
- run: yarn build
|
||||
working-directory: forget
|
||||
- run: yarn lint
|
||||
working-directory: forget
|
||||
- run: yarn test
|
||||
working-directory: forget
|
||||
|
||||
@@ -56,6 +56,7 @@ module.exports = {
|
||||
"constructor",
|
||||
],
|
||||
"@typescript-eslint/array-type": ["off", "generic"],
|
||||
"@typescript-eslint/triple-slash-reference": "off",
|
||||
},
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint"],
|
||||
|
||||
@@ -125,7 +125,7 @@ export class CompilerError extends Error {
|
||||
|
||||
override set message(_message: string) {}
|
||||
|
||||
override toString() {
|
||||
override toString(): string {
|
||||
return this.details.map((detail) => detail.toString()).join("\n\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class State {
|
||||
}
|
||||
}
|
||||
|
||||
export default function analyseFunctions(func: HIRFunction) {
|
||||
export default function analyseFunctions(func: HIRFunction): void {
|
||||
const state = new State();
|
||||
|
||||
for (const [_, block] of func.body.blocks) {
|
||||
@@ -73,7 +73,7 @@ export default function analyseFunctions(func: HIRFunction) {
|
||||
}
|
||||
}
|
||||
|
||||
function lower(func: HIRFunction) {
|
||||
function lower(func: HIRFunction): void {
|
||||
mergeConsecutiveBlocks(func);
|
||||
enterSSA(func);
|
||||
eliminateRedundantPhi(func);
|
||||
@@ -85,7 +85,11 @@ function lower(func: HIRFunction) {
|
||||
logHIRFunction("AnalyseFunction (inner)", func);
|
||||
}
|
||||
|
||||
function infer(value: FunctionExpression, state: State, context: Place[]) {
|
||||
function infer(
|
||||
value: FunctionExpression,
|
||||
state: State,
|
||||
context: Place[]
|
||||
): void {
|
||||
const mutations = new Set(
|
||||
value.loweredFunc.context
|
||||
.filter((dep) => isMutatedOrReassigned(dep.identifier))
|
||||
@@ -127,7 +131,7 @@ function infer(value: FunctionExpression, state: State, context: Place[]) {
|
||||
}
|
||||
}
|
||||
|
||||
function isMutatedOrReassigned(id: Identifier) {
|
||||
function isMutatedOrReassigned(id: Identifier): boolean {
|
||||
// This check checks for mutation and reassingnment, so the usual check for
|
||||
// mutation (ie, `mutableRange.end - mutableRange.start > 1`) isn't quite
|
||||
// enough.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Effect, HIRFunction, HookType, isHookType } from "../HIR";
|
||||
|
||||
export default function (func: HIRFunction) {
|
||||
export default function (func: HIRFunction): void {
|
||||
for (const [_, block] of func.body.blocks) {
|
||||
for (const instr of block.instructions) {
|
||||
switch (instr.value.kind) {
|
||||
|
||||
@@ -20,7 +20,10 @@ export function inferAliases(func: HIRFunction): DisjointSet<Identifier> {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
function inferInstr(instr: Instruction, aliases: DisjointSet<Identifier>) {
|
||||
function inferInstr(
|
||||
instr: Instruction,
|
||||
aliases: DisjointSet<Identifier>
|
||||
): void {
|
||||
const { lvalue, value: instrValue } = instr;
|
||||
let alias: Place | null = null;
|
||||
switch (instrValue.kind) {
|
||||
|
||||
@@ -10,7 +10,7 @@ import DisjointSet from "../Utils/DisjointSet";
|
||||
export function inferAliasForPhis(
|
||||
func: HIRFunction,
|
||||
aliases: DisjointSet<Identifier>
|
||||
) {
|
||||
): void {
|
||||
for (const [_, block] of func.body.blocks) {
|
||||
for (const phi of block.phis) {
|
||||
const isPhiMutatedAfterCreation: boolean =
|
||||
|
||||
@@ -20,7 +20,7 @@ import DisjointSet from "../Utils/DisjointSet";
|
||||
export function inferAliasForStores(
|
||||
func: HIRFunction,
|
||||
aliases: DisjointSet<Identifier>
|
||||
) {
|
||||
): void {
|
||||
for (const [_, block] of func.body.blocks) {
|
||||
for (const instr of block.instructions) {
|
||||
const { value, lvalue } = instr;
|
||||
|
||||
@@ -60,7 +60,7 @@ import { assertExhaustive } from "../Utils/utils";
|
||||
* ```
|
||||
*/
|
||||
|
||||
function infer(place: Place, instr: Instruction) {
|
||||
function infer(place: Place, instr: Instruction): void {
|
||||
place.identifier.mutableRange.end = makeInstructionId(instr.id + 1);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ function inferPlace(
|
||||
place: Place,
|
||||
instr: Instruction,
|
||||
inferMutableRangeForStores: boolean
|
||||
) {
|
||||
): void {
|
||||
switch (place.effect) {
|
||||
case Effect.Unknown: {
|
||||
throw new Error(
|
||||
@@ -98,7 +98,7 @@ function inferPlace(
|
||||
export function inferMutableLifetimes(
|
||||
func: HIRFunction,
|
||||
inferMutableRangeForStores: boolean
|
||||
) {
|
||||
): void {
|
||||
for (const [_, block] of func.body.blocks) {
|
||||
for (const phi of block.phis) {
|
||||
let start = Number.MAX_SAFE_INTEGER;
|
||||
|
||||
@@ -12,7 +12,7 @@ import { inferAliasForStores } from "./InferAliasForStores";
|
||||
import { inferMutableLifetimes } from "./InferMutableLifetimes";
|
||||
import { inferMutableRangesForAlias } from "./InferMutableRangesForAlias";
|
||||
|
||||
export function inferMutableRanges(ir: HIRFunction) {
|
||||
export function inferMutableRanges(ir: HIRFunction): void {
|
||||
// Infer mutable ranges for non fields
|
||||
inferMutableLifetimes(ir, false);
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ import { HIRFunction, Identifier, InstructionId } from "../HIR/HIR";
|
||||
import DisjointSet from "../Utils/DisjointSet";
|
||||
|
||||
export function inferMutableRangesForAlias(
|
||||
fn: HIRFunction,
|
||||
_fn: HIRFunction,
|
||||
aliases: DisjointSet<Identifier>
|
||||
) {
|
||||
): void {
|
||||
const aliasSets = aliases.buildSets();
|
||||
for (const aliasSet of aliasSets) {
|
||||
// Update mutableRange.end only if the identifiers have actually been
|
||||
|
||||
@@ -76,7 +76,7 @@ import { assertExhaustive } from "../Utils/utils";
|
||||
* When control flow paths converge the types of values are merged together, with the value
|
||||
* types forming a lattice to ensure convergence.
|
||||
*/
|
||||
export default function inferReferenceEffects(fn: HIRFunction) {
|
||||
export default function inferReferenceEffects(fn: HIRFunction): void {
|
||||
// Initial state contains function params
|
||||
// TODO: include module declarations here as well
|
||||
const initialState = InferenceState.empty();
|
||||
@@ -124,7 +124,7 @@ export default function inferReferenceEffects(fn: HIRFunction) {
|
||||
// so track the list of incoming state for each successor block.
|
||||
// These are merged when reaching that block again.
|
||||
const queuedStates: Map<BlockId, InferenceState> = new Map();
|
||||
function queue(blockId: BlockId, state: InferenceState) {
|
||||
function queue(blockId: BlockId, state: InferenceState): void {
|
||||
let queuedState = queuedStates.get(blockId);
|
||||
if (queuedState != null) {
|
||||
// merge the queued states for this block
|
||||
@@ -187,7 +187,7 @@ class InferenceState {
|
||||
/**
|
||||
* (Re)initializes a @param value with its default @param kind.
|
||||
*/
|
||||
initialize(value: InstructionValue, kind: ValueKind) {
|
||||
initialize(value: InstructionValue, kind: ValueKind): void {
|
||||
invariant(
|
||||
value.kind !== "LoadLocal",
|
||||
"Expected all top-level identifiers to be defined as variables, not values"
|
||||
@@ -225,7 +225,7 @@ class InferenceState {
|
||||
/**
|
||||
* Updates the value at @param place to point to the same value as @param value.
|
||||
*/
|
||||
alias(place: Place, value: Place) {
|
||||
alias(place: Place, value: Place): void {
|
||||
const values = this.#variables.get(value.identifier.id);
|
||||
invariant(
|
||||
values != null,
|
||||
@@ -238,7 +238,7 @@ class InferenceState {
|
||||
/**
|
||||
* Defines (initializing or updating) a variable with a specific kind of value.
|
||||
*/
|
||||
define(place: Place, value: InstructionValue) {
|
||||
define(place: Place, value: InstructionValue): void {
|
||||
invariant(
|
||||
this.#values.has(value),
|
||||
`Expected value to be initialized at '${printSourceLocation(value.loc)}'`
|
||||
@@ -262,7 +262,7 @@ class InferenceState {
|
||||
* Similarly, a freeze reference is converted to readonly if the
|
||||
* value is already frozen or is immutable.
|
||||
*/
|
||||
reference(place: Place, effectKind: Effect) {
|
||||
reference(place: Place, effectKind: Effect): void {
|
||||
const values = this.#variables.get(place.identifier.id);
|
||||
if (values === undefined) {
|
||||
place.effect = effectKind === Effect.Mutate ? Effect.Mutate : Effect.Read;
|
||||
@@ -442,7 +442,7 @@ class InferenceState {
|
||||
return result;
|
||||
}
|
||||
|
||||
inferPhi(phi: Phi) {
|
||||
inferPhi(phi: Phi): void {
|
||||
const values: Set<InstructionValue> = new Set();
|
||||
for (const [_, operand] of phi.operands) {
|
||||
const operandValues = this.#variables.get(operand.id);
|
||||
@@ -554,11 +554,10 @@ function mergeValues(a: ValueKind, b: ValueKind): ValueKind {
|
||||
* recording references on the @param state according to JS semantics.
|
||||
*/
|
||||
function inferBlock(
|
||||
env: Environment,
|
||||
|
||||
_env: Environment,
|
||||
state: InferenceState,
|
||||
block: BasicBlock
|
||||
) {
|
||||
): void {
|
||||
for (const phi of block.phis) {
|
||||
state.inferPhi(phi);
|
||||
}
|
||||
@@ -876,7 +875,7 @@ function inferBlock(
|
||||
function hasContextRefOperand(
|
||||
state: InferenceState,
|
||||
instrValue: InstructionValue
|
||||
) {
|
||||
): boolean {
|
||||
for (const place of eachInstructionValueOperand(instrValue)) {
|
||||
if (state.isDefined(place) && state.kind(place) === ValueKind.Context) {
|
||||
return true;
|
||||
|
||||
@@ -119,7 +119,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean {
|
||||
const testValue = read(constants, terminal.test);
|
||||
if (testValue !== null) {
|
||||
hasChanges = true;
|
||||
const targetBlockId = Boolean(testValue.value)
|
||||
const targetBlockId = testValue.value
|
||||
? terminal.consequent
|
||||
: terminal.alternate;
|
||||
block.terminal = {
|
||||
|
||||
@@ -60,7 +60,7 @@ export function deadCodeElimination(fn: HIRFunction): void {
|
||||
}
|
||||
for (const phi of block.phis) {
|
||||
if (used.has(phi.id)) {
|
||||
for (const [pred, operand] of phi.operands) {
|
||||
for (const [_pred, operand] of phi.operands) {
|
||||
used.add(operand);
|
||||
}
|
||||
}
|
||||
@@ -196,7 +196,6 @@ function pruneableValue(
|
||||
case "ArrayExpression":
|
||||
case "BinaryExpression":
|
||||
case "ComputedLoad":
|
||||
case "ComputedStore":
|
||||
case "FunctionExpression":
|
||||
case "LoadLocal":
|
||||
case "JsxExpression":
|
||||
|
||||
@@ -498,9 +498,6 @@ function codegenInstruction(
|
||||
cx.temp.set(instr.lvalue.identifier.id, value);
|
||||
return t.emptyStatement();
|
||||
} else {
|
||||
const kind = cx.hasDeclared(instr.lvalue.identifier)
|
||||
? InstructionKind.Reassign
|
||||
: InstructionKind.Const;
|
||||
if (cx.hasDeclared(instr.lvalue.identifier)) {
|
||||
return createExpressionStatement(
|
||||
instr.loc,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import invariant from "invariant";
|
||||
import { Identifier, IdentifierId, ReactiveScopeDependency } from "../HIR";
|
||||
import { Identifier, ReactiveScopeDependency } from "../HIR";
|
||||
import { printIdentifier } from "../HIR/PrintHIR";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
|
||||
@@ -46,7 +46,7 @@ export class ReactiveScopeDependencyTree {
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
add(dep: ReactiveScopeDependencyInfo) {
|
||||
add(dep: ReactiveScopeDependencyInfo): void {
|
||||
const path = dep.path ?? [];
|
||||
let currNode = this.#getOrCreateRoot(dep.identifier);
|
||||
|
||||
@@ -102,7 +102,7 @@ export class ReactiveScopeDependencyTree {
|
||||
depsFromInnerScope: ReactiveScopeDependencyTree,
|
||||
innerScopeInConditionalWithinParent: boolean,
|
||||
checkValidDepIdFn: (id: Identifier) => boolean
|
||||
) {
|
||||
): void {
|
||||
for (const [id, otherRoot] of depsFromInnerScope.#roots) {
|
||||
if (!checkValidDepIdFn(id)) {
|
||||
continue;
|
||||
@@ -119,7 +119,7 @@ export class ReactiveScopeDependencyTree {
|
||||
|
||||
promoteDepsFromExhaustiveConditionals(
|
||||
trees: Array<ReactiveScopeDependencyTree>
|
||||
) {
|
||||
): void {
|
||||
invariant(
|
||||
trees.length > 1,
|
||||
"Expected trees to be at least 2 elements long."
|
||||
@@ -180,13 +180,13 @@ enum PropertyAccessType {
|
||||
UnconditionalDependency = "UnconditionalDependency",
|
||||
}
|
||||
|
||||
function isUnconditional(access: PropertyAccessType) {
|
||||
function isUnconditional(access: PropertyAccessType): boolean {
|
||||
return (
|
||||
access === PropertyAccessType.UnconditionalAccess ||
|
||||
access === PropertyAccessType.UnconditionalDependency
|
||||
);
|
||||
}
|
||||
function isDependency(access: PropertyAccessType) {
|
||||
function isDependency(access: PropertyAccessType): boolean {
|
||||
return (
|
||||
access === PropertyAccessType.ConditionalDependency ||
|
||||
access === PropertyAccessType.UnconditionalDependency
|
||||
@@ -318,7 +318,7 @@ function deriveMinimalDependenciesInSubtree(
|
||||
* conditional equivalent, mutating subtree in place.
|
||||
* @param subtree unconditional node representing a subtree of dependencies
|
||||
*/
|
||||
function demoteSubtreeToConditional(subtree: DependencyNode) {
|
||||
function demoteSubtreeToConditional(subtree: DependencyNode): void {
|
||||
const stack: Array<DependencyNode> = [subtree];
|
||||
|
||||
let node;
|
||||
@@ -355,7 +355,7 @@ function addSubtree(
|
||||
currNode: DependencyNode,
|
||||
otherNode: DependencyNode,
|
||||
demoteOtherNode: boolean
|
||||
) {
|
||||
): void {
|
||||
let otherType = otherNode.accessType;
|
||||
if (demoteOtherNode) {
|
||||
otherType = isDependency(otherType)
|
||||
@@ -405,7 +405,7 @@ function addSubtree(
|
||||
function addSubtreeIntersection(
|
||||
otherProperties: Array<Map<string, DependencyNode>>,
|
||||
currProperties: Map<string, DependencyNode>
|
||||
) {
|
||||
): void {
|
||||
invariant(
|
||||
otherProperties.length > 1,
|
||||
"[DeriveMinimalDependencies] Expected otherProperties to be at least 2 elements long."
|
||||
|
||||
@@ -29,7 +29,7 @@ class State {
|
||||
}
|
||||
|
||||
class Visitor extends ReactiveFunctionVisitor<State> {
|
||||
override visitInstruction(instr: ReactiveInstruction, state: State) {
|
||||
override visitInstruction(instr: ReactiveInstruction, state: State): void {
|
||||
this.traverseInstruction(instr, state);
|
||||
const lval = instr.lvalue;
|
||||
if (lval == null) {
|
||||
|
||||
@@ -158,7 +158,7 @@ class Context {
|
||||
*/
|
||||
promoteDepsFromExhaustiveConditionals(
|
||||
depsInConditionals: Array<ReactiveScopeDependencyTree>
|
||||
) {
|
||||
): void {
|
||||
this.#dependencies.promoteDepsFromExhaustiveConditionals(
|
||||
depsInConditionals
|
||||
);
|
||||
@@ -205,7 +205,7 @@ class Context {
|
||||
}
|
||||
|
||||
// Checks if identifier is a valid dependency in the current scope
|
||||
#checkValidDependencyId(identifier: Identifier) {
|
||||
#checkValidDependencyId(identifier: Identifier): boolean {
|
||||
// If this operand is used in a scope, has a dynamic value, and was defined
|
||||
// before this scope, then its a dependency of the scope.
|
||||
const currentDeclaration =
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
* and phis rewrite all their identifiers based on this table. The algorithm loops over the CFG repeatedly
|
||||
* until there are no new rewrites: for a CFG without back-edges it completes in a single pass.
|
||||
*/
|
||||
export function eliminateRedundantPhi(fn: HIRFunction) {
|
||||
export function eliminateRedundantPhi(fn: HIRFunction): void {
|
||||
const ir = fn.body;
|
||||
const rewrites: Map<Identifier, Identifier> = new Map();
|
||||
|
||||
@@ -111,7 +111,10 @@ export function eliminateRedundantPhi(fn: HIRFunction) {
|
||||
} while (rewrites.size > size && hasBackEdge);
|
||||
}
|
||||
|
||||
function rewritePlace(place: Place, rewrites: Map<Identifier, Identifier>) {
|
||||
function rewritePlace(
|
||||
place: Place,
|
||||
rewrites: Map<Identifier, Identifier>
|
||||
): void {
|
||||
const rewrite = rewrites.get(place.identifier);
|
||||
if (rewrite != null) {
|
||||
place.identifier = rewrite;
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from "../HIR/HIR";
|
||||
import { eachInstructionLValue, eachInstructionOperand } from "../HIR/visitors";
|
||||
|
||||
function isPrimitiveBinaryOp(op: t.BinaryExpression["operator"]) {
|
||||
function isPrimitiveBinaryOp(op: t.BinaryExpression["operator"]): boolean {
|
||||
switch (op) {
|
||||
case "+":
|
||||
case "-":
|
||||
@@ -22,7 +22,6 @@ function isPrimitiveBinaryOp(op: t.BinaryExpression["operator"]) {
|
||||
case "&":
|
||||
case "|":
|
||||
case ">>":
|
||||
case ">>":
|
||||
case "<<":
|
||||
case "^":
|
||||
case ">":
|
||||
@@ -36,7 +35,7 @@ function isPrimitiveBinaryOp(op: t.BinaryExpression["operator"]) {
|
||||
}
|
||||
}
|
||||
|
||||
export default function (func: HIRFunction) {
|
||||
export default function (func: HIRFunction): void {
|
||||
const unifier = new Unifier();
|
||||
for (const e of generate(func)) {
|
||||
unifier.unify(e.left, e.right);
|
||||
@@ -44,7 +43,7 @@ export default function (func: HIRFunction) {
|
||||
apply(func, unifier);
|
||||
}
|
||||
|
||||
function apply(func: HIRFunction, unifier: Unifier) {
|
||||
function apply(func: HIRFunction, unifier: Unifier): void {
|
||||
for (const [_, block] of func.body.blocks) {
|
||||
for (const phi of block.phis) {
|
||||
phi.type = unifier.get(phi.type);
|
||||
@@ -169,7 +168,7 @@ type Substitution = Map<TypeId, Type>;
|
||||
class Unifier {
|
||||
substitutions: Substitution = new Map();
|
||||
|
||||
unify(tA: Type, tB: Type) {
|
||||
unify(tA: Type, tB: Type): void {
|
||||
if (typeEquals(tA, tB)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,6 @@ export default class DisjointSet<T> {
|
||||
canonicalize(): Map<T, T> {
|
||||
const entries = new Map<T, T>();
|
||||
for (const item of this.#entries.keys()) {
|
||||
const parent = this.#entries.get(item)!;
|
||||
const root = this.find(item)!;
|
||||
entries.set(item, root);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user