@neo4j-cypher/react-codemirror 2.0.0-next.12 → 2.0.0-next.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/unbound-method */
1
2
  import { testData } from '@neo4j-cypher/language-support';
2
3
  import { expect, test } from '@playwright/experimental-ct-react';
3
4
  import { Locator } from 'playwright/test';
@@ -10,6 +11,8 @@ type TooltipExpectations = {
10
11
  excludes?: string[];
11
12
  };
12
13
 
14
+ const importCsvProc = testData.mockSchema.procedures['apoc.import.csv'];
15
+
13
16
  function testTooltip(tooltip: Locator, expectations: TooltipExpectations) {
14
17
  const includes = expectations.includes ?? [];
15
18
  const excludes = expectations.excludes ?? [];
@@ -83,8 +86,9 @@ test('Signature help shows the description for the first argument', async ({
83
86
 
84
87
  await testTooltip(tooltip, {
85
88
  includes: [
86
- 'nodes :: LIST<MAP>',
87
- 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
89
+ testData.mockSchema.procedures['apoc.import.csv'].argumentDescription[0]
90
+ .description,
91
+ testData.mockSchema.procedures['apoc.import.csv'].description,
88
92
  ],
89
93
  });
90
94
  });
@@ -103,8 +107,8 @@ test('Signature help shows the description for the first argument when the curso
103
107
 
104
108
  await testTooltip(tooltip, {
105
109
  includes: [
106
- 'nodes :: LIST<MAP>',
107
- 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
110
+ importCsvProc.argumentDescription[0].description,
111
+ importCsvProc.description,
108
112
  ],
109
113
  });
110
114
  });
@@ -127,8 +131,8 @@ test('Signature help shows the description for the second argument', async ({
127
131
 
128
132
  await testTooltip(tooltip, {
129
133
  includes: [
130
- 'rels :: LIST<MAP>',
131
- 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
134
+ importCsvProc.argumentDescription[1].description,
135
+ importCsvProc.description,
132
136
  ],
133
137
  });
134
138
  });
@@ -147,8 +151,8 @@ test('Signature help shows the description for the second argument when the curs
147
151
 
148
152
  await testTooltip(tooltip, {
149
153
  includes: [
150
- 'rels :: LIST<MAP>',
151
- 'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
154
+ importCsvProc.argumentDescription[1].description,
155
+ importCsvProc.description,
152
156
  ],
153
157
  });
154
158
  });
@@ -77,73 +77,56 @@ export const cypherAutocomplete: (config: CypherConfig) => CompletionSource =
77
77
  }
78
78
 
79
79
  const options = autocomplete(
80
- documentText,
80
+ // TODO This is a temporary hack because completions are not working well
81
+ documentText.slice(0, context.pos),
81
82
  config.schema ?? {},
82
83
  context.pos,
83
84
  context.explicit,
84
85
  );
85
86
 
