languageFeatures.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. import { Uri, Range, editor, languages, MarkerSeverity } from './fillers/monaco-editor-core.js';
  6. import * as jsonService from './_deps/vscode-json-languageservice/jsonLanguageService.js';
  7. // --- diagnostics --- ---
  8. var DiagnosticsAdapter = /** @class */ (function () {
  9. function DiagnosticsAdapter(_languageId, _worker, defaults) {
  10. var _this = this;
  11. this._languageId = _languageId;
  12. this._worker = _worker;
  13. this._disposables = [];
  14. this._listener = Object.create(null);
  15. var onModelAdd = function (model) {
  16. var modeId = model.getModeId();
  17. if (modeId !== _this._languageId) {
  18. return;
  19. }
  20. var handle;
  21. _this._listener[model.uri.toString()] = model.onDidChangeContent(function () {
  22. clearTimeout(handle);
  23. handle = setTimeout(function () { return _this._doValidate(model.uri, modeId); }, 500);
  24. });
  25. _this._doValidate(model.uri, modeId);
  26. };
  27. var onModelRemoved = function (model) {
  28. editor.setModelMarkers(model, _this._languageId, []);
  29. var uriStr = model.uri.toString();
  30. var listener = _this._listener[uriStr];
  31. if (listener) {
  32. listener.dispose();
  33. delete _this._listener[uriStr];
  34. }
  35. };
  36. this._disposables.push(editor.onDidCreateModel(onModelAdd));
  37. this._disposables.push(editor.onWillDisposeModel(function (model) {
  38. onModelRemoved(model);
  39. _this._resetSchema(model.uri);
  40. }));
  41. this._disposables.push(editor.onDidChangeModelLanguage(function (event) {
  42. onModelRemoved(event.model);
  43. onModelAdd(event.model);
  44. _this._resetSchema(event.model.uri);
  45. }));
  46. this._disposables.push(defaults.onDidChange(function (_) {
  47. editor.getModels().forEach(function (model) {
  48. if (model.getModeId() === _this._languageId) {
  49. onModelRemoved(model);
  50. onModelAdd(model);
  51. }
  52. });
  53. }));
  54. this._disposables.push({
  55. dispose: function () {
  56. editor.getModels().forEach(onModelRemoved);
  57. for (var key in _this._listener) {
  58. _this._listener[key].dispose();
  59. }
  60. }
  61. });
  62. editor.getModels().forEach(onModelAdd);
  63. }
  64. DiagnosticsAdapter.prototype.dispose = function () {
  65. this._disposables.forEach(function (d) { return d && d.dispose(); });
  66. this._disposables = [];
  67. };
  68. DiagnosticsAdapter.prototype._resetSchema = function (resource) {
  69. this._worker().then(function (worker) {
  70. worker.resetSchema(resource.toString());
  71. });
  72. };
  73. DiagnosticsAdapter.prototype._doValidate = function (resource, languageId) {
  74. this._worker(resource)
  75. .then(function (worker) {
  76. return worker.doValidation(resource.toString()).then(function (diagnostics) {
  77. var markers = diagnostics.map(function (d) { return toDiagnostics(resource, d); });
  78. var model = editor.getModel(resource);
  79. if (model && model.getModeId() === languageId) {
  80. editor.setModelMarkers(model, languageId, markers);
  81. }
  82. });
  83. })
  84. .then(undefined, function (err) {
  85. console.error(err);
  86. });
  87. };
  88. return DiagnosticsAdapter;
  89. }());
  90. export { DiagnosticsAdapter };
  91. function toSeverity(lsSeverity) {
  92. switch (lsSeverity) {
  93. case jsonService.DiagnosticSeverity.Error:
  94. return MarkerSeverity.Error;
  95. case jsonService.DiagnosticSeverity.Warning:
  96. return MarkerSeverity.Warning;
  97. case jsonService.DiagnosticSeverity.Information:
  98. return MarkerSeverity.Info;
  99. case jsonService.DiagnosticSeverity.Hint:
  100. return MarkerSeverity.Hint;
  101. default:
  102. return MarkerSeverity.Info;
  103. }
  104. }
  105. function toDiagnostics(resource, diag) {
  106. var code = typeof diag.code === 'number' ? String(diag.code) : diag.code;
  107. return {
  108. severity: toSeverity(diag.severity),
  109. startLineNumber: diag.range.start.line + 1,
  110. startColumn: diag.range.start.character + 1,
  111. endLineNumber: diag.range.end.line + 1,
  112. endColumn: diag.range.end.character + 1,
  113. message: diag.message,
  114. code: code,
  115. source: diag.source
  116. };
  117. }
  118. // --- completion ------
  119. function fromPosition(position) {
  120. if (!position) {
  121. return void 0;
  122. }
  123. return { character: position.column - 1, line: position.lineNumber - 1 };
  124. }
  125. function fromRange(range) {
  126. if (!range) {
  127. return void 0;
  128. }
  129. return {
  130. start: {
  131. line: range.startLineNumber - 1,
  132. character: range.startColumn - 1
  133. },
  134. end: { line: range.endLineNumber - 1, character: range.endColumn - 1 }
  135. };
  136. }
  137. function toRange(range) {
  138. if (!range) {
  139. return void 0;
  140. }
  141. return new Range(range.start.line + 1, range.start.character + 1, range.end.line + 1, range.end.character + 1);
  142. }
  143. function isInsertReplaceEdit(edit) {
  144. return (typeof edit.insert !== 'undefined' &&
  145. typeof edit.replace !== 'undefined');
  146. }
  147. function toCompletionItemKind(kind) {
  148. var mItemKind = languages.CompletionItemKind;
  149. switch (kind) {
  150. case jsonService.CompletionItemKind.Text:
  151. return mItemKind.Text;
  152. case jsonService.CompletionItemKind.Method:
  153. return mItemKind.Method;
  154. case jsonService.CompletionItemKind.Function:
  155. return mItemKind.Function;
  156. case jsonService.CompletionItemKind.Constructor:
  157. return mItemKind.Constructor;
  158. case jsonService.CompletionItemKind.Field:
  159. return mItemKind.Field;
  160. case jsonService.CompletionItemKind.Variable:
  161. return mItemKind.Variable;
  162. case jsonService.CompletionItemKind.Class:
  163. return mItemKind.Class;
  164. case jsonService.CompletionItemKind.Interface:
  165. return mItemKind.Interface;
  166. case jsonService.CompletionItemKind.Module:
  167. return mItemKind.Module;
  168. case jsonService.CompletionItemKind.Property:
  169. return mItemKind.Property;
  170. case jsonService.CompletionItemKind.Unit:
  171. return mItemKind.Unit;
  172. case jsonService.CompletionItemKind.Value:
  173. return mItemKind.Value;
  174. case jsonService.CompletionItemKind.Enum:
  175. return mItemKind.Enum;
  176. case jsonService.CompletionItemKind.Keyword:
  177. return mItemKind.Keyword;
  178. case jsonService.CompletionItemKind.Snippet:
  179. return mItemKind.Snippet;
  180. case jsonService.CompletionItemKind.Color:
  181. return mItemKind.Color;
  182. case jsonService.CompletionItemKind.File:
  183. return mItemKind.File;
  184. case jsonService.CompletionItemKind.Reference:
  185. return mItemKind.Reference;
  186. }
  187. return mItemKind.Property;
  188. }
  189. function fromCompletionItemKind(kind) {
  190. var mItemKind = languages.CompletionItemKind;
  191. switch (kind) {
  192. case mItemKind.Text:
  193. return jsonService.CompletionItemKind.Text;
  194. case mItemKind.Method:
  195. return jsonService.CompletionItemKind.Method;
  196. case mItemKind.Function:
  197. return jsonService.CompletionItemKind.Function;
  198. case mItemKind.Constructor:
  199. return jsonService.CompletionItemKind.Constructor;
  200. case mItemKind.Field:
  201. return jsonService.CompletionItemKind.Field;
  202. case mItemKind.Variable:
  203. return jsonService.CompletionItemKind.Variable;
  204. case mItemKind.Class:
  205. return jsonService.CompletionItemKind.Class;
  206. case mItemKind.Interface:
  207. return jsonService.CompletionItemKind.Interface;
  208. case mItemKind.Module:
  209. return jsonService.CompletionItemKind.Module;
  210. case mItemKind.Property:
  211. return jsonService.CompletionItemKind.Property;
  212. case mItemKind.Unit:
  213. return jsonService.CompletionItemKind.Unit;
  214. case mItemKind.Value:
  215. return jsonService.CompletionItemKind.Value;
  216. case mItemKind.Enum:
  217. return jsonService.CompletionItemKind.Enum;
  218. case mItemKind.Keyword:
  219. return jsonService.CompletionItemKind.Keyword;
  220. case mItemKind.Snippet:
  221. return jsonService.CompletionItemKind.Snippet;
  222. case mItemKind.Color:
  223. return jsonService.CompletionItemKind.Color;
  224. case mItemKind.File:
  225. return jsonService.CompletionItemKind.File;
  226. case mItemKind.Reference:
  227. return jsonService.CompletionItemKind.Reference;
  228. }
  229. return jsonService.CompletionItemKind.Property;
  230. }
  231. function toTextEdit(textEdit) {
  232. if (!textEdit) {
  233. return void 0;
  234. }
  235. return {
  236. range: toRange(textEdit.range),
  237. text: textEdit.newText
  238. };
  239. }
  240. function toCommand(c) {
  241. return c && c.command === 'editor.action.triggerSuggest' ? { id: c.command, title: c.title, arguments: c.arguments } : undefined;
  242. }
  243. var CompletionAdapter = /** @class */ (function () {
  244. function CompletionAdapter(_worker) {
  245. this._worker = _worker;
  246. }
  247. Object.defineProperty(CompletionAdapter.prototype, "triggerCharacters", {
  248. get: function () {
  249. return [' ', ':', '"'];
  250. },
  251. enumerable: false,
  252. configurable: true
  253. });
  254. CompletionAdapter.prototype.provideCompletionItems = function (model, position, context, token) {
  255. var resource = model.uri;
  256. return this._worker(resource)
  257. .then(function (worker) {
  258. return worker.doComplete(resource.toString(), fromPosition(position));
  259. })
  260. .then(function (info) {
  261. if (!info) {
  262. return;
  263. }
  264. var wordInfo = model.getWordUntilPosition(position);
  265. var wordRange = new Range(position.lineNumber, wordInfo.startColumn, position.lineNumber, wordInfo.endColumn);
  266. var items = info.items.map(function (entry) {
  267. var item = {
  268. label: entry.label,
  269. insertText: entry.insertText || entry.label,
  270. sortText: entry.sortText,
  271. filterText: entry.filterText,
  272. documentation: entry.documentation,
  273. detail: entry.detail,
  274. command: toCommand(entry.command),
  275. range: wordRange,
  276. kind: toCompletionItemKind(entry.kind)
  277. };
  278. if (entry.textEdit) {
  279. if (isInsertReplaceEdit(entry.textEdit)) {
  280. item.range = {
  281. insert: toRange(entry.textEdit.insert),
  282. replace: toRange(entry.textEdit.replace)
  283. };
  284. }
  285. else {
  286. item.range = toRange(entry.textEdit.range);
  287. }
  288. item.insertText = entry.textEdit.newText;
  289. }
  290. if (entry.additionalTextEdits) {
  291. item.additionalTextEdits = entry.additionalTextEdits.map(toTextEdit);
  292. }
  293. if (entry.insertTextFormat === jsonService.InsertTextFormat.Snippet) {
  294. item.insertTextRules = languages.CompletionItemInsertTextRule.InsertAsSnippet;
  295. }
  296. return item;
  297. });
  298. return {
  299. isIncomplete: info.isIncomplete,
  300. suggestions: items
  301. };
  302. });
  303. };
  304. return CompletionAdapter;
  305. }());
  306. export { CompletionAdapter };
  307. function isMarkupContent(thing) {
  308. return (thing &&
  309. typeof thing === 'object' &&
  310. typeof thing.kind === 'string');
  311. }
  312. function toMarkdownString(entry) {
  313. if (typeof entry === 'string') {
  314. return {
  315. value: entry
  316. };
  317. }
  318. if (isMarkupContent(entry)) {
  319. if (entry.kind === 'plaintext') {
  320. return {
  321. value: entry.value.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&')
  322. };
  323. }
  324. return {
  325. value: entry.value
  326. };
  327. }
  328. return { value: '```' + entry.language + '\n' + entry.value + '\n```\n' };
  329. }
  330. function toMarkedStringArray(contents) {
  331. if (!contents) {
  332. return void 0;
  333. }
  334. if (Array.isArray(contents)) {
  335. return contents.map(toMarkdownString);
  336. }
  337. return [toMarkdownString(contents)];
  338. }
  339. // --- hover ------
  340. var HoverAdapter = /** @class */ (function () {
  341. function HoverAdapter(_worker) {
  342. this._worker = _worker;
  343. }
  344. HoverAdapter.prototype.provideHover = function (model, position, token) {
  345. var resource = model.uri;
  346. return this._worker(resource)
  347. .then(function (worker) {
  348. return worker.doHover(resource.toString(), fromPosition(position));
  349. })
  350. .then(function (info) {
  351. if (!info) {
  352. return;
  353. }
  354. return {
  355. range: toRange(info.range),
  356. contents: toMarkedStringArray(info.contents)
  357. };
  358. });
  359. };
  360. return HoverAdapter;
  361. }());
  362. export { HoverAdapter };
  363. // --- definition ------
  364. function toLocation(location) {
  365. return {
  366. uri: Uri.parse(location.uri),
  367. range: toRange(location.range)
  368. };
  369. }
  370. // --- document symbols ------
  371. function toSymbolKind(kind) {
  372. var mKind = languages.SymbolKind;
  373. switch (kind) {
  374. case jsonService.SymbolKind.File:
  375. return mKind.Array;
  376. case jsonService.SymbolKind.Module:
  377. return mKind.Module;
  378. case jsonService.SymbolKind.Namespace:
  379. return mKind.Namespace;
  380. case jsonService.SymbolKind.Package:
  381. return mKind.Package;
  382. case jsonService.SymbolKind.Class:
  383. return mKind.Class;
  384. case jsonService.SymbolKind.Method:
  385. return mKind.Method;
  386. case jsonService.SymbolKind.Property:
  387. return mKind.Property;
  388. case jsonService.SymbolKind.Field:
  389. return mKind.Field;
  390. case jsonService.SymbolKind.Constructor:
  391. return mKind.Constructor;
  392. case jsonService.SymbolKind.Enum:
  393. return mKind.Enum;
  394. case jsonService.SymbolKind.Interface:
  395. return mKind.Interface;
  396. case jsonService.SymbolKind.Function:
  397. return mKind.Function;
  398. case jsonService.SymbolKind.Variable:
  399. return mKind.Variable;
  400. case jsonService.SymbolKind.Constant:
  401. return mKind.Constant;
  402. case jsonService.SymbolKind.String:
  403. return mKind.String;
  404. case jsonService.SymbolKind.Number:
  405. return mKind.Number;
  406. case jsonService.SymbolKind.Boolean:
  407. return mKind.Boolean;
  408. case jsonService.SymbolKind.Array:
  409. return mKind.Array;
  410. }
  411. return mKind.Function;
  412. }
  413. var DocumentSymbolAdapter = /** @class */ (function () {
  414. function DocumentSymbolAdapter(_worker) {
  415. this._worker = _worker;
  416. }
  417. DocumentSymbolAdapter.prototype.provideDocumentSymbols = function (model, token) {
  418. var resource = model.uri;
  419. return this._worker(resource)
  420. .then(function (worker) { return worker.findDocumentSymbols(resource.toString()); })
  421. .then(function (items) {
  422. if (!items) {
  423. return;
  424. }
  425. return items.map(function (item) { return ({
  426. name: item.name,
  427. detail: '',
  428. containerName: item.containerName,
  429. kind: toSymbolKind(item.kind),
  430. range: toRange(item.location.range),
  431. selectionRange: toRange(item.location.range),
  432. tags: []
  433. }); });
  434. });
  435. };
  436. return DocumentSymbolAdapter;
  437. }());
  438. export { DocumentSymbolAdapter };
  439. function fromFormattingOptions(options) {
  440. return {
  441. tabSize: options.tabSize,
  442. insertSpaces: options.insertSpaces
  443. };
  444. }
  445. var DocumentFormattingEditProvider = /** @class */ (function () {
  446. function DocumentFormattingEditProvider(_worker) {
  447. this._worker = _worker;
  448. }
  449. DocumentFormattingEditProvider.prototype.provideDocumentFormattingEdits = function (model, options, token) {
  450. var resource = model.uri;
  451. return this._worker(resource).then(function (worker) {
  452. return worker
  453. .format(resource.toString(), null, fromFormattingOptions(options))
  454. .then(function (edits) {
  455. if (!edits || edits.length === 0) {
  456. return;
  457. }
  458. return edits.map(toTextEdit);
  459. });
  460. });
  461. };
  462. return DocumentFormattingEditProvider;
  463. }());
  464. export { DocumentFormattingEditProvider };
  465. var DocumentRangeFormattingEditProvider = /** @class */ (function () {
  466. function DocumentRangeFormattingEditProvider(_worker) {
  467. this._worker = _worker;
  468. }
  469. DocumentRangeFormattingEditProvider.prototype.provideDocumentRangeFormattingEdits = function (model, range, options, token) {
  470. var resource = model.uri;
  471. return this._worker(resource).then(function (worker) {
  472. return worker
  473. .format(resource.toString(), fromRange(range), fromFormattingOptions(options))
  474. .then(function (edits) {
  475. if (!edits || edits.length === 0) {
  476. return;
  477. }
  478. return edits.map(toTextEdit);
  479. });
  480. });
  481. };
  482. return DocumentRangeFormattingEditProvider;
  483. }());
  484. export { DocumentRangeFormattingEditProvider };
  485. var DocumentColorAdapter = /** @class */ (function () {
  486. function DocumentColorAdapter(_worker) {
  487. this._worker = _worker;
  488. }
  489. DocumentColorAdapter.prototype.provideDocumentColors = function (model, token) {
  490. var resource = model.uri;
  491. return this._worker(resource)
  492. .then(function (worker) { return worker.findDocumentColors(resource.toString()); })
  493. .then(function (infos) {
  494. if (!infos) {
  495. return;
  496. }
  497. return infos.map(function (item) { return ({
  498. color: item.color,
  499. range: toRange(item.range)
  500. }); });
  501. });
  502. };
  503. DocumentColorAdapter.prototype.provideColorPresentations = function (model, info, token) {
  504. var resource = model.uri;
  505. return this._worker(resource)
  506. .then(function (worker) {
  507. return worker.getColorPresentations(resource.toString(), info.color, fromRange(info.range));
  508. })
  509. .then(function (presentations) {
  510. if (!presentations) {
  511. return;
  512. }
  513. return presentations.map(function (presentation) {
  514. var item = {
  515. label: presentation.label
  516. };
  517. if (presentation.textEdit) {
  518. item.textEdit = toTextEdit(presentation.textEdit);
  519. }
  520. if (presentation.additionalTextEdits) {
  521. item.additionalTextEdits = presentation.additionalTextEdits.map(toTextEdit);
  522. }
  523. return item;
  524. });
  525. });
  526. };
  527. return DocumentColorAdapter;
  528. }());
  529. export { DocumentColorAdapter };
  530. var FoldingRangeAdapter = /** @class */ (function () {
  531. function FoldingRangeAdapter(_worker) {
  532. this._worker = _worker;
  533. }
  534. FoldingRangeAdapter.prototype.provideFoldingRanges = function (model, context, token) {
  535. var resource = model.uri;
  536. return this._worker(resource)
  537. .then(function (worker) { return worker.getFoldingRanges(resource.toString(), context); })
  538. .then(function (ranges) {
  539. if (!ranges) {
  540. return;
  541. }
  542. return ranges.map(function (range) {
  543. var result = {
  544. start: range.startLine + 1,
  545. end: range.endLine + 1
  546. };
  547. if (typeof range.kind !== 'undefined') {
  548. result.kind = toFoldingRangeKind(range.kind);
  549. }
  550. return result;
  551. });
  552. });
  553. };
  554. return FoldingRangeAdapter;
  555. }());
  556. export { FoldingRangeAdapter };
  557. function toFoldingRangeKind(kind) {
  558. switch (kind) {
  559. case jsonService.FoldingRangeKind.Comment:
  560. return languages.FoldingRangeKind.Comment;
  561. case jsonService.FoldingRangeKind.Imports:
  562. return languages.FoldingRangeKind.Imports;
  563. case jsonService.FoldingRangeKind.Region:
  564. return languages.FoldingRangeKind.Region;
  565. }
  566. return void 0;
  567. }
  568. var SelectionRangeAdapter = /** @class */ (function () {
  569. function SelectionRangeAdapter(_worker) {
  570. this._worker = _worker;
  571. }
  572. SelectionRangeAdapter.prototype.provideSelectionRanges = function (model, positions, token) {
  573. var resource = model.uri;
  574. return this._worker(resource)
  575. .then(function (worker) { return worker.getSelectionRanges(resource.toString(), positions.map(fromPosition)); })
  576. .then(function (selectionRanges) {
  577. if (!selectionRanges) {
  578. return;
  579. }
  580. return selectionRanges.map(function (selectionRange) {
  581. var result = [];
  582. while (selectionRange) {
  583. result.push({ range: toRange(selectionRange.range) });
  584. selectionRange = selectionRange.parent;
  585. }
  586. return result;
  587. });
  588. });
  589. };
  590. return SelectionRangeAdapter;
  591. }());
  592. export { SelectionRangeAdapter };