diff --git a/src/ZulipMobile.js b/src/ZulipMobile.js index 61d288a81c5..dd9a156a20c 100644 --- a/src/ZulipMobile.js +++ b/src/ZulipMobile.js @@ -18,7 +18,7 @@ import LoadingScreen from './start/LoadingScreen'; initializeSentry(); -// $FlowFixMe +// $FlowFixMe[prop-missing] console.disableYellowBox = true; // eslint-disable-line export default (): React$Node => ( diff --git a/src/__flow-tests__/types-test.js b/src/__flow-tests__/types-test.js index 8f3c6b03bc5..e608ddc61b3 100644 --- a/src/__flow-tests__/types-test.js +++ b/src/__flow-tests__/types-test.js @@ -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; } diff --git a/src/api/__tests__/queueMarkAsRead-test.js b/src/api/__tests__/queueMarkAsRead-test.js index 1936c5ef433..3d17a015226 100644 --- a/src/api/__tests__/queueMarkAsRead-test.js +++ b/src/api/__tests__/queueMarkAsRead-test.js @@ -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', () => { diff --git a/src/api/uploadFile.js b/src/api/uploadFile.js index 3e3381349ed..4be28443e33 100644 --- a/src/api/uploadFile.js +++ b/src/api/uploadFile.js @@ -12,7 +12,7 @@ export default (auth: Auth, uri: string, name: string): Promise { return ( - {/* $FlowFixMe SectionList type is confused; should take $ReadOnly objects. */} + {/* + $FlowFixMe[incompatible-variance] + $FlowFixMe[prop-missing] + SectionList type is confused; should take $ReadOnly objects. + */} { 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(); }); diff --git a/src/boot/store.js b/src/boot/store.js index 1731b379350..005c2aabb93 100644 --- a/src/boot/store.js +++ b/src/boot/store.js @@ -92,7 +92,8 @@ export const cacheKeys: Array<$Keys> = [ function dropCache(state: GlobalState): $Shape { const result: $Shape = {}; 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; @@ -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(/\/+$/, ''), })), }), @@ -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), })), }), @@ -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, diff --git a/src/chat/flagsReducer.js b/src/chat/flagsReducer.js index a824a488de8..b401e8d9a2d 100644 --- a/src/chat/flagsReducer.js +++ b/src/chat/flagsReducer.js @@ -35,7 +35,7 @@ const addFlagsForMessages = ( return state; } - // $FlowFixMe - #4252 + // $FlowFixMe[incompatible-exact] - #4252 const newState: FlagsState = {}; flags.forEach(flag => { @@ -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 => { @@ -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; }; diff --git a/src/compose/ComposeBox.js b/src/compose/ComposeBox.js index 9c857369b3b..97e78b01991 100644 --- a/src/compose/ComposeBox.js +++ b/src/compose/ComposeBox.js @@ -449,7 +449,10 @@ class ComposeBox extends PureComponent { return ( - {/* $FlowFixMe - `MentionWarnings` should use a type-checked `connect` */} + {/* + $FlowFixMe[incompatible-use]: + `MentionWarnings` should use a type-checked `connect` + */} { 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); diff --git a/src/compose/MentionWarnings.js b/src/compose/MentionWarnings.js index 0c7c6cd2ba0..3931a44a5e9 100644 --- a/src/compose/MentionWarnings.js +++ b/src/compose/MentionWarnings.js @@ -173,7 +173,7 @@ class MentionWarnings extends PureComponent { } } -// $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), diff --git a/src/emoji/Emoji.js b/src/emoji/Emoji.js index d5a68d746e9..6ac79009c1b 100644 --- a/src/emoji/Emoji.js +++ b/src/emoji/Emoji.js @@ -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 = {| diff --git a/src/events/doEventActionSideEffects.js b/src/events/doEventActionSideEffects.js index 432b4df1b41..01a687a8f99 100644 --- a/src/events/doEventActionSideEffects.js +++ b/src/events/doEventActionSideEffects.js @@ -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 diff --git a/src/message/__tests__/messageActions-test.js b/src/message/__tests__/messageActions-test.js index 322b5488eba..681afaddd27 100644 --- a/src/message/__tests__/messageActions-test.js +++ b/src/message/__tests__/messageActions-test.js @@ -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( diff --git a/src/message/__tests__/messagesReducer-test.js b/src/message/__tests__/messagesReducer-test.js index dcc222a616e..88cc0b2312e 100644 --- a/src/message/__tests__/messagesReducer-test.js +++ b/src/message/__tests__/messagesReducer-test.js @@ -113,7 +113,7 @@ describe('messagesReducer', () => { submessages: [ // We know message2 has `submessages`; we defined it that // way. - // $FlowFixMe + // $FlowFixMe[incompatible-cast] ...(message2.submessages: $ReadOnlyArray), { id: 2, diff --git a/src/notification/__tests__/notification-test.js b/src/notification/__tests__/notification-test.js index 7bb82d1968f..21382edb441 100644 --- a/src/notification/__tests__/notification-test.js +++ b/src/notification/__tests__/notification-test.js @@ -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); diff --git a/src/notification/index.js b/src/notification/index.js index 952ad8875d4..4c3b97bb335 100644 --- a/src/notification/index.js +++ b/src/notification/index.js @@ -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. diff --git a/src/pm-conversations/pmConversationsSelectors.js b/src/pm-conversations/pmConversationsSelectors.js index 837bb8ec322..d2c10c65021 100644 --- a/src/pm-conversations/pmConversationsSelectors.js +++ b/src/pm-conversations/pmConversationsSelectors.js @@ -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]; } diff --git a/src/redux-persist-migrate/index.js b/src/redux-persist-migrate/index.js index ca3ec13865a..0bf56744fbe 100644 --- a/src/redux-persist-migrate/index.js +++ b/src/redux-persist-migrate/index.js @@ -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)) { diff --git a/src/unread/UnreadCards.js b/src/unread/UnreadCards.js index 05397c142a6..033ee91ec54 100644 --- a/src/unread/UnreadCards.js +++ b/src/unread/UnreadCards.js @@ -46,7 +46,8 @@ class UnreadCards extends PureComponent { } return ( - // $FlowFixMe SectionList libdef seems confused; should take $ReadOnly objects. + /* $FlowFixMe[prop-missing]: SectionList libdef seems confused; + should take $ReadOnly objects. */ { )} renderSectionHeader={({ section }) => section.data.length === 0 ? null : ( - // $FlowFixMe + // $FlowFixMe[incompatible-type] ) } diff --git a/src/utils/__tests__/internalLinks-test.js b/src/utils/__tests__/internalLinks-test.js index 93af8619e11..4b6ed529ecd 100644 --- a/src/utils/__tests__/internalLinks-test.js +++ b/src/utils/__tests__/internalLinks-test.js @@ -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); diff --git a/src/utils/avatar.js b/src/utils/avatar.js index 94a8c9eab3c..f19ecdb22a6 100644 --- a/src/utils/avatar.js +++ b/src/utils/avatar.js @@ -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; @@ -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); diff --git a/src/webview/MessageList.js b/src/webview/MessageList.js index b5155323625..e82ab291f32 100644 --- a/src/webview/MessageList.js +++ b/src/webview/MessageList.js @@ -195,7 +195,8 @@ class MessageList extends Component { 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)), '*'); } diff --git a/src/webview/html/template.js b/src/webview/html/template.js index 9a3b71df70d..b2975eb227b 100644 --- a/src/webview/html/template.js +++ b/src/webview/html/template.js @@ -14,7 +14,7 @@ import escape from 'lodash.escape'; * template`Hello $\!${& 'Hello $!&<world' */ export default (strings: string[], ...values: Array) => { - // $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) => { diff --git a/src/webview/js/js.js b/src/webview/js/js.js index 5c9a0b9f8ac..ca474b33aca 100644 --- a/src/webview/js/js.js +++ b/src/webview/js/js.js @@ -55,7 +55,7 @@ declare var platformOS: string; Leaves out some of the fancy features (see MDN). */ type ArrayLike = { [indexer: number]: T, length: number, ... }; if (!Array.from) { - // $FlowFixMe (polyfill) + // $FlowFixMe[cannot-write] (polyfill) Array.from = function from(arr: ArrayLike): Array { return Array.prototype.slice.call(arr); }; @@ -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)) { @@ -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; @@ -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('...'); } @@ -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; @@ -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]; } } @@ -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;