86
- if (config.featureFlags?.signatureInfoOnAutoCompletions) {
87
- return {
88
- from: context.matchBefore(/(\w|\$)*$/).from,
89
- options: options.map((o) => {
90
- let maybeInfo = {};
91
- let emptyInfo = true;
92
- const newDiv = document.createElement('div');
87
+ return {
88
+ from: context.matchBefore(/(\w|\$)*$/).from,
89
+ options: options.map((o) => {
90
+ let maybeInfo = {};
91
+ let emptyInfo = true;
92
+ const newDiv = document.createElement('div');
93
93
 
94
- if (o.signature) {
95
- const header = document.createElement('p');
96
- header.setAttribute('class', 'cm-completionInfo-signature');
97
- header.textContent = o.signature;
98
- if (header.textContent.length > 0) {
99
- emptyInfo = false;
100
- newDiv.appendChild(header);
101
- }
94
+ if (o.signature) {
95
+ const header = document.createElement('p');
96
+ header.setAttribute('class', 'cm-completionInfo-signature');
97
+ header.textContent = o.signature;
98
+ if (header.textContent.length > 0) {
99
+ emptyInfo = false;
100
+ newDiv.appendChild(header);
102
101
  }
102
+ }
103
103
 
104
- if (o.documentation) {
105
- const paragraph = document.createElement('p');
106
- paragraph.textContent = getDocString(o.documentation);
107
- if (paragraph.textContent.length > 0) {
108
- emptyInfo = false;
109
- newDiv.appendChild(paragraph);
110
- }
104
+ if (o.documentation) {
105
+ const paragraph = document.createElement('p');
106
+ paragraph.textContent = getDocString(o.documentation);
107
+ if (paragraph.textContent.length > 0) {
108
+ emptyInfo = false;
109
+ newDiv.appendChild(paragraph);
111
110
  }
111
+ }
112
112
 
113
- if (!emptyInfo) {
114
- maybeInfo = {
115
- info: () => Promise.resolve(newDiv),
116
- };
117
- }
118
- const deprecated =
119
- o.tags?.find((tag) => tag === CompletionItemTag.Deprecated) ??
120
- false;
121
- // The negative boost moves the deprecation down the list
122
- // so we offer the user the completions that are
123
- // deprecated the last
124
- const maybeDeprecated = deprecated
125
- ? { boost: -99, deprecated: true }
126
- : {};
127
-
128
- return {
129
- label: o.label,
130
- type: completionKindToCodemirrorIcon(o.kind),
131
- apply:
132
- o.kind === CompletionItemKind.Snippet
133
- ? // codemirror requires an empty snippet space to be able to tab out of the completion
134
- snippet((o.insertText ?? o.label) + '${}')
135
- : undefined,
136
- detail: o.detail,
137
- ...maybeDeprecated,
138
- ...maybeInfo,
113
+ if (!emptyInfo) {
114
+ maybeInfo = {
115
+ info: () => Promise.resolve(newDiv),
139
116
  };
140
- }),
141
- };
142
- } else {
143
- return {
144
- from: context.matchBefore(/(\w|\$)*$/).from,
145
- options: options.map((o) => ({
146
- label: o.label,
117
+ }
118
+ const deprecated =
119
+ o.tags?.find((tag) => tag === CompletionItemTag.Deprecated) ?? false;
120
+ // The negative boost moves the deprecation down the list
121
+ // so we offer the user the completions that are
122
+ // deprecated the last
123
+ const maybeDeprecated = deprecated
124
+ ? { boost: -99, deprecated: true }
125
+ : {};
126
+
127
+ return {
128
+ label: o.insertText ? o.insertText : o.label,
129
+ displayLabel: o.label,
147
130
  type: completionKindToCodemirrorIcon(o.kind),
148
131
  apply:
149
132
  o.kind === CompletionItemKind.Snippet
@@ -151,7 +134,9 @@ export const cypherAutocomplete: (config: CypherConfig) => CompletionSource =
151
134
  snippet((o.insertText ?? o.label) + '${}')
152
135
  : undefined,
153
136
  detail: o.detail,
154
- })),
155
- };
156
- }
137
+ ...maybeDeprecated,
138
+ ...maybeInfo,
139
+ };
140
+ }),
141
+ };
157
142
  };
@@ -121,6 +121,9 @@ export const createCypherTheme = ({
121
121
  '& .cm-signature-help-panel-name': {
122
122
  padding: '5px',
123
123
  },
124
+ '& .cm-signature-help-panel-arg-description': {
125
+ padding: '5px',
126
+ },
124
127
  '& .cm-signature-help-panel-description': {
125
128
  padding: '5px',
126
129
  },
@@ -22,7 +22,6 @@ export type CypherConfig = {
22
22
  lint?: boolean;
23
23
  showSignatureTooltipBelow?: boolean;
24
24
  featureFlags?: {
25
- signatureInfoOnAutoCompletions?: boolean;
26
25
  consoleCommands?: boolean;
27
26
  };
28
27
  schema?: DbSchema;
@@ -1,7 +1,10 @@
1
1
  import { EditorState, StateField } from '@codemirror/state';
2
2
  import { showTooltip, Tooltip } from '@codemirror/view';
3
3
  import { signatureHelp } from '@neo4j-cypher/language-support';
4
- import { SignatureInformation } from 'vscode-languageserver-types';
4
+ import {
5
+ MarkupContent,
6
+ SignatureInformation,
7
+ } from 'vscode-languageserver-types';
5
8
  import { CypherConfig } from './langCypher';
6
9
  import { getDocString } from './utils';
7
10
 
@@ -38,24 +41,32 @@ const createSignatureHelpElement =
38
41
 
39
42
  const signatureLabel = document.createElement('div');
40
43
  signatureLabel.className = 'cm-signature-help-panel-name';
41
- signatureLabel.appendChild(document.createTextNode(`${signature.label}(`));
44
+ const methodName = signature.label.slice(0, signature.label.indexOf('('));
45
+ const returnType = signature.label.slice(signature.label.indexOf(')') + 1);
46
+ signatureLabel.appendChild(document.createTextNode(`${methodName}(`));
47
+ let currentParamDescription: string | undefined = undefined;
42
48
 
43
49
  parameters.forEach((param, index) => {
44
- if (typeof param.documentation === 'string') {
50
+ if (typeof param.label === 'string') {
45
51
  const span = document.createElement('span');
46
- span.appendChild(document.createTextNode(param.documentation));
52
+ span.appendChild(document.createTextNode(param.label));
47
53
  if (index !== parameters.length - 1) {
48
54
  span.appendChild(document.createTextNode(', '));
49
55
  }
50
56
 
51
57
  if (index === activeParameter) {
52
58
  span.className = 'cm-signature-help-panel-current-argument';
59
+ const paramDoc = param.documentation;
60
+ currentParamDescription = MarkupContent.is(paramDoc)
61
+ ? paramDoc.value
62
+ : paramDoc;
53
63
  }
54
64
  signatureLabel.appendChild(span);
55
65
  }
56
66
  });
57
67
 
58
68
  signatureLabel.appendChild(document.createTextNode(')'));
69
+ signatureLabel.appendChild(document.createTextNode(returnType));
59
70
 
60
71
  contents.appendChild(signatureLabel);
61
72
 
@@ -64,11 +75,18 @@ const createSignatureHelpElement =
64
75
 
65
76
  contents.appendChild(separator);
66
77
 
67
- const description = document.createElement('div');
68
- description.className = 'cm-signature-help-panel-description';
69
- description.appendChild(document.createTextNode(doc));
70
-
71
- contents.appendChild(description);
78
+ if (currentParamDescription !== undefined) {
79
+ const argDescription = document.createElement('div');
80
+ argDescription.className = 'cm-signature-help-panel-arg-description';
81
+ argDescription.appendChild(
82
+ document.createTextNode(currentParamDescription),
83
+ );
84
+ contents.appendChild(argDescription);
85
+ }
86
+ const methodDescription = document.createElement('div');
87
+ methodDescription.className = 'cm-signature-help-panel-description';
88
+ methodDescription.appendChild(document.createTextNode(doc));
89
+ contents.appendChild(methodDescription);
72
90
 
73
91
  return { dom };
74
92
  };