CompletionItemProvider.ts 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
  2. import type { Monaco, monacoTypes } from '@grafana/ui';
  3. import { CloudWatchDatasource } from '../datasource';
  4. import { LinkedToken } from './LinkedToken';
  5. import { linkedTokenBuilder } from './linkedTokenBuilder';
  6. import { LanguageDefinition } from './register';
  7. import { Completeable, StatementPosition, SuggestionKind, TokenTypes } from './types';
  8. type CompletionItem = monacoTypes.languages.CompletionItem;
  9. /*
  10. CompletionItemProvider is an extendable class which needs to implement :
  11. - tokenTypes
  12. - getStatementPosition
  13. - getSuggestionKinds
  14. - getSuggestions
  15. */
  16. export class CompletionItemProvider implements Completeable {
  17. templateVariables: string[];
  18. datasource: CloudWatchDatasource;
  19. templateSrv: TemplateSrv;
  20. tokenTypes: TokenTypes;
  21. constructor(datasource: CloudWatchDatasource, templateSrv: TemplateSrv = getTemplateSrv()) {
  22. this.datasource = datasource;
  23. this.templateSrv = templateSrv;
  24. this.templateVariables = this.datasource.getVariables();
  25. this.templateSrv = templateSrv;
  26. // implement with more specific tokens when extending this class
  27. this.tokenTypes = {
  28. Parenthesis: 'delimiter.parenthesis',
  29. Whitespace: 'white',
  30. Keyword: 'keyword',
  31. Delimiter: 'delimiter',
  32. Operator: 'operator',
  33. Identifier: 'identifier',
  34. Type: 'type',
  35. Function: 'predefined',
  36. Number: 'number',
  37. String: 'string',
  38. Variable: 'variable',
  39. };
  40. }
  41. // implemented by subclasses, given a token, returns a lexical position in a query
  42. getStatementPosition(currentToken: LinkedToken | null): StatementPosition {
  43. return StatementPosition.Unknown;
  44. }
  45. // implemented by subclasses, given a lexical statement position, returns potential kinds of suggestions
  46. getSuggestionKinds(position: StatementPosition): SuggestionKind[] {
  47. return [];
  48. }
  49. // implemented by subclasses, given potential suggestions kinds, returns suggestion objects for monaco aka "CompletionItem"
  50. getSuggestions(
  51. monaco: Monaco,
  52. currentToken: LinkedToken | null,
  53. suggestionKinds: SuggestionKind[],
  54. statementPosition: StatementPosition,
  55. position: monacoTypes.IPosition
  56. ): Promise<CompletionItem[]> {
  57. return Promise.reject([]);
  58. }
  59. // called by registerLanguage and passed to monaco with registerCompletionItemProvider
  60. // returns an object that implements https://microsoft.github.io/monaco-editor/api/interfaces/monaco.languages.CompletionItemProvider.html
  61. getCompletionProvider(monaco: Monaco, languageDefinition: LanguageDefinition) {
  62. return {
  63. triggerCharacters: [' ', '$', ',', '(', "'"], // one of these characters indicates that it is time to look for a suggestion
  64. provideCompletionItems: async (model: monacoTypes.editor.ITextModel, position: monacoTypes.IPosition) => {
  65. const currentToken = linkedTokenBuilder(monaco, languageDefinition, model, position, this.tokenTypes);
  66. const statementPosition = this.getStatementPosition(currentToken);
  67. const suggestionKinds = this.getSuggestionKinds(statementPosition);
  68. const suggestions = await this.getSuggestions(
  69. monaco,
  70. currentToken,
  71. suggestionKinds,
  72. statementPosition,
  73. position
  74. );
  75. return {
  76. suggestions,
  77. };
  78. },
  79. };
  80. }
  81. }