diff --git a/src/Stats.ts b/src/Stats.ts index a27ff98105..dd721c7e81 100644 --- a/src/Stats.ts +++ b/src/Stats.ts @@ -1,4 +1,3 @@ -import { Warning } from './interfaces'; import Component from './compile/Component'; const now = (typeof process !== 'undefined' && process.hrtime) @@ -31,14 +30,11 @@ export default class Stats { currentChildren: Timing[]; timings: Timing[]; stack: Timing[]; - warnings: Warning[]; constructor() { this.startTime = now(); this.stack = []; this.currentChildren = this.timings = []; - - this.warnings = []; } start(label) { @@ -92,7 +88,6 @@ export default class Stats { return { timings, - warnings: this.warnings, vars: component.vars.filter(variable => !variable.global && !variable.implicit && !variable.internal).map(variable => ({ name: variable.name, export_name: variable.export_name || null, @@ -105,8 +100,4 @@ export default class Stats { })) }; } - - warn(warning) { - this.warnings.push(warning); - } } diff --git a/src/compile/Component.ts b/src/compile/Component.ts index 09f5261c63..4ff1eff92d 100644 --- a/src/compile/Component.ts +++ b/src/compile/Component.ts @@ -11,7 +11,7 @@ import Stylesheet from './css/Stylesheet'; import { test } from '../config'; import Fragment from './nodes/Fragment'; import internal_exports from './internal-exports'; -import { Node, Ast, CompileOptions, Var } from '../interfaces'; +import { Node, Ast, CompileOptions, Var, Warning } from '../interfaces'; import error from '../utils/error'; import getCodeFrame from '../utils/getCodeFrame'; import flattenReference from '../utils/flattenReference'; @@ -40,6 +40,7 @@ childKeys.ExportNamedDeclaration = ['declaration', 'specifiers']; export default class Component { stats: Stats; + warnings: Warning[]; ast: Ast; source: string; @@ -93,11 +94,13 @@ export default class Component { source: string, name: string, compileOptions: CompileOptions, - stats: Stats + stats: Stats, + warnings: Warning[] ) { this.name = name; this.stats = stats; + this.warnings = warnings; this.ast = ast; this.source = source; this.compileOptions = compileOptions; @@ -161,7 +164,7 @@ export default class Component { if (!compileOptions.customElement) this.stylesheet.reify(); - this.stylesheet.warnOnUnusedSelectors(stats); + this.stylesheet.warnOnUnusedSelectors(this); } add_var(variable: Var) { @@ -309,9 +312,10 @@ export default class Component { }; return { - ast: this.ast, js, css, + ast: this.ast, + warnings: this.warnings, stats: this.stats.render(this) }; } @@ -393,7 +397,7 @@ export default class Component { const frame = getCodeFrame(this.source, start.line - 1, start.column); - this.stats.warn({ + this.warnings.push({ code: warning.code, message: warning.message, frame, diff --git a/src/compile/css/Stylesheet.ts b/src/compile/css/Stylesheet.ts index 0a36086765..aa4db3b5de 100644 --- a/src/compile/css/Stylesheet.ts +++ b/src/compile/css/Stylesheet.ts @@ -1,14 +1,11 @@ import MagicString from 'magic-string'; import { walk } from 'estree-walker'; -import { getLocator } from 'locate-character'; import Selector from './Selector'; -import getCodeFrame from '../../utils/getCodeFrame'; import hash from '../../utils/hash'; import removeCSSPrefix from '../../utils/removeCSSPrefix'; import Element from '../nodes/Element'; -import { Node, Ast, Warning } from '../../interfaces'; +import { Node, Ast } from '../../interfaces'; import Component from '../Component'; -import Stats from '../../Stats'; const isKeyframesNode = (node: Node) => removeCSSPrefix(node.name) === 'keyframes' @@ -392,33 +389,14 @@ export default class Stylesheet { }); } - warnOnUnusedSelectors(stats: Stats) { - let locator; - - const handler = (selector: Selector) => { - const pos = selector.node.start; - - if (!locator) locator = getLocator(this.source, { offsetLine: 1 }); - const start = locator(pos); - const end = locator(selector.node.end); - - const frame = getCodeFrame(this.source, start.line - 1, start.column); - const message = `Unused CSS selector`; - - stats.warn({ - code: `css-unused-selector`, - message, - frame, - start, - end, - pos, - filename: this.filename, - toString: () => `${message} (${start.line}:${start.column})\n${frame}`, - }); - }; - + warnOnUnusedSelectors(component: Component) { this.children.forEach(child => { - child.warnOnUnusedSelector(handler); + child.warnOnUnusedSelector((selector: Selector) => { + component.warn(selector.node, { + code: `css-unused-selector`, + message: `Unused CSS selector` + }); + }); }); } } diff --git a/src/compile/index.ts b/src/compile/index.ts index 404d933327..2efbaf53a2 100644 --- a/src/compile/index.ts +++ b/src/compile/index.ts @@ -3,7 +3,7 @@ import Stats from '../Stats'; import parse from '../parse/index'; import renderDOM from './render-dom/index'; import renderSSR from './render-ssr/index'; -import { CompileOptions, Ast } from '../interfaces'; +import { CompileOptions, Ast, Warning } from '../interfaces'; import Component from './Component'; import fuzzymatch from '../utils/fuzzymatch'; @@ -24,7 +24,7 @@ const valid_options = [ 'preserveComments' ]; -function validate_options(options: CompileOptions, stats: Stats) { +function validate_options(options: CompileOptions, warnings: Warning[]) { const { name, filename } = options; Object.keys(options).forEach(key => { @@ -43,7 +43,7 @@ function validate_options(options: CompileOptions, stats: Stats) { if (name && /^[a-z]/.test(name)) { const message = `options.name should be capitalised`; - stats.warn({ + warnings.push({ code: `options-lowercase-name`, message, filename, @@ -74,10 +74,11 @@ export default function compile(source: string, options: CompileOptions = {}) { options = assign({ generate: 'dom', dev: false }, options); const stats = new Stats(); + const warnings = []; let ast: Ast; - validate_options(options, stats); + validate_options(options, warnings); stats.start('parse'); ast = parse(source, options); @@ -89,12 +90,13 @@ export default function compile(source: string, options: CompileOptions = {}) { source, options.name || get_name(options.filename) || 'SvelteComponent', options, - stats + stats, + warnings ); stats.stop('create component'); if (options.generate === false) { - return { ast, stats: stats.render(component), js: null, css: null }; + return { ast, warnings, stats: stats.render(component), js: null, css: null }; } const js = options.generate === 'ssr' diff --git a/test/css/index.js b/test/css/index.js index 684c310526..be2a10bef1 100644 --- a/test/css/index.js +++ b/test/css/index.js @@ -68,8 +68,8 @@ describe('css', () => { assert.equal(dom.css.code, ssr.css.code); - const dom_warnings = dom.stats.warnings.map(normalize_warning); - const ssr_warnings = ssr.stats.warnings.map(normalize_warning); + const dom_warnings = dom.warnings.map(normalize_warning); + const ssr_warnings = ssr.warnings.map(normalize_warning); assert.deepEqual(dom_warnings, ssr_warnings); assert.deepEqual(dom_warnings.map(normalize_warning), expected_warnings); diff --git a/test/stats/index.js b/test/stats/index.js index fe4c2ac55b..e5a3c53eca 100644 --- a/test/stats/index.js +++ b/test/stats/index.js @@ -32,8 +32,8 @@ describe('stats', () => { result = svelte.compile(input, config.options); config.test(assert, result.stats); - if (result.stats.warnings.length || expectedWarnings.length) { - // TODO check warnings are added to stats.warnings + if (result.warnings.length || expectedWarnings.length) { + // TODO check warnings are added to warnings } } catch (e) { error = e; diff --git a/test/validator/index.js b/test/validator/index.js index f68cb8831d..b26b087bb3 100644 --- a/test/validator/index.js +++ b/test/validator/index.js @@ -24,21 +24,19 @@ describe("validate", () => { let error; try { - const { stats } = svelte.compile(input, { + let { warnings } = svelte.compile(input, { dev: config.dev, legacy: config.legacy, generate: false }); - const warnings = stats.warnings.map(w => ({ + assert.deepEqual(warnings.map(w => ({ code: w.code, message: w.message, pos: w.pos, start: w.start, end: w.end - })); - - assert.deepEqual(warnings, expected_warnings); + })), expected_warnings); } catch (e) { error = e; } @@ -78,12 +76,12 @@ describe("validate", () => { }); it("warns if options.name is not capitalised", () => { - const { stats } = svelte.compile("
", { + const { warnings } = svelte.compile("
", { name: "lowercase", generate: false }); - assert.deepEqual(stats.warnings.map(w => ({ + assert.deepEqual(warnings.map(w => ({ code: w.code, message: w.message })), [{ @@ -93,11 +91,11 @@ describe("validate", () => { }); it("does not warn if options.name begins with non-alphabetic character", () => { - const { stats } = svelte.compile("
", { + const { warnings } = svelte.compile("
", { name: "_", generate: false }); - assert.deepEqual(stats.warnings, []); + assert.deepEqual(warnings, []); }); });