Skip to content

Commit

Permalink
feat(jest-docblock): support multiple of the same @pragma (#5502)
Browse files Browse the repository at this point in the history
* feat(jest-docblock): support multiple of the same @pragma

* chore: fix types

* fix(jest-haste-map): update to allow multiple pragmas
  • Loading branch information
azz authored and cpojer committed Feb 9, 2018
1 parent 97f0308 commit f2ef92d
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 16 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

* `[babel-jest]` Revert "Remove retainLines from babel-jest"
([#5496](https://github.com/facebook/jest/pull/5496))
* `[jest-docblock]` Support multiple of the same `@pragma`.
([#5154](https://github.com/facebook/jest/pull/5502))

### Features

Expand Down
6 changes: 3 additions & 3 deletions packages/jest-docblock/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,17 @@ string (`""`).
Strips the top docblock from a file and return the result. If a file does not
have a docblock at the top, then return the file unchanged.

### `parse(docblock: string): {[key: string]: string}`
### `parse(docblock: string): {[key: string]: string | string[] }`

Parses the pragmas in a docblock string into an object whose keys are the pragma
tags and whose values are the arguments to those pragmas.

### `parseWithComments(docblock: string): { comments: string, pragmas: {[key: string]: string} }`
### `parseWithComments(docblock: string): { comments: string, pragmas: {[key: string]: string | string[]} }`

Similar to `parse` except this method also returns the comments from the
docblock. Useful when used with `print()`.

### `print({ comments?: string, pragmas?: {[key: string]: string} }): string`
### `print({ comments?: string, pragmas?: {[key: string]: string | string[]} }): string`

Prints an object of key-value pairs back into a docblock. If `comments` are
provided, they will be positioned on the top of the docblock.
58 changes: 58 additions & 0 deletions packages/jest-docblock/src/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,47 @@ describe('docblock', () => {
});
});

it('parses multiple of the same directives out of a docblock', () => {
const code =
'/**' +
os.EOL +
'' +
' * @x foo' +
os.EOL +
'' +
' * @x bar' +
os.EOL +
'' +
' * @y' +
os.EOL +
'' +
' */';
expect(docblock.parse(code)).toEqual({
x: ['foo', 'bar'],
y: '',
});
});

it('parses >=3 of the same directives out of a docblock', () => {
const code =
'/**' +
os.EOL +
'' +
' * @x foo' +
os.EOL +
'' +
' * @x bar' +
os.EOL +
'' +
' * @x baz' +
os.EOL +
'' +
' */';
expect(docblock.parse(code)).toEqual({
x: ['foo', 'bar', 'baz'],
});
});

it('parses directives out of a docblock with comments', () => {
const code =
'/**' +
Expand Down Expand Up @@ -395,6 +436,23 @@ describe('docblock', () => {
);
});

it('prints docblocks with multiple of the same pragma', () => {
const pragmas = {
x: ['a', 'b'],
y: 'c',
};
expect(docblock.print({pragmas})).toEqual(
'/**' +
os.EOL +
' * @x a' +
os.EOL +
' * @x b' +
os.EOL +
' * @y c' +
os.EOL +
' */',
);
});
it('prints docblocks with pragmas', () => {
const pragmas = {
flow: 'foo',
Expand Down
33 changes: 22 additions & 11 deletions packages/jest-docblock/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import detectNewline from 'detect-newline';
import {EOL} from 'os';

type Pragmas = {[key: string]: string | string[], __proto__: null};

const commentEndRe = /\*\/$/;
const commentStartRe = /^\/\*\*/;
const docblockRe = /^\s*(\/\*\*?(.|\r?\n)*?\*\/)/;
Expand All @@ -31,15 +33,13 @@ export function strip(contents: string) {
return match && match[0] ? contents.substring(match[0].length) : contents;
}

export function parse(
docblock: string,
): {[key: string]: string, __proto__: null} {
export function parse(docblock: string): Pragmas {
return parseWithComments(docblock).pragmas;
}

export function parseWithComments(
docblock: string,
): {comments: string, pragmas: {[key: string]: string, __proto__: null}} {
): {comments: string, pragmas: Pragmas} {
const line = detectNewline(docblock) || EOL;

docblock = docblock
Expand All @@ -64,7 +64,15 @@ export function parseWithComments(
let match;
while ((match = propertyRe.exec(docblock))) {
// strip linecomments from pragmas
result[match[1]] = match[2].replace(lineCommentRe, '');
const nextPragma = match[2].replace(lineCommentRe, '');
if (
typeof result[match[1]] === 'string' ||
Array.isArray(result[match[1]])
) {
result[match[1]] = [].concat(result[match[1]], nextPragma);
} else {
result[match[1]] = nextPragma;
}
}
return {comments, pragmas: result};
}
Expand All @@ -74,7 +82,7 @@ export function print({
pragmas = {},
}: {
comments?: string,
pragmas?: {[key: string]: string, __proto__: null},
pragmas?: Pragmas,
__proto__: null,
}): string {
const line = detectNewline(comments) || EOL;
Expand All @@ -85,15 +93,18 @@ export function print({
const keys = Object.keys(pragmas);

const printedObject = keys
.map(key => start + ' ' + printKeyValue(key, pragmas[key]) + line)
.map(key => printKeyValues(key, pragmas[key]))
.reduce((arr, next) => arr.concat(next), [])
.map(keyValue => start + ' ' + keyValue + line)
.join('');

if (!comments) {
if (keys.length === 0) {
return '';
}
if (keys.length === 1) {
return `${head} ${printKeyValue(keys[0], pragmas[keys[0]])}${tail}`;
if (keys.length === 1 && !Array.isArray(pragmas[keys[0]])) {
const value = pragmas[keys[0]];
return `${head} ${printKeyValues(keys[0], value)[0]}${tail}`;
}
}

Expand All @@ -113,6 +124,6 @@ export function print({
);
}

function printKeyValue(key, value) {
return `@${key} ${value}`.trim();
function printKeyValues(key, valueOrArray) {
return [].concat(valueOrArray).map(value => `@${key} ${value}`.trim());
}
5 changes: 3 additions & 2 deletions packages/jest-haste-map/src/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export async function worker(data: WorkerMessage): Promise<WorkerMetadata> {
const filePath = data.filePath;
const content = fs.readFileSync(filePath, 'utf8');
let module;
let id;
let id: ?string;
let dependencies;

if (filePath.endsWith(PACKAGE_JSON)) {
Expand All @@ -51,7 +51,8 @@ export async function worker(data: WorkerMessage): Promise<WorkerMetadata> {
id = hasteImpl.getHasteName(filePath);
} else {
const doc = docblock.parse(docblock.extract(content));
id = doc.providesModule || doc.provides;
const idPragmas = [].concat(doc.providesModule || doc.provides);
id = idPragmas[0];
}
dependencies = extractRequires(content);
if (id) {
Expand Down

0 comments on commit f2ef92d

Please sign in to comment.