Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(jest-docblock): support multiple of the same @pragma #5502

Merged
merged 3 commits into from
Feb 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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