Skip to content

Commit d31d857

Browse files
authored
Merge pull request #2102 from sveltejs/warnings-and-vars
move warnings and vars out of stats
2 parents 0ad8bf9 + b2f371a commit d31d857

File tree

41 files changed

+231
-221
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+231
-221
lines changed

src/Stats.ts

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import { Warning } from './interfaces';
2-
import Component from './compile/Component';
3-
41
const now = (typeof process !== 'undefined' && process.hrtime)
52
? () => {
63
const t = process.hrtime();
@@ -31,14 +28,11 @@ export default class Stats {
3128
currentChildren: Timing[];
3229
timings: Timing[];
3330
stack: Timing[];
34-
warnings: Warning[];
3531

3632
constructor() {
3733
this.startTime = now();
3834
this.stack = [];
3935
this.currentChildren = this.timings = [];
40-
41-
this.warnings = [];
4236
}
4337

4438
start(label) {
@@ -67,46 +61,13 @@ export default class Stats {
6761
this.currentChildren = this.currentTiming ? this.currentTiming.children : this.timings;
6862
}
6963

70-
render(component: Component) {
64+
render() {
7165
const timings = Object.assign({
7266
total: now() - this.startTime
7367
}, collapseTimings(this.timings));
7468

75-
// TODO would be good to have this info even
76-
// if options.generate is false
77-
const imports = component && component.imports.map(node => {
78-
return {
79-
source: node.source.value,
80-
specifiers: node.specifiers.map(specifier => {
81-
return {
82-
name: (
83-
specifier.type === 'ImportDefaultSpecifier' ? 'default' :
84-
specifier.type === 'ImportNamespaceSpecifier' ? '*' :
85-
specifier.imported.name
86-
),
87-
as: specifier.local.name
88-
};
89-
})
90-
}
91-
});
92-
9369
return {
94-
timings,
95-
warnings: this.warnings,
96-
vars: component.vars.filter(variable => !variable.global && !variable.implicit && !variable.internal).map(variable => ({
97-
name: variable.name,
98-
export_name: variable.export_name || null,
99-
injected: variable.injected || false,
100-
module: variable.module || false,
101-
mutated: variable.mutated || false,
102-
reassigned: variable.reassigned || false,
103-
referenced: variable.referenced || false,
104-
writable: variable.writable || false
105-
}))
70+
timings
10671
};
10772
}
108-
109-
warn(warning) {
110-
this.warnings.push(warning);
111-
}
11273
}

src/compile/Component.ts

Lines changed: 97 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Stylesheet from './css/Stylesheet';
1111
import { test } from '../config';
1212
import Fragment from './nodes/Fragment';
1313
import internal_exports from './internal-exports';
14-
import { Node, Ast, CompileOptions, Var } from '../interfaces';
14+
import { Node, Ast, CompileOptions, Var, Warning } from '../interfaces';
1515
import error from '../utils/error';
1616
import getCodeFrame from '../utils/getCodeFrame';
1717
import flattenReference from '../utils/flattenReference';
@@ -40,6 +40,7 @@ childKeys.ExportNamedDeclaration = ['declaration', 'specifiers'];
4040

4141
export default class Component {
4242
stats: Stats;
43+
warnings: Warning[];
4344

4445
ast: Ast;
4546
source: string;
@@ -93,11 +94,13 @@ export default class Component {
9394
source: string,
9495
name: string,
9596
compileOptions: CompileOptions,
96-
stats: Stats
97+
stats: Stats,
98+
warnings: Warning[]
9799
) {
98100
this.name = name;
99101

100102
this.stats = stats;
103+
this.warnings = warnings;
101104
this.ast = ast;
102105
this.source = source;
103106
this.compileOptions = compileOptions;
@@ -161,7 +164,7 @@ export default class Component {
161164

162165
if (!compileOptions.customElement) this.stylesheet.reify();
163166

164-
this.stylesheet.warnOnUnusedSelectors(stats);
167+
this.stylesheet.warnOnUnusedSelectors(this);
165168
}
166169

167170
add_var(variable: Var) {
@@ -214,105 +217,121 @@ export default class Component {
214217
}
215218

216219
generate(result: string) {
217-
const { compileOptions, name } = this;
218-
const { format = 'esm' } = compileOptions;
220+
let js = null;
221+
let css = null;
219222

220-
const banner = `/* ${this.file ? `${this.file} ` : ``}generated by Svelte v${"__VERSION__"} */`;
223+
if (result) {
224+
const { compileOptions, name } = this;
225+
const { format = 'esm' } = compileOptions;
221226

222-
// TODO use same regex for both
223-
result = result.replace(compileOptions.generate === 'ssr' ? /(@+|#+)(\w*(?:-\w*)?)/g : /(@+)(\w*(?:-\w*)?)/g, (match: string, sigil: string, name: string) => {
224-
if (sigil === '@') {
225-
if (internal_exports.has(name)) {
226-
if (compileOptions.dev && internal_exports.has(`${name}Dev`)) name = `${name}Dev`;
227-
this.helpers.add(name);
228-
}
227+
const banner = `/* ${this.file ? `${this.file} ` : ``}generated by Svelte v${"__VERSION__"} */`;
229228

230-
return this.alias(name);
231-
}
229+
// TODO use same regex for both
230+
result = result.replace(compileOptions.generate === 'ssr' ? /(@+|#+)(\w*(?:-\w*)?)/g : /(@+)(\w*(?:-\w*)?)/g, (match: string, sigil: string, name: string) => {
231+
if (sigil === '@') {
232+
if (internal_exports.has(name)) {
233+
if (compileOptions.dev && internal_exports.has(`${name}Dev`)) name = `${name}Dev`;
234+
this.helpers.add(name);
235+
}
232236

233-
return sigil.slice(1) + name;
234-
});
237+
return this.alias(name);
238+
}
235239

236-
const importedHelpers = Array.from(this.helpers)
237-
.sort()
238-
.map(name => {
239-
const alias = this.alias(name);
240-
return { name, alias };
240+
return sigil.slice(1) + name;
241241
});
242242

243-
const module = wrapModule(
244-
result,
245-
format,
246-
name,
247-
compileOptions,
248-
banner,
249-
compileOptions.sveltePath,
250-
importedHelpers,
251-
this.imports,
252-
this.vars.filter(variable => variable.module && variable.export_name).map(variable => ({
253-
name: variable.name,
254-
as: variable.export_name
255-
})),
256-
this.source
257-
);
243+
const importedHelpers = Array.from(this.helpers)
244+
.sort()
245+
.map(name => {
246+
const alias = this.alias(name);
247+
return { name, alias };
248+
});
249+
250+
const module = wrapModule(
251+
result,
252+
format,
253+
name,
254+
compileOptions,
255+
banner,
256+
compileOptions.sveltePath,
257+
importedHelpers,
258+
this.imports,
259+
this.vars.filter(variable => variable.module && variable.export_name).map(variable => ({
260+
name: variable.name,
261+
as: variable.export_name
262+
})),
263+
this.source
264+
);
258265

259-
const parts = module.split('✂]');
260-
const finalChunk = parts.pop();
266+
const parts = module.split('✂]');
267+
const finalChunk = parts.pop();
261268

262-
const compiled = new Bundle({ separator: '' });
269+
const compiled = new Bundle({ separator: '' });
263270

264-
function addString(str: string) {
265-
compiled.addSource({
266-
content: new MagicString(str),
267-
});
268-
}
271+
function addString(str: string) {
272+
compiled.addSource({
273+
content: new MagicString(str),
274+
});
275+
}
269276

270-
const { filename } = compileOptions;
277+
const { filename } = compileOptions;
271278

272-
// special case — the source file doesn't actually get used anywhere. we need
273-
// to add an empty file to populate map.sources and map.sourcesContent
274-
if (!parts.length) {
275-
compiled.addSource({
276-
filename,
277-
content: new MagicString(this.source).remove(0, this.source.length),
278-
});
279-
}
279+
// special case — the source file doesn't actually get used anywhere. we need
280+
// to add an empty file to populate map.sources and map.sourcesContent
281+
if (!parts.length) {
282+
compiled.addSource({
283+
filename,
284+
content: new MagicString(this.source).remove(0, this.source.length),
285+
});
286+
}
280287

281-
const pattern = /\[(\d+)-(\d+)$/;
288+
const pattern = /\[(\d+)-(\d+)$/;
282289

283-
parts.forEach((str: string) => {
284-
const chunk = str.replace(pattern, '');
285-
if (chunk) addString(chunk);
290+
parts.forEach((str: string) => {
291+
const chunk = str.replace(pattern, '');
292+
if (chunk) addString(chunk);
286293

287-
const match = pattern.exec(str);
294+
const match = pattern.exec(str);
288295

289-
const snippet = this.code.snip(+match[1], +match[2]);
296+
const snippet = this.code.snip(+match[1], +match[2]);
290297

291-
compiled.addSource({
292-
filename,
293-
content: snippet,
298+
compiled.addSource({
299+
filename,
300+
content: snippet,
301+
});
294302
});
295-
});
296303

297-
addString(finalChunk);
304+
addString(finalChunk);
298305

299-
const css = compileOptions.customElement ?
300-
{ code: null, map: null } :
301-
this.stylesheet.render(compileOptions.cssOutputFilename, true);
306+
css = compileOptions.customElement ?
307+
{ code: null, map: null } :
308+
this.stylesheet.render(compileOptions.cssOutputFilename, true);
302309

303-
const js = {
304-
code: compiled.toString(),
305-
map: compiled.generateMap({
306-
includeContent: true,
307-
file: compileOptions.outputFilename,
308-
})
309-
};
310+
js = {
311+
code: compiled.toString(),
312+
map: compiled.generateMap({
313+
includeContent: true,
314+
file: compileOptions.outputFilename,
315+
})
316+
};
317+
}
310318

311319
return {
312-
ast: this.ast,
313320
js,
314321
css,
315-
stats: this.stats.render(this)
322+
ast: this.ast,
323+
warnings: this.warnings,
324+
vars: this.vars.filter(v => !v.global && !v.implicit && !v.internal).map(v => ({
325+
name: v.name,
326+
export_name: v.export_name || null,
327+
injected: v.injected || false,
328+
module: v.module || false,
329+
mutated: v.mutated || false,
330+
reassigned: v.reassigned || false,
331+
referenced: v.referenced || false,
332+
writable: v.writable || false
333+
})),
334+
stats: this.stats.render()
316335
};
317336
}
318337

@@ -393,7 +412,7 @@ export default class Component {
393412

394413
const frame = getCodeFrame(this.source, start.line - 1, start.column);
395414

396-
this.stats.warn({
415+
this.warnings.push({
397416
code: warning.code,
398417
message: warning.message,
399418
frame,

src/compile/css/Stylesheet.ts

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import MagicString from 'magic-string';
22
import { walk } from 'estree-walker';
3-
import { getLocator } from 'locate-character';
43
import Selector from './Selector';
5-
import getCodeFrame from '../../utils/getCodeFrame';
64
import hash from '../../utils/hash';
75
import removeCSSPrefix from '../../utils/removeCSSPrefix';
86
import Element from '../nodes/Element';
9-
import { Node, Ast, Warning } from '../../interfaces';
7+
import { Node, Ast } from '../../interfaces';
108
import Component from '../Component';
11-
import Stats from '../../Stats';
129

1310
const isKeyframesNode = (node: Node) => removeCSSPrefix(node.name) === 'keyframes'
1411

@@ -392,33 +389,14 @@ export default class Stylesheet {
392389
});
393390
}
394391

395-
warnOnUnusedSelectors(stats: Stats) {
396-
let locator;
397-
398-
const handler = (selector: Selector) => {
399-
const pos = selector.node.start;
400-
401-
if (!locator) locator = getLocator(this.source, { offsetLine: 1 });
402-
const start = locator(pos);
403-
const end = locator(selector.node.end);
404-
405-
const frame = getCodeFrame(this.source, start.line - 1, start.column);
406-
const message = `Unused CSS selector`;
407-
408-
stats.warn({
409-
code: `css-unused-selector`,
410-
message,
411-
frame,
412-
start,
413-
end,
414-
pos,
415-
filename: this.filename,
416-
toString: () => `${message} (${start.line}:${start.column})\n${frame}`,
417-
});
418-
};
419-
392+
warnOnUnusedSelectors(component: Component) {
420393
this.children.forEach(child => {
421-
child.warnOnUnusedSelector(handler);
394+
child.warnOnUnusedSelector((selector: Selector) => {
395+
component.warn(selector.node, {
396+
code: `css-unused-selector`,
397+
message: `Unused CSS selector`
398+
});
399+
});
422400
});
423401
}
424402
}

0 commit comments

Comments
 (0)