@codemirror/lang-javascript
Advanced tools
Comparing version 0.20.0 to 0.20.1
@@ -0,1 +1,7 @@ | ||
## 0.20.1 (2022-06-01) | ||
### New features | ||
`localCompletionSource` (included in the support extensions returned from `javascript`) now provides a way to complete locally-defined names. | ||
## 0.20.0 (2022-04-20) | ||
@@ -2,0 +8,0 @@ |
import * as _codemirror_state from '@codemirror/state'; | ||
import { LRLanguage, LanguageSupport } from '@codemirror/language'; | ||
import { Completion } from '@codemirror/autocomplete'; | ||
import { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete'; | ||
import { Diagnostic } from '@codemirror/lint'; | ||
@@ -61,2 +61,8 @@ import { EditorView } from '@codemirror/view'; | ||
export { autoCloseTags, esLint, javascript, javascriptLanguage, jsxLanguage, snippets, tsxLanguage, typescriptLanguage }; | ||
/** | ||
Completion source that looks up locally defined names in | ||
JavaScript code. | ||
*/ | ||
declare function localCompletionSource(context: CompletionContext): CompletionResult | null; | ||
export { autoCloseTags, esLint, javascript, javascriptLanguage, jsxLanguage, localCompletionSource, snippets, tsxLanguage, typescriptLanguage }; |
import { parser } from '@lezer/javascript'; | ||
import { LRLanguage, indentNodeProp, continuedIndent, flatIndent, delimitedIndent, foldNodeProp, foldInside, syntaxTree, LanguageSupport } from '@codemirror/language'; | ||
import { syntaxTree, LRLanguage, indentNodeProp, continuedIndent, flatIndent, delimitedIndent, foldNodeProp, foldInside, LanguageSupport } from '@codemirror/language'; | ||
import { EditorSelection } from '@codemirror/state'; | ||
import { EditorView } from '@codemirror/view'; | ||
import { snippetCompletion, ifNotIn, completeFromList } from '@codemirror/autocomplete'; | ||
import { NodeWeakMap, IterMode } from '@lezer/common'; | ||
@@ -49,3 +50,83 @@ /** | ||
const cache = /*@__PURE__*/new NodeWeakMap(); | ||
const ScopeNodes = /*@__PURE__*/new Set([ | ||
"Script", "Block", | ||
"FunctionExpression", "FunctionDeclaration", "ArrowFunction", "MethodDeclaration", | ||
"ForStatement" | ||
]); | ||
function defID(type) { | ||
return (node, def) => { | ||
let id = node.node.getChild("VariableDefinition"); | ||
if (id) | ||
def(id, type); | ||
return true; | ||
}; | ||
} | ||
const functionContext = ["FunctionDeclaration"]; | ||
const gatherCompletions = { | ||
FunctionDeclaration: /*@__PURE__*/defID("function"), | ||
ClassDeclaration: /*@__PURE__*/defID("class"), | ||
ClassExpression: () => true, | ||
EnumDeclaration: /*@__PURE__*/defID("constant"), | ||
TypeAliasDeclaration: /*@__PURE__*/defID("type"), | ||
NamespaceDeclaration: /*@__PURE__*/defID("namespace"), | ||
VariableDefinition(node, def) { if (!node.matchContext(functionContext)) | ||
def(node, "variable"); }, | ||
TypeDefinition(node, def) { def(node, "type"); }, | ||
__proto__: null | ||
}; | ||
function getScope(doc, node) { | ||
let cached = cache.get(node); | ||
if (cached) | ||
return cached; | ||
let completions = [], top = true; | ||
function def(node, type) { | ||
let name = doc.sliceString(node.from, node.to); | ||
completions.push({ label: name, type }); | ||
} | ||
node.cursor(IterMode.IncludeAnonymous).iterate(node => { | ||
if (top) { | ||
top = false; | ||
} | ||
else if (node.name) { | ||
let gather = gatherCompletions[node.name]; | ||
if (gather && gather(node, def) || ScopeNodes.has(node.name)) | ||
return false; | ||
} | ||
else if (node.to - node.from > 8192) { | ||
// Allow caching for bigger internal nodes | ||
for (let c of getScope(doc, node.node)) | ||
completions.push(c); | ||
return false; | ||
} | ||
}); | ||
cache.set(node, completions); | ||
return completions; | ||
} | ||
const Identifier = /^[\w$\xa1-\uffff][\w$\d\xa1-\uffff]*$/; | ||
/** | ||
Completion source that looks up locally defined names in | ||
JavaScript code. | ||
*/ | ||
function localCompletionSource(context) { | ||
let inner = syntaxTree(context.state).resolve(context.pos, -1); | ||
if (inner.name == "TemplateString" || inner.name == "String" || | ||
inner.name == "LineComment" || inner.name == "BlockComment") | ||
return null; | ||
let isWord = inner.to - inner.from < 20 && Identifier.test(context.state.sliceDoc(inner.from, inner.to)); | ||
if (!isWord && !context.explicit) | ||
return null; | ||
let options = []; | ||
for (let pos = inner; pos; pos = pos.parent) { | ||
if (ScopeNodes.has(pos.name)) | ||
options = options.concat(getScope(context.state.doc, pos)); | ||
} | ||
return { | ||
options, | ||
from: isWord ? inner.from : context.pos, | ||
validFor: Identifier | ||
}; | ||
} | ||
/** | ||
A language provider based on the [Lezer JavaScript | ||
@@ -118,2 +199,5 @@ parser](https://github.com/lezer-parser/javascript), extended with | ||
}), | ||
javascriptLanguage.data.of({ | ||
autocomplete: localCompletionSource | ||
}), | ||
config.jsx ? autoCloseTags : [], | ||
@@ -226,2 +310,2 @@ ]); | ||
export { autoCloseTags, esLint, javascript, javascriptLanguage, jsxLanguage, snippets, tsxLanguage, typescriptLanguage }; | ||
export { autoCloseTags, esLint, javascript, javascriptLanguage, jsxLanguage, localCompletionSource, snippets, tsxLanguage, typescriptLanguage }; |
{ | ||
"name": "@codemirror/lang-javascript", | ||
"version": "0.20.0", | ||
"version": "0.20.1", | ||
"description": "JavaScript language support for the CodeMirror code editor", | ||
@@ -34,2 +34,3 @@ "scripts": { | ||
"@codemirror/view": "^0.20.0", | ||
"@lezer/common": "^0.16.1", | ||
"@lezer/javascript": "^0.16.0" | ||
@@ -36,0 +37,0 @@ }, |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
37102
675
7
+ Added@lezer/common@^0.16.1