From d2e2d488bf2dea68bbf7e90a2491d857dfe62fb7 Mon Sep 17 00:00:00 2001 From: Ben Shaw Date: Sat, 31 Aug 2019 14:56:03 +1200 Subject: [PATCH] feat(JS): Added checking for empty string semaphore in imports --- py/tests/test_document_compiler.py | 2 +- ts/interpreter.ts | 23 ++++++++++++++++++++++- ts/parsing.test.ts | 30 ++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/py/tests/test_document_compiler.py b/py/tests/test_document_compiler.py index 78eced7d9c..d245507165 100644 --- a/py/tests/test_document_compiler.py +++ b/py/tests/test_document_compiler.py @@ -111,7 +111,7 @@ def test_compile_article(): def test_import_appending(): """Found imports in a piece of code should be added to the list of imports the code chunk already specifies.""" - c = CodeChunk('import moda\nimport modb', imports=['modc', 'modd'], language='python') + c = CodeChunk('import moda\nimport modb\nimport modc', imports=['modc', 'modd'], language='python') dc = DocumentCompiler() dc.compile(c) diff --git a/ts/interpreter.ts b/ts/interpreter.ts index c9cb30e6be..2850f098bb 100644 --- a/ts/interpreter.ts +++ b/ts/interpreter.ts @@ -123,6 +123,27 @@ export function execute( }) } +/** + * Add `imports` to the `CodeChunk.imports` array if they aren't already there. If the existing imports array contains + * the empty string semaphore then no more imports should be added. + */ +function setCodeChunkImports(code: CodeChunk, imports: string[]): void { + if (code.imports === undefined) { + code.imports = imports + return + } + + if (code.imports.includes('')) return + + // Can't do any kind of de-dupe magic as code.imports might contain types other than strings. + imports.forEach(im => { + // Typescript seems to forget that this has already been checked to not be undefined + if (code.imports === undefined) return + + if (!code.imports.includes(im)) code.imports.push(im) + }) +} + /** * Traverse a `Node` hierarchy and push any `Parameter` that is found onto the `parameters` array, * and any executable code block onto the `code` array. @@ -146,7 +167,7 @@ export function parseItem( if (isA('CodeChunk', item)) { const parseResult = parseCodeChunk(item) - item.imports = parseResult.imports + setCodeChunkImports(item, parseResult.imports) item.declares = parseResult.declares item.assigns = parseResult.assigns item.alters = parseResult.alters diff --git a/ts/parsing.test.ts b/ts/parsing.test.ts index e643c25e64..9e042a67b2 100644 --- a/ts/parsing.test.ts +++ b/ts/parsing.test.ts @@ -348,6 +348,36 @@ describe('Parsing information from an Article', () => { 'IntegerSchema' ) }) + + test('it adds imports it finds to existing CodeChunk imports', () => { + const c = codeChunk( + "import { export1 } from 'module-name3'\nimport { export2 } from 'module-name4'", + { + language: 'javascript', + imports: ['module-name1', 'module-name2', 'module-name3'] + } + ) + parseItem(c, [], []) + + expect(c.imports).toHaveLength(4) + expect(c.imports).toContain('module-name1') + expect(c.imports).toContain('module-name2') + expect(c.imports).toContain('module-name3') + expect(c.imports).toContain('module-name4') + }) + + test("it doesn't add imports it finds to existing CodeChunk imports if the empty string semaphore is present", () => { + const c = codeChunk( + "import { export1 } from 'module-name3'\nimport { export2 } from 'module-name4'", + { language: 'javascript', imports: ['module-name1', 'module-name2', ''] } + ) + parseItem(c, [], []) + + expect(c.imports).toHaveLength(3) + expect(c.imports).toContain('module-name1') + expect(c.imports).toContain('module-name2') + expect(c.imports).toContain('') + }) }) describe('CLI parameter parsing', () => {