diff --git a/package.json b/package.json index 6593b4f..21c26ed 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "test.watch": "yarn test --watch" }, "dependencies": { - "@stoplight/types": "4.x.x", + "@stoplight/types": "5.x.x", "lodash": "4.x.x", "yaml-ast-parser": "0.0.43" }, diff --git a/src/__tests__/getJsonPathForPosition.spec.ts b/src/__tests__/getJsonPathForPosition.spec.ts index 1a828bc..298a88d 100644 --- a/src/__tests__/getJsonPathForPosition.spec.ts +++ b/src/__tests__/getJsonPathForPosition.spec.ts @@ -36,7 +36,7 @@ describe('getJsonPathForPosition', () => { test.each` line | character | path ${0} | ${0} | ${['hello']} - ${0} | ${13} | ${undefined} + ${0} | ${13} | ${void 0} ${0} | ${4} | ${['hello']} ${1} | ${0} | ${['address']} ${1} | ${7} | ${['address']} @@ -62,7 +62,7 @@ describe('getJsonPathForPosition', () => { ${12} | ${51} | ${['map', 'Flow style', 'Oren']} ${12} | ${52} | ${['map', 'Flow style', 'Oren']} ${12} | ${57} | ${['map', 'Flow style', 'Oren']} - ${13} | ${0} | ${undefined} + ${13} | ${0} | ${void 0} ${19} | ${0} | ${['omap', 'Bestiary', 0, 'aardvark']} ${19} | ${10} | ${['omap', 'Bestiary', 0, 'aardvark']} ${19} | ${32} | ${['omap', 'Bestiary', 0, 'aardvark']} @@ -88,7 +88,7 @@ describe('getJsonPathForPosition', () => { ${63} | ${31} | ${['seq', 'Flow style', 5]} ${63} | ${42} | ${['seq', 'Flow style', 6]} ${63} | ${50} | ${['seq', 'Flow style', 7]} - ${66} | ${0} | ${undefined} + ${66} | ${0} | ${void 0} ${138} | ${0} | ${['null', '~']} ${202} | ${12} | ${['foobar']} ${204} | ${7} | ${['foobar', 1]} diff --git a/src/__tests__/getLocationForJsonPath.spec.ts b/src/__tests__/getLocationForJsonPath.spec.ts index 9912c77..2ec493e 100644 --- a/src/__tests__/getLocationForJsonPath.spec.ts +++ b/src/__tests__/getLocationForJsonPath.spec.ts @@ -14,30 +14,39 @@ describe('getLocationForJsonPath', () => { const result = parseWithPointers(petStore); test.each` - start | end | path - ${[9, 10]} | ${[10, 29]} | ${['info', 'contact']} - ${[10, 11]} | ${[10, 29]} | ${['info', 'contact', 'email']} - ${[9, 10]} | ${[10, 29]} | ${['info', 'contact', 'dasdas']} - ${[29, 8]} | ${[31, 8]} | ${['schemes']} - ${[32, 6]} | ${[104, 23]} | ${['paths']} - ${[40, 15]} | ${[42, 25]} | ${['paths', '/pets', 'post', 'consumes']} - ${[41, 10]} | ${[41, 26]} | ${['paths', '/pets', 'post', 'consumes', 0]} - ${[41, 10]} | ${[41, 26]} | ${['paths', '/pets', 'post', 'consumes', '0']} - ${[60, 8]} | ${[71, 60]} | ${['paths', '/pets', 'get']} - ${[62, 14]} | ${[66, 26]} | ${['paths', '/pets', 'get', 'responses', '200']} - `('should return proper location for given JSONPath $path', ({ start, end, path }) => { - expect(getLocationForJsonPath(result, path)).toEqual({ - range: { - start: { - character: start[1], - line: start[0], - }, - end: { - character: end[1], - line: end[0], - }, - }, - }); + start | end | path | closest + ${[9, 10]} | ${[10, 29]} | ${['info', 'contact']} | ${false} + ${[10, 11]} | ${[10, 29]} | ${['info', 'contact', 'email']} | ${false} + ${[9, 10]} | ${[10, 29]} | ${['info', 'contact', 'dasdas']} | ${true} + ${[]} | ${[]} | ${['info', 'contact', 'dasdas']} | ${false} + ${[29, 8]} | ${[31, 8]} | ${['schemes']} | ${false} + ${[32, 6]} | ${[104, 23]} | ${['paths']} | ${false} + ${[40, 15]} | ${[42, 25]} | ${['paths', '/pets', 'post', 'consumes']} | ${false} + ${[40, 15]} | ${[42, 25]} | ${['paths', '/pets', 'post', 'consumes', 5]} | ${true} + ${[]} | ${[]} | ${['paths', '/pets', 'post', 'consumes', 5]} | ${false} + ${[41, 10]} | ${[41, 26]} | ${['paths', '/pets', 'post', 'consumes', 0]} | ${false} + ${[41, 10]} | ${[41, 26]} | ${['paths', '/pets', 'post', 'consumes', 0, 1]} | ${true} + ${[]} | ${[]} | ${['paths', '/pets', 'post', 'consumes', 0, 1]} | ${false} + ${[41, 10]} | ${[41, 26]} | ${['paths', '/pets', 'post', 'consumes', '0']} | ${false} + ${[60, 8]} | ${[71, 60]} | ${['paths', '/pets', 'get']} | ${false} + ${[62, 14]} | ${[66, 26]} | ${['paths', '/pets', 'get', 'responses', '200']} | ${false} + `('should return proper location for given JSONPath $path', ({ start, end, path, closest }) => { + expect(getLocationForJsonPath(result, path, closest)).toEqual( + start.length > 0 && end.length > 0 + ? { + range: { + start: { + character: start[1], + line: start[0], + }, + end: { + character: end[1], + line: end[0], + }, + }, + } + : void 0 + ); }); }); diff --git a/src/getLocationForJsonPath.ts b/src/getLocationForJsonPath.ts index 022baea..6c83286 100644 --- a/src/getLocationForJsonPath.ts +++ b/src/getLocationForJsonPath.ts @@ -2,9 +2,13 @@ import { GetLocationForJsonPath, ILocation, JsonPath } from '@stoplight/types'; import { Kind, YAMLNode, YAMLSequence } from 'yaml-ast-parser'; import { lineForPosition } from './lineForPosition'; -export const getLocationForJsonPath: GetLocationForJsonPath = ({ ast, lineMap }, path) => { - const node = findNodeAtPath(ast, path); - if (node === undefined) return; +export const getLocationForJsonPath: GetLocationForJsonPath = ( + { ast, lineMap }, + path, + closest = false +) => { + const node = findNodeAtPath(ast, path, closest); + if (node === void 0) return; return getLoc(lineMap, { start: getStartPosition(node), end: getEndPosition(node) }); }; @@ -55,7 +59,7 @@ function getEndPosition(node: YAMLNode): number { return node.endPosition; } -function findNodeAtPath(node: YAMLNode, path: JsonPath) { +function findNodeAtPath(node: YAMLNode, path: JsonPath, closest: boolean) { pathLoop: for (const segment of path) { switch (node && node.kind) { case Kind.MAP: @@ -69,7 +73,8 @@ function findNodeAtPath(node: YAMLNode, path: JsonPath) { continue pathLoop; } } - break; + + return closest ? node : void 0; case Kind.SEQ: for (let i = 0; i < (node as YAMLSequence).items.length; i++) { if (i === Number(segment)) { @@ -77,7 +82,10 @@ function findNodeAtPath(node: YAMLNode, path: JsonPath) { continue pathLoop; } } - break; + + return closest ? node : void 0; + default: + return closest ? node : void 0; } } diff --git a/src/parseWithPointers.ts b/src/parseWithPointers.ts index 6f8e00d..aa6bc57 100644 --- a/src/parseWithPointers.ts +++ b/src/parseWithPointers.ts @@ -50,7 +50,7 @@ const walk = (node: YAMLNode | null): unknown => { case Kind.SCALAR: return 'valueObject' in node ? node.valueObject : node.value; case Kind.ANCHOR_REF: - if (node.value !== undefined && isCircularAnchorRef(node as YAMLAnchorReference)) { + if (node.value !== void 0 && isCircularAnchorRef(node as YAMLAnchorReference)) { node.value = dereferenceAnchor(node.value, (node as YAMLAnchorReference).referencesAnchor); } diff --git a/yarn.lock b/yarn.lock index 7b7943c..33734ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1252,10 +1252,10 @@ typedoc "0.13.x" typescript-plugin-styled-components "1.0.x" -"@stoplight/types@4.x.x": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-4.0.0.tgz#04669b13f4de54e0446392167087cd6a9a570556" - integrity sha512-xh7STKNeE7j4Z6w8vkw+QxSCaxhF5+c2mY7UBqT6BMiom/Ep/EdYmYq3dmvYfXqwbkiTMR6qbYymwqnoJo8Z6w== +"@stoplight/types@5.x.x": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-5.1.0.tgz#33fb18d8927e2538b2f0b19edc076d6f7e3a9978" + integrity sha512-GKOcgmwDMJyg09WmI4irIiq7d32hwlqyrdAqpV4b/Eg6/XT2e3g8spguiOsQKIqQSvZqSrrfpGWn/ENCPBvFEA== "@storybook/addon-actions@4.0.11": version "4.0.11"