Browse Source

Merge pull request #1231 from rollup/gh-1140

[WIP] [BREAKING] add this.warn method to plugin contexts
gh-1187
Rich Harris 8 years ago
committed by GitHub
parent
commit
e955ea76b1
  1. 41
      bin/src/logging.js
  2. 12
      src/Bundle.js
  3. 83
      src/utils/transform.js
  4. 0
      test/function/plugin-error-only-first-transform-bundle/_config.js
  5. 0
      test/function/plugin-error-only-first-transform-bundle/main.js
  6. 4
      test/function/plugin-error-only-first-transform/_config.js
  7. 0
      test/function/plugin-error-only-first-transform/main.js
  8. 29
      test/function/plugin-error/_config.js
  9. 1
      test/function/plugin-error/main.js
  10. 39
      test/function/plugin-warn/_config.js
  11. 1
      test/function/plugin-warn/main.js
  12. 22
      test/function/report-transform-error-file/_config.js
  13. 3
      test/function/report-transform-error-file/foo.js
  14. 3
      test/function/report-transform-error-file/main.js

41
bin/src/logging.js

@ -8,40 +8,33 @@ const errorSymbol = process.stderr.isTTY ? `🚨 ` : `Error: `;
// log to stderr to keep `rollup main.js > bundle.js` from breaking
export const stderr = console.error.bind( console ); // eslint-disable-line no-console
export function handleWarning ( warning ) {
stderr( `${warnSymbol}${chalk.bold( warning.message )}` );
function log ( object, symbol ) {
const message = object.plugin ? `(${object.plugin} plugin) ${object.message}` : object.message;
stderr( `${symbol}${chalk.bold( message )}` );
if ( warning.url ) {
stderr( chalk.cyan( warning.url ) );
if ( object.url ) {
stderr( chalk.cyan( object.url ) );
}
if ( warning.loc ) {
stderr( `${relativeId( warning.loc.file )} (${warning.loc.line}:${warning.loc.column})` );
if ( object.loc ) {
stderr( `${relativeId( object.loc.file )} (${object.loc.line}:${object.loc.column})` );
} else if ( object.id ) {
stderr( relativeId( object.id ) );
}
if ( warning.frame ) {
stderr( chalk.dim( warning.frame ) );
if ( object.frame ) {
stderr( chalk.dim( object.frame ) );
}
stderr( '' );
}
export function handleError ( err, recover ) {
stderr( `${errorSymbol}${chalk.bold( err.message )}` );
if ( err.url ) {
stderr( chalk.cyan( err.url ) );
}
if ( err.loc ) {
stderr( `${relativeId( err.loc.file )} (${err.loc.line}:${err.loc.column})` );
}
if ( err.frame ) {
stderr( chalk.dim( err.frame ) );
}
stderr( '' );
export function handleWarning ( warning ) {
log( warning, warnSymbol );
}
export function handleError ( err, recover ) {
log( err, errorSymbol );
if ( !recover ) process.exit( 1 );
}

12
src/Bundle.js

@ -293,7 +293,7 @@ export default class Bundle {
return this.cachedModules.get( id );
}
return transform( source, id, this.plugins );
return transform( this, source, id, this.plugins );
})
.then( source => {
const { code, originalCode, originalSourceMap, ast, sourceMapChain, resolvedIds } = source;
@ -619,11 +619,13 @@ export default class Bundle {
warn ( warning ) {
warning.toString = () => {
if ( warning.loc ) {
return `${relativeId( warning.loc.file )} (${warning.loc.line}:${warning.loc.column}) ${warning.message}`;
}
let str = '';
if ( warning.plugin ) str += `(${warning.plugin} plugin) `;
if ( warning.loc ) str += `${relativeId( warning.loc.file )} (${warning.loc.line}:${warning.loc.column}) `;
str += warning.message;
return warning.message;
return str;
};
this.onwarn( warning );

83
src/utils/transform.js

@ -1,8 +1,9 @@
import { decode } from 'sourcemap-codec';
import { locate } from 'locate-character';
import error from './error.js';
import relativeId from './relativeId.js';
import getCodeFrame from './getCodeFrame.js';
export default function transform ( source, id, plugins ) {
export default function transform ( bundle, source, id, plugins ) {
const sourceMapChain = [];
const originalSourceMap = typeof source.map === 'string' ? JSON.parse( source.map ) : source.map;
@ -13,13 +14,57 @@ export default function transform ( source, id, plugins ) {
const originalCode = source.code;
let ast = source.ast;
let errored = false;
return plugins.reduce( ( promise, plugin ) => {
return promise.then( previous => {
if ( !plugin.transform ) return previous;
let promise = Promise.resolve( source.code );
plugins.forEach( plugin => {
if ( !plugin.transform ) return;
promise = promise.then( previous => {
function augment ( object, pos, code ) {
if ( typeof object === 'string' ) {
object = { message: object };
}
if ( !object.code ) object.code = code;
if ( pos !== undefined ) {
object.pos = pos;
const { line, column } = locate( previous, pos, { offsetLine: 1 });
object.loc = { file: id, line, column };
object.frame = getCodeFrame( previous, line, column );
}
return object;
}
let err;
const context = {
warn: ( warning, pos ) => {
warning = augment( warning, pos, 'PLUGIN_WARNING' );
warning.plugin = plugin.name;
warning.id = id;
bundle.warn( warning );
},
error ( e, pos ) {
err = augment( e, pos, 'PLUGIN_ERROR' );
}
};
let transformed;
try {
transformed = plugin.transform.call( context, previous, id );
} catch ( err ) {
context.error( err );
}
return Promise.resolve( transformed )
.then( result => {
if ( err ) throw err;
return Promise.resolve( plugin.transform( previous, id ) ).then( result => {
if ( result == null ) return previous;
if ( typeof result === 'string' ) {
@ -29,6 +74,7 @@ export default function transform ( source, id, plugins ) {
map: null
};
}
// `result.map` can only be a string if `result` isn't
else if ( typeof result.map === 'string' ) {
result.map = JSON.parse( result.map );
@ -42,23 +88,14 @@ export default function transform ( source, id, plugins ) {
ast = result.ast;
return result.code;
});
}).catch( err => {
// TODO this all seems a bit hacky
if ( errored ) throw err;
errored = true;
})
.catch( err => {
err.plugin = plugin.name;
throw err;
err.id = id;
error( err );
});
}, Promise.resolve( source.code ) )
.catch( err => {
error({
code: 'BAD_TRANSFORMER',
message: `Error transforming ${relativeId( id )}${err.plugin ? ` with '${err.plugin}' plugin` : ''}: ${err.message}`,
plugin: err.plugin,
id
});
})
.then( code => ({ code, originalCode, originalSourceMap, ast, sourceMapChain }) );
});
return promise.then( code => ({ code, originalCode, originalSourceMap, ast, sourceMapChain }) );
}

0
test/function/throws-only-first-transform-bundle/_config.js → test/function/plugin-error-only-first-transform-bundle/_config.js

0
test/function/throws-only-first-transform-bundle/main.js → test/function/plugin-error-only-first-transform-bundle/main.js

4
test/function/throws-only-first-transform/_config.js → test/function/plugin-error-only-first-transform/_config.js

@ -20,8 +20,8 @@ module.exports = {
]
},
error: {
code: 'BAD_TRANSFORMER',
message: `Error transforming main.js with 'plugin1' plugin: Something happened 1`,
code: 'PLUGIN_ERROR',
message: `Something happened 1`,
plugin: 'plugin1',
id: path.resolve( __dirname, 'main.js' )
}

0
test/function/throws-only-first-transform/main.js → test/function/plugin-error-only-first-transform/main.js

29
test/function/plugin-error/_config.js

@ -0,0 +1,29 @@
const path = require( 'path' );
module.exports = {
description: 'plugin transform hooks can use `this.error({...}, char)` (#1140)',
options: {
plugins: [{
name: 'test',
transform ( code, id ) {
this.error( 'nope', 22 );
}
}]
},
error: {
code: 'PLUGIN_ERROR',
plugin: 'test',
message: 'nope',
id: path.resolve( __dirname, 'main.js' ),
pos: 22,
loc: {
file: path.resolve( __dirname, 'main.js' ),
line: 1,
column: 22
},
frame: `
1: assert.equal( 21 * 2, TK );
^
`
}
};

1
test/function/plugin-error/main.js

@ -0,0 +1 @@
assert.equal( 21 * 2, TK );

39
test/function/plugin-warn/_config.js

@ -0,0 +1,39 @@
const path = require( 'path' );
module.exports = {
description: 'plugin transform hooks can use `this.warn({...}, char)` (#1140)',
options: {
plugins: [{
name: 'test',
transform ( code, id ) {
this.warn({ message: 'foo' });
this.warn( 'bar', 22 );
return 'assert.equal( 21 * 2, 42 );';
}
}]
},
warnings: [
{
code: 'PLUGIN_WARNING',
id: path.resolve( __dirname, 'main.js' ),
plugin: 'test',
message: 'foo'
},
{
code: 'PLUGIN_WARNING',
id: path.resolve( __dirname, 'main.js' ),
plugin: 'test',
message: 'bar',
pos: 22,
loc: {
file: path.resolve( __dirname, 'main.js' ),
line: 1,
column: 22
},
frame: `
1: assert.equal( 21 * 2, TK );
^
`
}
]
};

1
test/function/plugin-warn/main.js

@ -0,0 +1 @@
assert.equal( 21 * 2, TK );

22
test/function/report-transform-error-file/_config.js

@ -1,22 +0,0 @@
var path = require( 'path' );
var assert = require( 'assert' );
module.exports = {
description: 'reports which file caused a transform error',
options: {
plugins: [{
name: 'bad-plugin',
transform: function ( code, id ) {
if ( /foo/.test( id ) ) {
throw new Error( 'nope' );
}
}
}]
},
error: {
code: 'BAD_TRANSFORMER',
message: `Error transforming foo.js with 'bad-plugin' plugin: nope`,
plugin: 'bad-plugin',
id: path.resolve( __dirname, 'foo.js' )
}
};

3
test/function/report-transform-error-file/foo.js

@ -1,3 +0,0 @@
export default function () {
console.log( 'foo' );
}

3
test/function/report-transform-error-file/main.js

@ -1,3 +0,0 @@
import foo from './foo.js';
foo();
Loading…
Cancel
Save