You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
3.3 KiB
127 lines
3.3 KiB
const createCustomError = require('../utils/createCustomError'); |
|
const generate = require('../definition-syntax/generate'); |
|
const defaultLoc = { offset: 0, line: 1, column: 1 }; |
|
|
|
function locateMismatch(matchResult, node) { |
|
const tokens = matchResult.tokens; |
|
const longestMatch = matchResult.longestMatch; |
|
const mismatchNode = longestMatch < tokens.length ? tokens[longestMatch].node || null : null; |
|
const badNode = mismatchNode !== node ? mismatchNode : null; |
|
let mismatchOffset = 0; |
|
let mismatchLength = 0; |
|
let entries = 0; |
|
let css = ''; |
|
let start; |
|
let end; |
|
|
|
for (let i = 0; i < tokens.length; i++) { |
|
const token = tokens[i].value; |
|
|
|
if (i === longestMatch) { |
|
mismatchLength = token.length; |
|
mismatchOffset = css.length; |
|
} |
|
|
|
if (badNode !== null && tokens[i].node === badNode) { |
|
if (i <= longestMatch) { |
|
entries++; |
|
} else { |
|
entries = 0; |
|
} |
|
} |
|
|
|
css += token; |
|
} |
|
|
|
if (longestMatch === tokens.length || entries > 1) { // last |
|
start = fromLoc(badNode || node, 'end') || buildLoc(defaultLoc, css); |
|
end = buildLoc(start); |
|
} else { |
|
start = fromLoc(badNode, 'start') || |
|
buildLoc(fromLoc(node, 'start') || defaultLoc, css.slice(0, mismatchOffset)); |
|
end = fromLoc(badNode, 'end') || |
|
buildLoc(start, css.substr(mismatchOffset, mismatchLength)); |
|
} |
|
|
|
return { |
|
css, |
|
mismatchOffset, |
|
mismatchLength, |
|
start, |
|
end |
|
}; |
|
} |
|
|
|
function fromLoc(node, point) { |
|
const value = node && node.loc && node.loc[point]; |
|
|
|
if (value) { |
|
return 'line' in value ? buildLoc(value) : value; |
|
} |
|
|
|
return null; |
|
} |
|
|
|
function buildLoc({ offset, line, column }, extra) { |
|
const loc = { |
|
offset, |
|
line, |
|
column |
|
}; |
|
|
|
if (extra) { |
|
const lines = extra.split(/\n|\r\n?|\f/); |
|
|
|
loc.offset += extra.length; |
|
loc.line += lines.length - 1; |
|
loc.column = lines.length === 1 ? loc.column + extra.length : lines.pop().length + 1; |
|
} |
|
|
|
return loc; |
|
} |
|
|
|
const SyntaxReferenceError = function(type, referenceName) { |
|
const error = createCustomError( |
|
'SyntaxReferenceError', |
|
type + (referenceName ? ' `' + referenceName + '`' : '') |
|
); |
|
|
|
error.reference = referenceName; |
|
|
|
return error; |
|
}; |
|
|
|
const SyntaxMatchError = function(message, syntax, node, matchResult) { |
|
const error = createCustomError('SyntaxMatchError', message); |
|
const { |
|
css, |
|
mismatchOffset, |
|
mismatchLength, |
|
start, |
|
end |
|
} = locateMismatch(matchResult, node); |
|
|
|
error.rawMessage = message; |
|
error.syntax = syntax ? generate(syntax) : '<generic>'; |
|
error.css = css; |
|
error.mismatchOffset = mismatchOffset; |
|
error.mismatchLength = mismatchLength; |
|
error.message = message + '\n' + |
|
' syntax: ' + error.syntax + '\n' + |
|
' value: ' + (css || '<empty string>') + '\n' + |
|
' --------' + new Array(error.mismatchOffset + 1).join('-') + '^'; |
|
|
|
Object.assign(error, start); |
|
error.loc = { |
|
source: (node && node.loc && node.loc.source) || '<unknown>', |
|
start, |
|
end |
|
}; |
|
|
|
return error; |
|
}; |
|
|
|
module.exports = { |
|
SyntaxReferenceError, |
|
SyntaxMatchError |
|
};
|
|
|