fix display of warnings/errors

pull/2179/head
Richard Harris 7 years ago
parent 4b106d07d1
commit 4a142ea71e

@ -6,7 +6,21 @@
export let error;
export let errorLoc;
export let warningCount = 0;
export let warnings;
$: message = warning => {
let str = warning.message;
let loc = [];
if (warning.filename && warning.filename !== `${$selected.name}.${$selected.type}`) {
loc.push(warning.filename);
}
if (warning.start) loc.push(warning.start.line, warning.start.column);
return str + (loc.length ? ` (${loc.join(':')})` : ``);
};
</script>
<style>
@ -31,6 +45,10 @@
border-top: 1px solid white;
}
.navigable {
cursor: pointer;
}
.info p::before {
content: '!';
position: absolute;
@ -78,9 +96,19 @@
<div class="info">
{#if error}
<p class="error" on:click="{() => navigate(error)}">{error.message}</p>
{:else if warningCount > 0}
<p class="warning">Compiled, but with {warningCount} {warningCount === 1 ? 'warning' : 'warnings'} — check the console for details</p>
<p
class="error"
class:navigable={error.filename}
on:click="{() => navigate(error)}"
>{error.message}</p>
{:else if warnings.length > 0}
{#each warnings as warning}
<p
class="warning"
class:navigable={warning.filename}
on:click="{() => navigate(warning)}"
>{message(warning)}</p>
{/each}
{/if}
</div>
</div>

@ -4,13 +4,9 @@
export let error;
export let errorLoc;
export let warningCount;
export let warnings; // TODO use context
</script>
<ComponentSelector/>
<ModuleEditor
{error}
{errorLoc}
{warningCount}
/>
<ModuleEditor {error} {errorLoc} {warnings}/>

@ -37,13 +37,15 @@
values,
selected,
navigate: filename => {
const name = filename.replace(/\.svelte$/, '');
navigate: item => {
const match = /^(.+)\.(\w+)$/.exec(item.filename);
if (!match) return; // ???
console.error(`TODO navigate`);
const [, name, type] = match;
const component = $components.find(c => c.name === name && c.type === type);
selected.set(component);
// if (selected.name === name) return;
// selected = components.find(c => c.name === name);
// TODO select the line/column in question
},
handle_change: event => {
@ -80,7 +82,7 @@
let ssr;
let sourceError = null;
let runtimeError = null;
let warningCount = 0;
let warnings = [];
let js = '';
let css = '';
let uid = 0;
@ -110,13 +112,13 @@
workers.compiler.postMessage({ type: 'init', version });
workers.compiler.onmessage = event => {
js = event.data.js;
css = event.data.css || `/* Add a <style> tag to see compiled CSS */`;
css = event.data.css || `/* Add a <sty` + `le> tag to see compiled CSS */`;
if (event.data.props) props = event.data.props;
};
workers.bundler.postMessage({ type: 'init', version });
workers.bundler.onmessage = event => {
({ bundle, dom, ssr, warningCount, error: sourceError } = event.data);
({ bundle, dom, ssr, warnings, error: sourceError } = event.data);
if (sourceError) console.error(sourceError);
runtimeError = null;
};
@ -274,7 +276,7 @@
<Input
error={sourceError}
errorLoc="{sourceErrorLoc || runtimeErrorLoc}"
{warningCount}
{warnings}
/>
</section>

@ -1,290 +0,0 @@
<script context="module">
let codemirror_promise;
let _CodeMirror;
if (process.browser) {
codemirror_promise = import(/* webpackChunkName: "codemirror" */ './_codemirror.js');
codemirror_promise.then(mod => {
_CodeMirror = mod.default;
});
}
</script>
<script>
import { onMount, beforeUpdate, createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
export let mode;
export let code;
export let readonly = false;
export let error = null;
export let errorLoc = null;
export let warningCount = 0;
export let flex = false;
export let lineNumbers = true;
export let tab = true;
let w;
let h;
export function resize() {
editor.refresh();
}
const modes = {
json: {
name: 'javascript',
json: true
},
handlebars: {
name: 'handlebars',
base: 'text/html'
}
};
const refs = {};
let editor;
let updating = false;
let marker;
let error_line;
let destroyed = false;
let CodeMirror;
$: if (CodeMirror) {
createEditor(mode);
}
$: if (editor && !updating && code != null) {
updating = true;
editor.setValue(code);
}
$: if (editor && w && h) {
editor.refresh();
}
$: {
if (marker) marker.clear();
if (errorLoc) {
const line = errorLoc.line - 1;
const ch = errorLoc.column;
marker = editor.markText({ line, ch }, { line, ch: ch + 1 }, {
className: 'error-loc'
});
error_line = line;
} else {
error_line = null;
}
}
let previous_error_line;
$: if (editor) {
if (previous_error_line != null) {
editor.removeLineClass(previous_error_line, 'wrap', 'error-line')
}
if (error_line && (error_line !== previous_error_line)) {
editor.addLineClass(error_line, 'wrap', 'error-line');
previous_error_line = error_line;
}
}
onMount(() => {
if (_CodeMirror) {
CodeMirror = _CodeMirror;
} else {
codemirror_promise.then(mod => {
CodeMirror = mod.default;
});
}
return () => {
destroyed = true;
if (editor) editor.toTextArea();
}
});
beforeUpdate(() => {
updating = false;
});
function createEditor(mode) {
if (destroyed) return;
if (editor) {
editor.toTextArea();
}
const opts = {
lineNumbers,
lineWrapping: true,
indentWithTabs: true,
indentUnit: 2,
tabSize: 2,
value: code,
mode: modes[mode] || {
name: mode
},
readOnly: readonly
};
if (!tab) opts.extraKeys = {
Tab: tab,
'Shift-Tab': tab
};
editor = CodeMirror.fromTextArea(refs.editor, opts);
editor.on('change', instance => {
if (!updating) {
updating = true;
code = instance.getValue();
dispatch('change', { value: code });
}
});
editor.refresh();
}
</script>
<style>
.codemirror-container {
position: relative;
width: 100%;
height: 100%;
border: none;
line-height: 1.5;
}
.codemirror-container :global(.CodeMirror) {
height: 100%;
/* background: var(--background); */
background: transparent;
font: 400 var(--code-fs)/1.7 var(--font-mono);
color: var(--base);
}
.codemirror-container.flex :global(.CodeMirror) {
height: auto;
}
.codemirror-container.flex :global(.CodeMirror-lines) {
padding: 0;
}
.codemirror-container :global(.CodeMirror-gutters) {
padding: 0 1.6rem 0 .8rem;
border: none;
}
.codemirror-container .message {
position: absolute;
bottom: 2.4rem;
left: 2.4rem;
z-index: 20;
}
.codemirror-container :global(.error-loc) {
position: relative;
border-bottom: 2px solid #da106e;
}
.codemirror-container :global(.error-line) {
background-color: rgba(200, 0, 0, .05);
}
.loading,
.error {
text-align: center;
color: #999;
font-weight: 400;
margin: 2.4rem 0 0 0;
}
.loading {
background-color: #666;
}
textarea {
visibility: hidden;
}
pre {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
border: none;
padding: 4px 4px 4px 57px;
resize: none;
font-family: var(--font-mono);
font-size: 1.3rem;
line-height: 1.7;
user-select: none;
pointer-events: none;
color: #ccc;
tab-size: 2;
-moz-tab-size: 2;
}
.flex pre {
padding: 0 0 0 4px;
height: auto;
}
.flex .loading {
display: none;
}
</style>
<!--
-----------------------------------------------
syntax-highlighting [prism]
NOTE
- just started to transfer colors from prism to codemirror
-----------------------------------------------
-->
<div class='codemirror-container' class:flex bind:offsetWidth={w} bind:offsetHeight={h}>
<textarea
tabindex='2'
bind:this={refs.editor}
readonly
value={code}
></textarea>
{#if error}
<p class='error message'>
{#if error.loc}
<strong>
{#if error.filename}
<span
class='filename'
on:click="{() => dispatch('navigate', { filename: error.filename })}"
>{error.filename}</span>
{/if}
({error.loc.line}:{error.loc.column})
</strong>
{/if}
{error.message}
</p>
{:else if warningCount > 0}
<p class='warning message'>
Compiled, but with {warningCount} {warningCount === 1 ? 'warning' : 'warnings'} — check the console for details
</p>
{/if}
{#if !CodeMirror}
<pre style="position: absolute; left: 0; top: 0"
>{code}</pre>
<p class='loading message'>loading editor...</p>
{/if}
</div>

@ -38,8 +38,8 @@ const commonCompilerOptions = {
};
let cached = {
dom: null,
ssr: null
dom: {},
ssr: {}
};
let currentToken;
@ -63,9 +63,9 @@ function fetch_if_uncached(url) {
async function getBundle(mode, cache, lookup) {
let bundle;
let error;
let warningCount = 0;
const all_warnings = [];
const info = {};
const new_cache = {};
try {
bundle = await rollup.rollup({
@ -99,33 +99,40 @@ async function getBundle(mode, cache, lookup) {
const name = id.replace(/^\.\//, '').replace(/\.svelte$/, '');
const { js, stats, warnings } = svelte.compile(code, Object.assign({
const result = cache[id] && cache[id].code === code
? cache[id].result
: svelte.compile(code, Object.assign({
generate: mode,
format: 'esm',
name: name,
filename: name + '.svelte'
}, commonCompilerOptions));
(warnings || stats.warnings).forEach(warning => { // TODO remove stats post-launch
console.warn(warning.message);
console.log(warning.frame);
warningCount += 1;
new_cache[id] = { code, result };
(result.warnings || result.stats.warnings).forEach(warning => { // TODO remove stats post-launch
all_warnings.push({
message: warning.message,
filename: warning.filename,
start: warning.start,
end: warning.end
});
});
return js;
return result.js;
}
}],
onwarn(warning) {
console.warn(warning);
warningCount += 1;
},
cache
all_warnings.push({
message: warning.message
});
}
});
} catch (error) {
return { error, bundle: null, info: null, warningCount: null }
return { error, bundle: null, cache: new_cache, warnings: all_warnings }
}
return { bundle, info, error: null, warningCount };
return { bundle, cache: new_cache, error: null, warnings: all_warnings };
}
async function bundle(components) {
@ -154,7 +161,7 @@ async function bundle(components) {
return;
}
cached.dom = dom.bundle;
cached.dom = dom.cache;
let uid = 1;
const importMap = new Map();
@ -172,12 +179,12 @@ async function bundle(components) {
if (token !== currentToken) return;
const ssr = dom.info.usesHooks
const ssr = false // TODO how can we do SSR?
? await getBundle('ssr', cached.ssr, lookup)
: null;
if (ssr) {
cached.ssr = ssr.bundle;
cached.ssr = ssr.cache;
if (ssr.error) {
throw ssr.error;
}
@ -201,7 +208,7 @@ async function bundle(components) {
},
dom: domResult,
ssr: ssrResult,
warningCount: dom.warningCount,
warnings: dom.warnings,
error: null
};
} catch (err) {
@ -212,7 +219,7 @@ async function bundle(components) {
bundle: null,
dom: null,
ssr: null,
warningCount: dom.warningCount,
warnings: dom.warnings,
error: Object.assign({}, e, {
message: e.message,
stack: e.stack

Loading…
Cancel
Save