fix(lsp): ignore diagnostic check within code blocks (#399)

Co-authored-by: tjex <tjex@tjex.net>
pull/398/head^2
Tadeas Uhlir 4 weeks ago committed by GitHub
parent 05c50a70d5
commit c9d4734d3c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -160,10 +160,6 @@ func (d *document) LookForward(pos protocol.Position, length int) string {
return string(utf16.Decode(utf16Bytes[charIdx:(charIdx + length)]))
}
var wikiLinkRegex = regexp.MustCompile(`\[?\[\[(.+?)(?: *\| *(.+?))?\]\]`)
var markdownLinkRegex = regexp.MustCompile(`\[([^\]]+?[^\\])\]\((.+?[^\\])\)`)
var fileURIregex = regexp.MustCompile(`file:///`)
// LinkFromRoot returns a Link to this document from the root of the given
// notebook.
func (d *document) LinkFromRoot(nb *core.Notebook) (*documentLink, error) {
@ -194,6 +190,66 @@ func (d *document) DocumentLinkAt(pos protocol.Position) (*documentLink, error)
return nil, nil
}
// Recursive function to check whether a link is within inline code.
func linkWithinInlineCode(strBuffer string, linkStart, linkEnd int, insideInline bool) bool {
if backtickId := strings.Index(strBuffer, "`"); backtickId >= 0 && backtickId < linkEnd {
return linkWithinInlineCode(strBuffer[backtickId+1:],
linkStart-backtickId-1, linkEnd-backtickId-1, !insideInline)
} else {
return insideInline
}
}
var wikiLinkRegex = regexp.MustCompile(`\[?\[\[(.+?)(?: *\| *(.+?))?\]\]`)
var markdownLinkRegex = regexp.MustCompile(`\[([^\]]+?[^\\])\]\((.+?[^\\])\)`)
var fileURIregex = regexp.MustCompile(`file:///`)
var fencedStartRegex = regexp.MustCompile(`^(` + "```" + `|~~~).*`)
var fencedEndRegex = regexp.MustCompile(`^(` + "```" + `|~~~)\s*`)
var indentedRegex = regexp.MustCompile(`^(\s{4}|\t).+`)
var insideInline = false
var insideFenced = false
var insideIndented = false
var currentCodeBlockStart = -1
// check whether the current line in document is within a fenced or indented
// code block
func isLineWithinCodeBlock(lines []string, lineIndex int, line string) bool {
// if line is already within code fences or indented code block
if insideFenced {
if fencedEndRegex.FindStringIndex(line) != nil &&
lines[currentCodeBlockStart][:3] == line[:3] {
// Fenced code block ends with this line
insideFenced = false
currentCodeBlockStart = -1
}
return true
} else if insideIndented {
if indentedRegex.FindStringIndex(line) == nil && len(line) > 0 {
// Indeted code block ends with this line
insideIndented = false
currentCodeBlockStart = -1
} else {
return true
}
} else {
// Check whether the current line is the start of a code fence or
// indented code block
if fencedStartRegex.FindStringIndex(line) != nil {
insideFenced = true
currentCodeBlockStart = lineIndex
return true
} else if indentedRegex.FindStringIndex(line) != nil &&
(lineIndex > 0 && len(lines[lineIndex-1]) == 0 || lineIndex == 0) {
insideIndented = true
currentCodeBlockStart = lineIndex
return true
}
}
return false
}
// DocumentLinks returns all the internal and external links found in the
// document.
func (d *document) DocumentLinks() ([]documentLink, error) {
@ -202,6 +258,10 @@ func (d *document) DocumentLinks() ([]documentLink, error) {
lines := d.GetLines()
for lineIndex, line := range lines {
if isLineWithinCodeBlock(lines, lineIndex, line) {
continue
}
appendLink := func(href string, start, end int, hasTitle bool, isWikiLink bool) {
if href == "" {
return
@ -233,6 +293,10 @@ func (d *document) DocumentLinks() ([]documentLink, error) {
// note: match[0:1] is the entire match, match[2:3] is the contents of
// brackets, match[4:5] is contents of parentheses
for _, match := range markdownLinkRegex.FindAllStringSubmatchIndex(line, -1) {
// Ignore when inside backticks: `[title](file)`
if linkWithinInlineCode(line, match[0], match[1], insideInline) {
continue
}
// Ignore embedded images ![title](file.png)
if match[0] > 0 && line[match[0]-1] == '!' {
@ -259,10 +323,17 @@ func (d *document) DocumentLinks() ([]documentLink, error) {
}
for _, match := range wikiLinkRegex.FindAllStringSubmatchIndex(line, -1) {
// Ignore when inside backticks: `[[filename]]`
if linkWithinInlineCode(line, match[0], match[1], insideInline) {
continue
}
href := line[match[2]:match[3]]
hasTitle := match[4] != -1
appendLink(href, match[0], match[1], hasTitle, true)
}
if strings.Count(line, "`")%2 == 1 {
insideInline = !insideInline
}
}
return links, nil

Loading…
Cancel
Save