From e1a06544bccda0e899965ae5db67decc4ea4d76e Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 27 Apr 2017 07:23:13 -0700 Subject: [PATCH] Type-check utils (#491) * Type-check utils * Improve test coverage --- src/tokenizer/index.js | 1 + src/util/identifier.js | 17 ++++++++++------- src/util/location.js | 18 +++++++++++++++++- src/util/whitespace.js | 2 ++ 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/tokenizer/index.js b/src/tokenizer/index.js index fde3448c0d..34f75fa490 100644 --- a/src/tokenizer/index.js +++ b/src/tokenizer/index.js @@ -809,6 +809,7 @@ export default class Tokenizer extends LocationParser { ++this.state.pos; const esc = this.readCodePoint(true); + // $FlowFixMe (thinks esc may be null, but throwOnInvalid is true) if (!(first ? isIdentifierStart : isIdentifierChar)(esc, true)) { this.raise(escStart, "Invalid Unicode escape"); } diff --git a/src/util/identifier.js b/src/util/identifier.js index d8a9c83c49..3fc6ab2cde 100644 --- a/src/util/identifier.js +++ b/src/util/identifier.js @@ -1,5 +1,7 @@ /* eslint max-len: 0 */ +// @flow + // This is a trick taken from Esprima. It turns out that, on // non-Chrome browsers, to check whether a string is in a set, a // predicate containing a big ugly `switch` statement is faster than @@ -9,17 +11,17 @@ // // It starts by sorting the words by length. -function makePredicate(words) { - words = words.split(" "); +function makePredicate(words: string): (str: string) => boolean { + const wordsArr = words.split(" "); return function (str) { - return words.indexOf(str) >= 0; + return wordsArr.indexOf(str) >= 0; }; } // Reserved word lists for various dialects of the language export const reservedWords = { - 6: makePredicate("enum await"), + "6": makePredicate("enum await"), strict: makePredicate("implements interface let package private protected public static yield"), strictBind: makePredicate("eval arguments") }; @@ -57,7 +59,7 @@ const astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,1 // This has a complexity linear to the value of the code. The // assumption is that looking up astral identifier characters is // rare. -function isInAstralSet(code, set) { +function isInAstralSet(code: number, set: $ReadOnlyArray): boolean { let pos = 0x10000; for (let i = 0; i < set.length; i += 2) { pos += set[i]; @@ -66,11 +68,12 @@ function isInAstralSet(code, set) { pos += set[i + 1]; if (pos >= code) return true; } + return false; } // Test whether a given character code starts an identifier. -export function isIdentifierStart(code) { +export function isIdentifierStart(code: number): boolean { if (code < 65) return code === 36; if (code < 91) return true; if (code < 97) return code === 95; @@ -81,7 +84,7 @@ export function isIdentifierStart(code) { // Test whether a given character is part of an identifier. -export function isIdentifierChar(code) { +export function isIdentifierChar(code: number): boolean { if (code < 48) return code === 36; if (code < 58) return true; if (code < 65) return false; diff --git a/src/util/location.js b/src/util/location.js index fb53aab1c5..aaa4ae531c 100644 --- a/src/util/location.js +++ b/src/util/location.js @@ -1,9 +1,18 @@ +// @flow + import { lineBreakG } from "./whitespace"; +export type Pos = { + start: number; +} + // These are used when `options.locations` is on, for the // `startLoc` and `endLoc` properties. export class Position { + line: number; + column: number; + constructor(line: number, col: number) { this.line = line; this.column = col; @@ -11,8 +20,13 @@ export class Position { } export class SourceLocation { + start: Position; + end: Position; + filename: string; + constructor(start: Position, end?: Position) { this.start = start; + // $FlowIgnore (may start as null, but initialized later) this.end = end; } } @@ -23,7 +37,7 @@ export class SourceLocation { // offset. `input` should be the code string that the offset refers // into. -export function getLineInfo(input, offset) { +export function getLineInfo(input: string, offset: number): Position { for (let line = 1, cur = 0; ;) { lineBreakG.lastIndex = cur; const match = lineBreakG.exec(input); @@ -34,4 +48,6 @@ export function getLineInfo(input, offset) { return new Position(line, offset - cur); } } + // istanbul ignore next + throw new Error("Unreachable"); } diff --git a/src/util/whitespace.js b/src/util/whitespace.js index e345a4cf5e..0588213ecd 100644 --- a/src/util/whitespace.js +++ b/src/util/whitespace.js @@ -1,3 +1,5 @@ +// @flow + // Matches a whole line break (where CRLF is considered a single // line break). Used to count lines.