From 40bc464e9fdaf796e27eb9b435b56b38703f6ff6 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 20 May 2015 12:48:51 -0400 Subject: [PATCH] throw error on duplicated import --- src/Module.js | 8 ++++++++ src/utils/getLocation.js | 20 +++++++++++++++++++ src/utils/replaceIdentifiers.js | 2 +- .../_config.js | 5 ++++- .../duplicate-import-specifier-fails/main.js | 2 +- 5 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 src/utils/getLocation.js diff --git a/src/Module.js b/src/Module.js index 94d33ca..b561a97 100644 --- a/src/Module.js +++ b/src/Module.js @@ -5,6 +5,7 @@ import MagicString from 'magic-string'; import analyse from './ast/analyse'; import { has } from './utils/object'; import { sequence } from './utils/promise'; +import getLocation from './utils/getLocation'; const emptyArrayPromise = Promise.resolve([]); @@ -76,6 +77,13 @@ export default class Module { const localName = specifier.local.name; const name = isDefault ? 'default' : isNamespace ? '*' : specifier.imported.name; + if ( has( this.imports, localName ) ) { + const err = new Error( `Duplicated import '${localName}'` ); + err.file = this.path; + err.loc = getLocation( this.code.original, specifier.start ); + throw err; + } + this.imports[ localName ] = { source, name, diff --git a/src/utils/getLocation.js b/src/utils/getLocation.js new file mode 100644 index 0000000..41ca492 --- /dev/null +++ b/src/utils/getLocation.js @@ -0,0 +1,20 @@ +export default function getLocation ( source, charIndex ) { + const lines = source.split( '\n' ); + const len = lines.length; + + let lineStart = 0; + let i; + + for ( i = 0; i < len; i += 1 ) { + const line = lines[i]; + const lineEnd = lineStart + line.length + 1; // +1 for newline + + if ( lineEnd > charIndex ) { + return { line: i + 1, column: charIndex - lineStart }; + } + + lineStart = lineEnd; + } + + throw new Error( 'Could not determine location of character' ); +} diff --git a/src/utils/replaceIdentifiers.js b/src/utils/replaceIdentifiers.js index 47b5ab5..da6f7db 100644 --- a/src/utils/replaceIdentifiers.js +++ b/src/utils/replaceIdentifiers.js @@ -53,4 +53,4 @@ export default function replaceIdentifiers ( statement, snippet, names ) { } } }); -} \ No newline at end of file +} diff --git a/test/samples/duplicate-import-specifier-fails/_config.js b/test/samples/duplicate-import-specifier-fails/_config.js index bc37a42..b935a69 100644 --- a/test/samples/duplicate-import-specifier-fails/_config.js +++ b/test/samples/duplicate-import-specifier-fails/_config.js @@ -1,9 +1,12 @@ +var path = require( 'path' ); var assert = require( 'assert' ); module.exports = { description: 'disallows duplicate import specifiers', error: function ( err ) { - assert.ok( false ); // TK - pick an error message + assert.equal( err.file, path.resolve( __dirname, 'main.js' ) ); + assert.deepEqual( err.loc, { line: 1, column: 12 }); + assert.ok( /Duplicated import/.test( err.message ) ); } }; diff --git a/test/samples/duplicate-import-specifier-fails/main.js b/test/samples/duplicate-import-specifier-fails/main.js index 0cde574..3e9f69d 100644 --- a/test/samples/duplicate-import-specifier-fails/main.js +++ b/test/samples/duplicate-import-specifier-fails/main.js @@ -1,2 +1,2 @@ -import { a, a } from './exporter'; +import { a, a } from './foo'; assert.equal(a, 1);