Skip to content

Commit

Permalink
fix: 0-based error ranges (#8)
Browse files Browse the repository at this point in the history
* fix: error ranges are 0-based

* chore: update readme
  • Loading branch information
P0lip authored and XVincentX committed Mar 27, 2019
1 parent 3f5fa7c commit 15522ca
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 37 deletions.
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ yarn add @stoplight/yaml

### Usage

- **[parseWithPointers](https://stoplightio.github.io/yaml/globals.html#parsewithpointers)**: Parses YAML into JSON and also returns a source map that includes a JSON path pointer for every property in the result (with line information).
- **[getJsonPathForPosition](https://stoplightio.github.io/yaml/globals.html#getjsonpathforposition)**: Computes JSON path for given position.
- **[getLocationForJsonPath](https://stoplightio.github.io/yaml/globals.html#getlocationforjsonpath)**: Retrieves location of node matching given JSON path.
- **[parseWithPointers](https://stoplightio.github.io/yaml/globals.html#parsewithpointers)**: Parses YAML into JSON and also returns diagnostics as well as full ast with line information.

```ts
// basic example of parseWithPointers
Expand All @@ -27,7 +29,23 @@ import { parseWithPointers } from "@stoplight/yaml";
const result = parseWithPointers("foo: bar");

console.log(result.data); // => the {foo: "bar"} JS object
console.log(result.pointers); // => the source map with a single "#/foo" pointer that has position info for the foo property
```

```ts
// basic example of getJsonPathForPosition and getLocationForJsonPath
import { getJsonPathForPosition, getLocationForJsonPath, parseWithPointers } from "@stoplight/yaml";

const result = parseWithPointers(`hello: world
address:
street: 123`
);

const path = getJsonPathForPosition(result, { line: 2, character: 7 }); // line and character are 0-based
console.log(path); // -> ["address", "street"];

const position = getLocationForJsonPath(result, ['address']);
console.log(position.range.start); // { line: 1, character: 8 } line and character are 0-based
console.log(position.range.end); // { line: 2, character: 15 } line and character are 0-based
```

### Contributing
Expand Down
110 changes: 78 additions & 32 deletions src/__tests__/parseWithPointers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,45 +43,91 @@ describe('yaml parser', () => {
expect(result.data).toEqual(HugeJSON);
});

test('report errors', () => {
const result = parseWithPointers(
`prop1: true
describe('report errors', () => {
test('unknown tags', () => {
const result = parseWithPointers(`function: !!js/function >
function foobar() {
return 'Wow! JS-YAML Rocks!';
}
test: !!css >
function boom() {}
`);

expect(result).toHaveProperty('diagnostics', [
{
code: 'YAMLException',
message: 'unknown tag <tag:yaml.org,2002:js/function>',
range: {
end: {
character: 25,
line: 0,
},
start: {
character: 10,
line: 0,
},
},
severity: DiagnosticSeverity.Error,
},
{
code: 'YAMLException',
message: 'unknown tag <tag:yaml.org,2002:css>',
range: {
end: {
character: 13,
line: 5,
},
start: {
character: 6,
line: 5,
},
},
severity: DiagnosticSeverity.Error,
},
]);
});

test('invalid mapping', () => {
const result = parseWithPointers(
`prop1: true
prop2: true
inner 1
val: 2`
);
);

expect(result.diagnostics).toEqual([
{
severity: DiagnosticSeverity.Error,
message: 'bad indentation of a mapping entry',
code: 'YAMLException',
range: {
start: {
character: 5,
line: 2,
},
end: {
character: 5,
line: 2,
expect(result.diagnostics).toEqual([
{
severity: DiagnosticSeverity.Error,
message: 'bad indentation of a mapping entry',
code: 'YAMLException',
range: {
start: {
character: 5,
line: 3,
},
end: {
character: 5,
line: 3,
},
},
},
},
{
severity: DiagnosticSeverity.Error,
message: 'incomplete explicit mapping pair; a key node is missed',
code: 'YAMLException',
range: {
start: {
character: 7,
line: 2,
},
end: {
character: 7,
line: 2,
{
severity: DiagnosticSeverity.Error,
message: 'incomplete explicit mapping pair; a key node is missed',
code: 'YAMLException',
range: {
start: {
character: 7,
line: 3,
},
end: {
character: 7,
line: 3,
},
},
},
},
]);
]);
});
});
});
14 changes: 11 additions & 3 deletions src/parseWithPointers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ const computeLineMap = (input: string) => {
return lineMap;
};

function getLineLength(lineMap: number[], line: number) {
if (line === 0) {
return Math.max(0, lineMap[0] - 1);
}

return Math.max(0, lineMap[line] - lineMap[line - 1] - 1);
}

const transformErrors = (errors: YAMLException[], lineMap: number[]): IDiagnostic[] => {
const validations: IDiagnostic[] = [];
for (const error of errors) {
Expand All @@ -90,12 +98,12 @@ const transformErrors = (errors: YAMLException[], lineMap: number[]): IDiagnosti
severity: error.isWarning ? DiagnosticSeverity.Warning : DiagnosticSeverity.Error,
range: {
start: {
line: error.mark.line - 1,
line: error.mark.line,
character: error.mark.column,
},
end: {
line: error.mark.line - 1,
character: error.mark.toLineEnd ? lineMap[error.mark.line - 1] : error.mark.column,
line: error.mark.line,
character: error.mark.toLineEnd ? getLineLength(lineMap, error.mark.line) : error.mark.column,
},
},
};
Expand Down

0 comments on commit 15522ca

Please sign in to comment.