diff --git a/src/Bundle.js b/src/Bundle.js index 0cfe895..26e6229 100644 --- a/src/Bundle.js +++ b/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; diff --git a/src/utils/transform.js b/src/utils/transform.js index 7e90a74..0dd813c 100644 --- a/src/utils/transform.js +++ b/src/utils/transform.js @@ -1,8 +1,10 @@ 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; @@ -19,7 +21,27 @@ export default function transform ( source, id, plugins ) { return promise.then( previous => { if ( !plugin.transform ) return previous; - return Promise.resolve( plugin.transform( previous, id ) ).then( result => { + const context = { + warn: ( warning, pos ) => { + if ( typeof warning === 'string' ) { + warning = { message: warning }; + } + + warning.plugin = plugin.name; + if ( !warning.code ) warning.code = 'PLUGIN_WARNING'; + + if ( pos !== undefined ) { + warning.pos = pos; + const { line, column } = locate( previous, pos, { offsetLine: 1 }); + warning.loc = { file: id, line, column }; + warning.frame = getCodeFrame( previous, line, column ); + } + + bundle.warn( warning ); + } + }; + + return Promise.resolve( plugin.transform.call( context, previous, id ) ).then( result => { if ( result == null ) return previous; if ( typeof result === 'string' ) { @@ -29,6 +51,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 ); diff --git a/test/function/plugin-warn/_config.js b/test/function/plugin-warn/_config.js new file mode 100644 index 0000000..1fd2f8c --- /dev/null +++ b/test/function/plugin-warn/_config.js @@ -0,0 +1,37 @@ +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', + plugin: 'test', + message: 'foo' + }, + { + code: 'PLUGIN_WARNING', + plugin: 'test', + message: 'bar', + pos: 22, + loc: { + file: path.resolve( __dirname, 'main.js' ), + line: 1, + column: 22 + }, + frame: ` + 1: assert.equal( 21 * 2, TK ); + ^ + ` + } + ] +}; diff --git a/test/function/plugin-warn/main.js b/test/function/plugin-warn/main.js new file mode 100644 index 0000000..04164ee --- /dev/null +++ b/test/function/plugin-warn/main.js @@ -0,0 +1 @@ +assert.equal( 21 * 2, TK );