Better error handling

This commit is contained in:
pietervdvn 2022-04-22 03:17:40 +02:00
parent e5dbeee621
commit ad3a776366
6 changed files with 106 additions and 78 deletions

View file

@ -202,6 +202,7 @@ export class Fuse<T> extends DesugaringStep<T> {
const information = [] const information = []
for (let i = 0; i < this.steps.length; i++) { for (let i = 0; i < this.steps.length; i++) {
const step = this.steps[i]; const step = this.steps[i];
try{
let r = step.convert(json, "While running step " + step.name + ": " + context) let r = step.convert(json, "While running step " + step.name + ": " + context)
errors.push(...r.errors ?? []) errors.push(...r.errors ?? [])
warnings.push(...r.warnings ?? []) warnings.push(...r.warnings ?? [])
@ -210,6 +211,10 @@ export class Fuse<T> extends DesugaringStep<T> {
if (errors.length > 0) { if (errors.length > 0) {
break; break;
} }
}catch(e){
console.error("Step "+step.name+" failed due to "+e);
throw e
}
} }
return { return {
result: json, result: json,

View file

@ -13,6 +13,7 @@ import {AddContextToTranslations} from "./AddContextToTranslations";
class SubstituteLayer extends Conversion<(string | LayerConfigJson), LayerConfigJson[]> { class SubstituteLayer extends Conversion<(string | LayerConfigJson), LayerConfigJson[]> {
private readonly _state: DesugaringContext; private readonly _state: DesugaringContext;
constructor( constructor(
state: DesugaringContext, state: DesugaringContext,
) { ) {
@ -24,6 +25,7 @@ class SubstituteLayer extends Conversion<(string | LayerConfigJson), LayerConfig
const errors = [] const errors = []
const information = [] const information = []
const state = this._state const state = this._state
function reportNotFound(name: string) { function reportNotFound(name: string) {
const knownLayers = Array.from(state.sharedLayers.keys()) const knownLayers = Array.from(state.sharedLayers.keys())
const withDistance = knownLayers.map(lname => [lname, Utils.levenshteinDistance(name, lname)]) const withDistance = knownLayers.map(lname => [lname, Utils.levenshteinDistance(name, lname)])
@ -222,6 +224,7 @@ class AddImportLayers extends DesugaringStep<LayoutConfigJson> {
export class AddMiniMap extends DesugaringStep<LayerConfigJson> { export class AddMiniMap extends DesugaringStep<LayerConfigJson> {
private readonly _state: DesugaringContext; private readonly _state: DesugaringContext;
constructor(state: DesugaringContext,) { constructor(state: DesugaringContext,) {
super("Adds a default 'minimap'-element to the tagrenderings if none of the elements define such a minimap", ["tagRenderings"], "AddMiniMap"); super("Adds a default 'minimap'-element to the tagrenderings if none of the elements define such a minimap", ["tagRenderings"], "AddMiniMap");
this._state = state; this._state = state;
@ -325,6 +328,7 @@ class ApplyOverrideAll extends DesugaringStep<LayoutConfigJson> {
class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> { class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
private readonly _state: DesugaringContext; private readonly _state: DesugaringContext;
constructor(state: DesugaringContext,) { constructor(state: DesugaringContext,) {
super("If a layer has a dependency on another layer, these layers are added automatically on the theme. (For example: defibrillator depends on 'walls_and_buildings' to snap onto. This layer is added automatically)", ["layers"], "AddDependencyLayersToTheme"); super("If a layer has a dependency on another layer, these layers are added automatically on the theme. (For example: defibrillator depends on 'walls_and_buildings' to snap onto. This layer is added automatically)", ["layers"], "AddDependencyLayersToTheme");
this._state = state; this._state = state;
@ -418,6 +422,7 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
class PreparePersonalTheme extends DesugaringStep<LayoutConfigJson> { class PreparePersonalTheme extends DesugaringStep<LayoutConfigJson> {
private readonly _state: DesugaringContext; private readonly _state: DesugaringContext;
constructor(state: DesugaringContext) { constructor(state: DesugaringContext) {
super("Adds every public layer to the personal theme", ["layers"], "PreparePersonalTheme"); super("Adds every public layer to the personal theme", ["layers"], "PreparePersonalTheme");
this._state = state; this._state = state;
@ -472,6 +477,7 @@ export class PrepareTheme extends Fuse<LayoutConfigJson> {
constructor(state: DesugaringContext) { constructor(state: DesugaringContext) {
super( super(
"Fully prepares and expands a theme", "Fully prepares and expands a theme",
new AddContextToTransltionsInLayout(), new AddContextToTransltionsInLayout(),
new PreparePersonalTheme(state), new PreparePersonalTheme(state),
new WarnForUnsubstitutedLayersInTheme(), new WarnForUnsubstitutedLayersInTheme(),

View file

@ -217,12 +217,17 @@ class MiscThemeChecks extends DesugaringStep<LayoutConfigJson>{
convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } {
const warnings = [] const warnings = []
const errors = []
if(json.id !== "personal" && (json.layers === undefined || json.layers.length === 0)){
errors.push("The theme "+json.id+" has no 'layers' defined ("+context+")")
}
if(json.socialImage === ""){ if(json.socialImage === ""){
warnings.push("Social image for theme "+json.id+" is the emtpy string") warnings.push("Social image for theme "+json.id+" is the emtpy string")
} }
return { return {
result :json, result :json,
warnings warnings,
errors
}; };
} }
} }
@ -231,8 +236,8 @@ export class PrevalidateTheme extends Fuse<LayoutConfigJson> {
constructor() { constructor() {
super("Various consistency checks on the raw JSON", super("Various consistency checks on the raw JSON",
new OverrideShadowingCheck(), new MiscThemeChecks(),
new MiscThemeChecks() new OverrideShadowingCheck()
); );
} }

View file

@ -18,9 +18,12 @@ export default interface UnitConfigJson {
export interface ApplicableUnitJson { export interface ApplicableUnitJson {
/** /**
* The canonical value which will be added to the text. * The canonical value which will be added to the value in OSM.
* e.g. "m" for meters * e.g. "m" for meters
* If the user inputs '42', the canonical value will be added and it'll become '42m' * If the user inputs '42', the canonical value will be added and it'll become '42m'.
*
* Important: often, _no_ canonical values are expected, e.g. in the case of 'maxspeed' where 'km/h' is the default.
* In this case, an empty string should be used
*/ */
canonicalDenomination: string, canonicalDenomination: string,
/** /**

View file

@ -133,6 +133,9 @@ export default class LayerConfig extends WithContextLoader {
this.allowSplit = json.allowSplit ?? false; this.allowSplit = json.allowSplit ?? false;
this.name = Translations.T(json.name, translationContext + ".name"); this.name = Translations.T(json.name, translationContext + ".name");
if(json.units!==undefined && !Array.isArray(json.units)){
throw "At "+context+".units: the 'units'-section should be a list; you probably have an object there"
}
this.units = (json.units ?? []).map(((unitJson, i) => Unit.fromJson(unitJson, `${context}.unit[${i}]`))) this.units = (json.units ?? []).map(((unitJson, i) => Unit.fromJson(unitJson, `${context}.unit[${i}]`)))
if (json.description !== undefined) { if (json.description !== undefined) {

View file

@ -203,6 +203,8 @@ class LayerOverviewUtils {
const themePath = themeInfo.path const themePath = themeInfo.path
new PrevalidateTheme().convertStrict(themeFile, themePath) new PrevalidateTheme().convertStrict(themeFile, themePath)
try{
themeFile = new PrepareTheme(convertState).convertStrict(themeFile, themePath) themeFile = new PrepareTheme(convertState).convertStrict(themeFile, themePath)
if(knownImagePaths === undefined){ if(knownImagePaths === undefined){
@ -213,6 +215,10 @@ class LayerOverviewUtils {
this.writeTheme(themeFile) this.writeTheme(themeFile)
fixed.set(themeFile.id, themeFile) fixed.set(themeFile.id, themeFile)
}catch(e){
console.error("ERROR: could not prepare theme "+themePath+" due to "+e)
throw e;
}
} }
this.writeSmallOverview(themeFiles.map(tf => { this.writeSmallOverview(themeFiles.map(tf => {