Merge pull request #18334 from atom/mb-nested-language-comment-strings

Use the correct comment strings for nested languages
This commit is contained in:
Max Brunsfeld
2018-10-25 15:28:46 -07:00
committed by GitHub
3 changed files with 71 additions and 13 deletions

View File

@@ -1692,6 +1692,54 @@ describe('TreeSitterLanguageMode', () => {
})
})
describe('.commentStringsForPosition(position)', () => {
it('returns the correct comment strings for nested languages', () => {
const jsGrammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, {
scopeName: 'javascript',
parser: 'tree-sitter-javascript',
comments: {start: '//'},
injectionRegExp: 'javascript',
injectionPoints: [HTML_TEMPLATE_LITERAL_INJECTION_POINT]
})
const htmlGrammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, {
scopeName: 'html',
parser: 'tree-sitter-html',
scopes: {},
comments: {start: '<!--', end: '-->'},
injectionRegExp: 'html',
injectionPoints: [SCRIPT_TAG_INJECTION_POINT]
})
atom.grammars.addGrammar(jsGrammar)
atom.grammars.addGrammar(htmlGrammar)
const languageMode = new TreeSitterLanguageMode({buffer, grammar: htmlGrammar, grammars: atom.grammars})
buffer.setLanguageMode(languageMode)
buffer.setText(`
<div>hi</div>
<script>
const node = document.getElementById('some-id');
node.innerHTML = html \`
<span>bye</span>
\`
</script>
`.trim())
const htmlCommentStrings = {commentStartString: '<!--', commentEndString: '-->'}
const jsCommentStrings = {commentStartString: '//', commentEndString: undefined}
expect(languageMode.commentStringsForPosition(new Point(0, 0))).toEqual(htmlCommentStrings)
expect(languageMode.commentStringsForPosition(new Point(1, 0))).toEqual(htmlCommentStrings)
expect(languageMode.commentStringsForPosition(new Point(2, 0))).toEqual(jsCommentStrings)
expect(languageMode.commentStringsForPosition(new Point(3, 0))).toEqual(jsCommentStrings)
expect(languageMode.commentStringsForPosition(new Point(4, 0))).toEqual(htmlCommentStrings)
expect(languageMode.commentStringsForPosition(new Point(5, 0))).toEqual(jsCommentStrings)
expect(languageMode.commentStringsForPosition(new Point(6, 0))).toEqual(htmlCommentStrings)
})
})
describe('TextEditor.selectLargerSyntaxNode and .selectSmallerSyntaxNode', () => {
it('expands and contracts the selection based on the syntax tree', async () => {
const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, {

View File

@@ -4768,7 +4768,7 @@ class TextEditor {
const languageMode = this.buffer.getLanguageMode()
let {commentStartString, commentEndString} =
languageMode.commentStringsForPosition &&
languageMode.commentStringsForPosition(Point(start, 0)) || {}
languageMode.commentStringsForPosition(new Point(start, 0)) || {}
if (!commentStartString) return
commentStartString = commentStartString.trim()

View File

@@ -144,17 +144,16 @@ class TreeSitterLanguageMode {
Section - Commenting
*/
commentStringsForPosition () {
return this.grammar.commentStrings
commentStringsForPosition (position) {
const range = this.firstNonWhitespaceRange(position.row) || new Range(position, position)
const {grammar} = this.getSyntaxNodeAndGrammarContainingRange(range)
return grammar.commentStrings
}
isRowCommented (row) {
const firstNonWhitespaceRange = this.buffer.findInRangeSync(
/\S/,
new Range(new Point(row, 0), new Point(row, Infinity))
)
if (firstNonWhitespaceRange) {
const firstNode = this.getSyntaxNodeContainingRange(firstNonWhitespaceRange)
const range = this.firstNonWhitespaceRange(row)
if (range) {
const firstNode = this.getSyntaxNodeContainingRange(range)
if (firstNode) return firstNode.type.includes('comment')
}
return false
@@ -367,23 +366,31 @@ class TreeSitterLanguageMode {
*/
getSyntaxNodeContainingRange (range, where = _ => true) {
return this.getSyntaxNodeAndGrammarContainingRange(range, where).node
}
getSyntaxNodeAndGrammarContainingRange (range, where = _ => true) {
const startIndex = this.buffer.characterIndexForPosition(range.start)
const endIndex = this.buffer.characterIndexForPosition(range.end)
const searchEndIndex = Math.max(0, endIndex - 1)
let smallestNode
let smallestNode = null
let smallestNodeGrammar = this.grammar
this._forEachTreeWithRange(range, (tree, grammar) => {
let node = tree.rootNode.descendantForIndex(startIndex, searchEndIndex)
while (node) {
if (nodeContainsIndices(node, startIndex, endIndex) && where(node, grammar)) {
if (nodeIsSmaller(node, smallestNode)) smallestNode = node
if (nodeIsSmaller(node, smallestNode)) {
smallestNode = node
smallestNodeGrammar = grammar
}
break
}
node = node.parent
}
})
return smallestNode
return {node: smallestNode, grammar: smallestNodeGrammar}
}
getRangeForSyntaxNodeContainingRange (range, where) {
@@ -482,6 +489,10 @@ class TreeSitterLanguageMode {
Section - Private
*/
firstNonWhitespaceRange (row) {
return this.buffer.findInRangeSync(/\S/, new Range(new Point(row, 0), new Point(row, Infinity)))
}
grammarForLanguageString (languageString) {
return this.grammarRegistry.treeSitterGrammarForLanguageString(languageString)
}
@@ -599,7 +610,6 @@ class LanguageLayer {
params.async = true
tree = await tree
}
tree.buffer = this.languageMode.buffer
const changes = this.patchSinceCurrentParseStarted.getChanges()
this.patchSinceCurrentParseStarted = null