Skip to content

Commit

Permalink
flow [nfc]: Mark specific rules that are being suppressed.
Browse files Browse the repository at this point in the history
When we start using Flow v0.137+, along with React Native v0.64
(that's issue #4426), we'll be asked to specify what rule(s) we're
suppressing with each suppression comment. Conveniently, the
warnings will tell us the applicable rule(s) we need to write down.

So, having peeked ahead at the warnings seen in the RN 0.64.0-rc.2
world, get a head start on doing so. There will probably be more of
these (we haven't yet started enforcing the requirement now, so some
unmarked `$FlowFixMe`s will naturally accumulate), but we might as
well get this chunk out of the way.
  • Loading branch information
chrisbobbe committed Jan 27, 2021
1 parent a2000b9 commit d751f40
Show file tree
Hide file tree
Showing 26 changed files with 65 additions and 44 deletions.
2 changes: 1 addition & 1 deletion src/ZulipMobile.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import LoadingScreen from './start/LoadingScreen';

initializeSentry();

// $FlowFixMe
// $FlowFixMe[prop-missing]
console.disableYellowBox = true; // eslint-disable-line

export default (): React$Node => (
Expand Down
2 changes: 1 addition & 1 deletion src/__flow-tests__/types-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import type { Action } from '../types';
// Assert that Action does not allow arbitrary objects.
{
const foo = { nonexistent_key: 'bar' };
// $FlowExpectedError
// $FlowExpectedError[incompatible-type]
const bar: Action = foo;
}
2 changes: 1 addition & 1 deletion src/api/__tests__/queueMarkAsRead-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as messagesFlags from '../messages/messagesFlags';
import * as eg from '../../__tests__/lib/exampleData';
import { Lolex } from '../../__tests__/lib/lolex';

// $FlowFixMe Make flow understand about mocking
// $FlowFixMe[cannot-write] Make flow understand about mocking
messagesFlags.default = jest.fn(() => {});

describe('queueMarkAsRead', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/api/uploadFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default (auth: Auth, uri: string, name: string): Promise<ApiResponseUploa
const formData = new FormData();
const extension = getFileExtension(name);
const type = getMimeTypeFromFileExtension(extension);
// $FlowFixMe
// $FlowFixMe[incompatible-call]
formData.append('file', { uri, name, type, extension });
return apiFile(auth, 'user_uploads', formData);
};
6 changes: 5 additions & 1 deletion src/autocomplete/PeopleAutocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ class PeopleAutocomplete extends PureComponent<Props> {

return (
<Popup>
{/* $FlowFixMe SectionList type is confused; should take $ReadOnly objects. */}
{/*
$FlowFixMe[incompatible-variance]
$FlowFixMe[prop-missing]
SectionList type is confused; should take $ReadOnly objects.
*/}
<SectionList
keyboardShouldPersistTaps="always"
initialNumToRender={10}
Expand Down
2 changes: 1 addition & 1 deletion src/boot/__tests__/reducers-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as eg from '../../__tests__/lib/exampleData';

describe('reducers', () => {
test('reducers return the default states on unknown action', () => {
// $FlowFixMe bogus action object
// $FlowFixMe[incompatible-call] bogus action object
expect(() => reducers({}, { type: 'UNKNOWN_ACTION' })).not.toThrow();
});

Expand Down
11 changes: 7 additions & 4 deletions src/boot/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ export const cacheKeys: Array<$Keys<GlobalState>> = [
function dropCache(state: GlobalState): $Shape<GlobalState> {
const result: $Shape<GlobalState> = {};
storeKeys.forEach(key => {
// $FlowFixMe This is well-typed only because it's the same `key` twice.
/* $FlowFixMe[incompatible-type]: This is well-typed only because
it's the same `key` twice. */
result[key] = state[key];
});
return result;
Expand Down Expand Up @@ -170,7 +171,7 @@ const migrations: { [string]: (GlobalState) => GlobalState } = {
accounts: state.accounts.map(a => ({
...a,
// `a.realm` is a string until migration 15
// $FlowMigrationFudge
// $FlowMigrationFudge[prop-missing]
realm: a.realm.replace(/\/+$/, ''),
})),
}),
Expand Down Expand Up @@ -207,7 +208,8 @@ const migrations: { [string]: (GlobalState) => GlobalState } = {
...state,
accounts: state.accounts.map(a => ({
...a,
// $FlowMigrationFudge - `a.realm` will be a string here
/* $FlowMigrationFudge[incompatible-call]: `a.realm` will be a
string here */
realm: new URL(a.realm),
})),
}),
Expand Down Expand Up @@ -343,7 +345,8 @@ const reduxPersistConfig: Config = {

// Store data through our own wrapper for AsyncStorage, in particular
// to get compression.
// $FlowFixMe: https://github.com/rt2zz/redux-persist/issues/823
/* $FlowFixMe[incompatible-variance]:
https://github.com/rt2zz/redux-persist/issues/823 */
storage: ZulipAsyncStorage,
serialize: stringify,
deserialize: parse,
Expand Down
7 changes: 4 additions & 3 deletions src/chat/flagsReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const addFlagsForMessages = (
return state;
}

// $FlowFixMe - #4252
// $FlowFixMe[incompatible-exact] - #4252
const newState: FlagsState = {};

flags.forEach(flag => {
Expand Down Expand Up @@ -65,7 +65,7 @@ const removeFlagForMessages = (state: FlagsState, messages: number[], flag: stri

const processFlagsForMessages = (state: FlagsState, messages: Message[]): FlagsState => {
let stateChanged = false;
// $FlowFixMe - #4252
// $FlowFixMe[incompatible-exact] - #4252
const newState: FlagsState = {};
messages.forEach(msg => {
(msg.flags || []).forEach(flag => {
Expand All @@ -79,7 +79,8 @@ const processFlagsForMessages = (state: FlagsState, messages: Message[]): FlagsS
});
});

// $FlowFixMe: Flow can't follow this objects-as-maps logic.
/* $FlowFixMe[incompatible-indexer]: Flow can't follow this
objects-as-maps logic. */
return stateChanged ? deeperMerge(state, newState) : state;
};

Expand Down
5 changes: 4 additions & 1 deletion src/compose/ComposeBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,10 @@ class ComposeBox extends PureComponent<Props, State> {

return (
<View style={this.styles.wrapper}>
{/* $FlowFixMe - `MentionWarnings` should use a type-checked `connect` */}
{/*
$FlowFixMe[incompatible-use]:
`MentionWarnings` should use a type-checked `connect`
*/}
<MentionWarnings narrow={narrow} stream={stream} ref={this.mentionWarnings} />
<View style={[this.styles.autocompleteWrapper, { marginBottom: height }]}>
<TopicAutocomplete
Expand Down
2 changes: 1 addition & 1 deletion src/compose/ComposeMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class ComposeMenu extends PureComponent<Props> {
return;
}

// $FlowFixMe sketchy falsiness check, because upstream API is unclear
// $FlowFixMe[sketchy-null-bool]: Upstream API is unclear.
const error: string | null = response.error || null;
if (error !== null) {
showErrorAlert('Error', error);
Expand Down
2 changes: 1 addition & 1 deletion src/compose/MentionWarnings.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ class MentionWarnings extends PureComponent<Props, State> {
}
}

// $FlowFixMe. TODO: Use a type checked connect call.
// $FlowFixMe[missing-annot]. TODO: Use a type checked connect call.
export default connect(
state => ({
auth: getAuth(state),
Expand Down
5 changes: 3 additions & 2 deletions src/emoji/Emoji.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import { connect } from '../react-redux';
import { getAllImageEmojiByCode } from './emojiSelectors';
import { codeToEmojiMap } from './data';

/* $FlowFixMe: `createIconSet` is mistyped upstream; elements of
`glyphMap` may be either `number` or `string`. */
/* $FlowFixMe[incompatible-call]: `createIconSet` is mistyped
upstream; elements of `glyphMap` may be either `number` or `string`.
*/
const UnicodeEmoji = createIconSet(codeToEmojiMap);

type SelectorProps = {|
Expand Down
2 changes: 1 addition & 1 deletion src/events/doEventActionSideEffects.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const messageEvent = (state: GlobalState, message: Message): void => {

const activeAccount = getActiveAccount(state);
// Assume (unchecked) that `narrow` is `Narrow` if present
// $FlowFixMe
// $FlowFixMe[cannot-resolve-name]
const narrow: Narrow | void = getChatScreenParams().narrow;
const isUserInSameNarrow =
activeAccount
Expand Down
2 changes: 1 addition & 1 deletion src/message/__tests__/messageActions-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const streamNarrowObj = streamNarrow('some stream');
describe('messageActions', () => {
describe('doNarrow', () => {
test('action to push to nav dispatched', () => {
// $FlowFixMe - Flow says `dispatch` is not writeable
// $FlowFixMe[cannot-write]
NavigationService.dispatch = jest.fn();

const store = mockStore<GlobalState, Action>(
Expand Down
2 changes: 1 addition & 1 deletion src/message/__tests__/messagesReducer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ describe('messagesReducer', () => {
submessages: [
// We know message2 has `submessages`; we defined it that
// way.
// $FlowFixMe
// $FlowFixMe[incompatible-cast]
...(message2.submessages: $ReadOnlyArray<Submessage>),
{
id: 2,
Expand Down
2 changes: 1 addition & 1 deletion src/notification/__tests__/notification-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('getNarrowFromNotificationData', () => {
const ownUserId = eg.selfUser.user_id;

test('unknown notification data returns null', () => {
// $FlowFixMe: actually validate APNs messages
// $FlowFixMe[incompatible-type]: actually validate APNs messages
const notification: Notification = {};
const narrow = getNarrowFromNotificationData(notification, new Map(), ownUserId);
expect(narrow).toBe(null);
Expand Down
3 changes: 2 additions & 1 deletion src/notification/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ export class NotificationListener {
// Otherwise, a device token should be some (platform-dependent and largely
// unspecified) flavor of string.
if (deviceToken !== null && typeof deviceToken !== 'string') {
// $FlowFixMe: deviceToken probably _is_ JSONable, but we can only hope
/* $FlowFixMe[incompatible-type]: `deviceToken` probably _is_
JSONable, but we can only hope. */
const token: JSONable = deviceToken;
logging.error('Received invalid device token', { token });
// Take no further action.
Expand Down
8 changes: 4 additions & 4 deletions src/pm-conversations/pmConversationsSelectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ function unreadCount(unreadsKey, unreadPms, unreadHuddles): number {
// of messy. Fortunately it always works, because the key spaces
// are disjoint: all `unreadHuddles` keys contain a comma, and all
// `unreadPms` keys don't.
/* $FlowFixMe: The keys of unreadPms are logically numbers... but because
it's an object, they end up converted to strings, so this access with
string keys works. We should probably use a Map for this and similar
maps. */
/* $FlowFixMe[incompatible-type]: The keys of unreadPms are
logically numbers... but because it's an object, they end up
converted to strings, so this access with string keys works.
We should probably use a Map for this and similar maps. */
return unreadPms[unreadsKey] || unreadHuddles[unreadsKey];
}

Expand Down
3 changes: 2 additions & 1 deletion src/redux-persist-migrate/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ export function createMigrationImpl(
throw new Error('createMigration: bad arguments');
}
if (action.type === REHYDRATE) {
// $FlowMigrationFudge this really is a lie -- and kind of central to migration
/* $FlowMigrationFudge[incompatible-type]: this really is a lie
-- and kind of central to migration */
const incomingState: State = action.payload;
const incomingVersion = parseInt(versionSelector(incomingState), 10);
if (Number.isNaN(incomingVersion)) {
Expand Down
3 changes: 2 additions & 1 deletion src/unread/UnreadCards.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class UnreadCards extends PureComponent<Props> {
}

return (
// $FlowFixMe SectionList libdef seems confused; should take $ReadOnly objects.
/* $FlowFixMe[prop-missing]: SectionList libdef seems confused;
should take $ReadOnly objects. */
<SectionList
stickySectionHeadersEnabled
initialNumToRender={20}
Expand Down
2 changes: 1 addition & 1 deletion src/users/UserList.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default class UserList extends PureComponent<Props> {
)}
renderSectionHeader={({ section }) =>
section.data.length === 0 ? null : (
// $FlowFixMe
// $FlowFixMe[incompatible-type]
<SectionHeader text={section.key} />
)
}
Expand Down
3 changes: 2 additions & 1 deletion src/utils/__tests__/internalLinks-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ describe('isInternalLink', () => {
],
];

// $FlowFixMe realm_ is URL | void, but complains of out-of-bounds access
/* $FlowFixMe[invalid-tuple-index]:
realm_ is URL | void, but complains of out-of-bounds access */
for (const [expected, description, url, realm_] of cases) {
test(`${expected ? 'accept' : 'reject'} ${description}: ${url}`, () => {
expect(isInternalLink(url, realm_ ?? realm)).toBe(expected);
Expand Down
11 changes: 7 additions & 4 deletions src/utils/avatar.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,9 @@ export class GravatarURL extends AvatarURL {
this._standardUrl = new URL(this._standardUrl);
}

// Make a new URL to mutate
// $FlowFixMe - https://github.com/zulip/zulip-mobile/pull/4230#discussion_r512351202
/* $FlowFixMe[incompatible-call]: Make a new URL to mutate
https://github.com/zulip/zulip-mobile/pull/4230#discussion_r512351202
*/
const result: URL = new URL(this._standardUrl);
result.searchParams.set('s', sizePhysicalPx.toString());
return result;
Expand Down Expand Up @@ -382,8 +383,10 @@ export class UploadedAvatarURL extends AvatarURL {

let result: URL = this._standardUrl;
if (sizePhysicalPx > 100) {
// Make a new URL to mutate, instead of mutating this._standardUrl
// $FlowFixMe - https://github.com/zulip/zulip-mobile/pull/4230#discussion_r512351202
/* $FlowFixMe[incompatible-call]: Make a new URL to mutate,
instead of mutating this._standardUrl
https://github.com/zulip/zulip-mobile/pull/4230#discussion_r512351202
*/
result = new URL(this._standardUrl);

const match = new RegExp(/(\w+)\.png/g).exec(result.pathname);
Expand Down
3 changes: 2 additions & 1 deletion src/webview/MessageList.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ class MessageList extends Component<Props> {

sendInboundEvents = (uevents: WebViewInboundEvent[]): void => {
if (this.webview && uevents.length > 0) {
// $FlowFixMe This `postMessage` is undocumented; tracking as #3572.
/* $FlowFixMe[prop-missing]: This `postMessage` is undocumented;
tracking as #3572. */
const secretWebView: { postMessage: (string, string) => void } = this.webview;
secretWebView.postMessage(base64Utf8Encode(JSON.stringify(uevents)), '*');
}
Expand Down
2 changes: 1 addition & 1 deletion src/webview/html/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import escape from 'lodash.escape';
* template`Hello $\!${&<world}` -> 'Hello $!&amp;&lt;world'
*/
export default (strings: string[], ...values: Array<string | number>) => {
// $FlowFixMe github.com/facebook/flow/issues/2616
// $FlowFixMe[prop-missing] github.com/facebook/flow/issues/2616
const raw: string[] = strings.raw; // eslint-disable-line prefer-destructuring
const result = [];
values.forEach((value, i) => {
Expand Down
15 changes: 8 additions & 7 deletions src/webview/js/js.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ declare var platformOS: string;
Leaves out some of the fancy features (see MDN). */
type ArrayLike<T> = { [indexer: number]: T, length: number, ... };
if (!Array.from) {
// $FlowFixMe (polyfill)
// $FlowFixMe[cannot-write] (polyfill)
Array.from = function from<T>(arr: ArrayLike<T>): Array<T> {
return Array.prototype.slice.call(arr);
};
Expand All @@ -69,7 +69,8 @@ if (!Array.from) {
* Uses Element#matches, which we have a separate polyfill for.
*/
if (!Element.prototype.closest) {
// $FlowFixMe closest is not writable... except it's absent here.
/* $FlowFixMe[cannot-write]: closest is not writable... except it's
absent here. */
Element.prototype.closest = function closest(selector) {
let element = this;
while (element && !element.matches(selector)) {
Expand All @@ -82,7 +83,7 @@ if (!Element.prototype.closest) {
/* Polyfill String#startsWith. Native in Mobile Safari 9, Chrome 49.
Taken (with minor edits) from the relevant MDN page. */
if (!String.prototype.startsWith) {
// $FlowFixMe (polyfill)
// $FlowFixMe[cannot-write] (polyfill)
String.prototype.startsWith = function startsWith(search: string, rawPos: number) {
const pos = rawPos > 0 ? rawPos | 0 : 0;
return this.substring(pos, pos + search.length) === search;
Expand All @@ -93,7 +94,7 @@ if (!String.prototype.startsWith) {
Based directly on the current ECMAScript draft:
https://tc39.es/ecma262/#sec-string.prototype.includes */
if (!String.prototype.includes) {
// $FlowFixMe (polyfill)
// $FlowFixMe[cannot-write] (polyfill)
String.prototype.includes = function includes(search: string, start: number = 0) {
/* required by the spec, but not worth the trouble */
// if (search instanceof RegExp) { throw new TypeError('...'); }
Expand Down Expand Up @@ -275,7 +276,7 @@ function walkToMessage(
): ?Element {
let element: ?Element = start;
while (element && !element.classList.contains('message')) {
// $FlowFixMe: doesn't use finite type of `step`
// $FlowFixMe[prop-missing]: doesn't use finite type of `step`
element = element[step];
}
return element;
Expand Down Expand Up @@ -346,7 +347,7 @@ function visibleMessageIds(): { first: number, last: number } {
first = Math.min(first, id);
last = Math.max(last, id);
}
// $FlowFixMe: doesn't use finite type of `step`
// $FlowFixMe[prop-missing]: doesn't use finite type of `step`
element = element[step];
}
}
Expand Down Expand Up @@ -668,7 +669,7 @@ const handleMessageEvent: MessageEventListener = e => {

inboundEvents.forEach((uevent: WebViewInboundEvent) => {
eventLogger.maybeCaptureInboundEvent(uevent);
// $FlowFixMe
// $FlowFixMe[prop-missing]
inboundEventHandlers[uevent.type](uevent);
});
scrollEventsDisabled = false;
Expand Down

0 comments on commit d751f40

Please sign in to comment.