diff --git a/src/languageservice/services/validation/unused-anchors.ts b/src/languageservice/services/validation/unused-anchors.ts index 1f0b7619d..c451cc270 100644 --- a/src/languageservice/services/validation/unused-anchors.ts +++ b/src/languageservice/services/validation/unused-anchors.ts @@ -16,6 +16,7 @@ export class UnusedAnchorsValidator implements AdditionalValidator { const result = []; const anchors = new Set(); const usedAnchors = new Set(); + const unIdentifiedAlias = new Set(); const anchorParent = new Map(); visit(yamlDoc.internalDocument, (key, node, path) => { @@ -27,7 +28,11 @@ export class UnusedAnchorsValidator implements AdditionalValidator { anchorParent.set(node, path[path.length - 1] as Node); } if (isAlias(node)) { - usedAnchors.add(node.resolve(yamlDoc.internalDocument)); + if (!node.resolve(yamlDoc.internalDocument)) { + unIdentifiedAlias.add(node); + } else { + usedAnchors.add(node.resolve(yamlDoc.internalDocument)); + } } }); @@ -39,13 +44,29 @@ export class UnusedAnchorsValidator implements AdditionalValidator { document.positionAt(aToken.offset), document.positionAt(aToken.offset + aToken.source.length) ); - const warningDiagnostic = Diagnostic.create(range, `Unused anchor "${aToken.source}"`, DiagnosticSeverity.Hint, 0); + const warningDiagnostic = Diagnostic.create( + range, + `Unused anchor "${aToken.source}"`, + DiagnosticSeverity.Information, + 0 + ); warningDiagnostic.tags = [DiagnosticTag.Unnecessary]; result.push(warningDiagnostic); } } } + unIdentifiedAlias.forEach((node) => { + const nodeRange = node.range; + if (nodeRange) { + const startOffset = nodeRange[0]; + const endOffset = nodeRange[1]; + const range = Range.create(document.positionAt(startOffset), document.positionAt(endOffset)); + const warningDiagnostic = Diagnostic.create(range, `Unresolved alias "${node}"`, DiagnosticSeverity.Information, 0); + warningDiagnostic.tags = [DiagnosticTag.Unnecessary]; + result.push(warningDiagnostic); + } + }); return result; } private getAnchorNode(parentNode: YamlNode, node: Node): CST.SourceToken | undefined { diff --git a/test/utils/verifyError.ts b/test/utils/verifyError.ts index d2769c740..4b3dad96e 100644 --- a/test/utils/verifyError.ts +++ b/test/utils/verifyError.ts @@ -69,7 +69,7 @@ export function createUnusedAnchorDiagnostic( startCharacter, endLine, endCharacter, - DiagnosticSeverity.Hint, + DiagnosticSeverity.Information, 'YAML' ); diagnostic.tags = [DiagnosticTag.Unnecessary]; diff --git a/test/yamlValidation.test.ts b/test/yamlValidation.test.ts index 167bab86d..50ef5b886 100644 --- a/test/yamlValidation.test.ts +++ b/test/yamlValidation.test.ts @@ -84,7 +84,7 @@ some: ee: *g`; const result = await parseSetup(yaml); expect(result).is.not.empty; - expect(result.length).to.be.equal(4); + expect(result.length).to.be.equal(5); expect(result).to.include.deep.members([ createUnusedAnchorDiagnostic('Unused anchor "&bar"', 0, 5, 0, 9), createUnusedAnchorDiagnostic('Unused anchor "&a"', 4, 2, 4, 4), @@ -94,6 +94,16 @@ ee: *g`; }); }); + describe('Unresolved alias diagnostics', () => { + it('should report unresolved alias', async () => { + const yaml = 'foo: *bar'; + const result = await parseSetup(yaml); + expect(result).is.not.empty; + expect(result.length).to.be.equal(1); + expect(result[0]).deep.equal(createUnusedAnchorDiagnostic('Unresolved alias "*bar"', 0, 5, 0, 9)); + }); + }); + describe(`YAML styles test`, () => { it('should not report flow style', async () => { const yaml = `host: phl-42