Skip to content

Commit

Permalink
Adds feature flag to the codemirror wiring
Browse files Browse the repository at this point in the history
  • Loading branch information
ncordon committed Jan 26, 2025
1 parent 07f20b7 commit f3b41a1
Show file tree
Hide file tree
Showing 13 changed files with 262 additions and 72 deletions.
5 changes: 4 additions & 1 deletion packages/language-server/src/lintWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import workerpool from 'workerpool';
function lintCypherQuery(
query: string,
dbSchema: DbSchema,
featureFlags: { cypher25?: boolean } = {},
featureFlags: { consoleCommands?: boolean; cypher25?: boolean } = {},
) {
// We allow to override the consoleCommands feature flag
if (featureFlags.consoleCommands !== undefined) {
_internalFeatureFlags.consoleCommands = featureFlags.consoleCommands;
}
if (featureFlags.cypher25 !== undefined) {
_internalFeatureFlags.cypher25 = featureFlags.cypher25;
}
Expand Down
15 changes: 10 additions & 5 deletions packages/language-support/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import antlrDefaultExport, {
Token,
} from 'antlr4';
import { DbSchema } from './dbSchema';
import { _internalFeatureFlags } from './featureFlags';
import CypherLexer from './generated-parser/CypherCmdLexer';
import CypherParser, {
NodePatternContext,
Expand Down Expand Up @@ -209,11 +210,15 @@ export function resolveCypherVersion(
parsedVersion: CypherVersion | undefined,
dbSchema: DbSchema,
) {
const cypherVersion: CypherVersion =
parsedVersion ??
(dbSchema.defaultLanguage ? dbSchema.defaultLanguage : 'cypher 5');

return cypherVersion;
if (_internalFeatureFlags.cypher25) {
const cypherVersion: CypherVersion =
parsedVersion ??
(dbSchema.defaultLanguage ? dbSchema.defaultLanguage : 'cypher 5');

return cypherVersion;
} else {
return 'cypher 5';
}
}

export const rulesDefiningVariables = [
Expand Down
1 change: 0 additions & 1 deletion packages/react-codemirror-playground/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ export function App() {
theme={darkMode ? 'dark' : 'light'}
history={Object.values(demos)}
schema={schema}
featureFlags={{ signatureInfoOnAutoCompletions: true }}
ariaLabel="Cypher Editor"
/>

Expand Down
11 changes: 9 additions & 2 deletions packages/react-codemirror/src/CypherEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import {
placeholder,
ViewUpdate,
} from '@codemirror/view';
import { type DbSchema } from '@neo4j-cypher/language-support';
import {
_internalFeatureFlags,
type DbSchema,
} from '@neo4j-cypher/language-support';
import debounce from 'lodash.debounce';
import { Component, createRef } from 'react';
import { DEBOUNCE_TIME } from './constants';
Expand Down Expand Up @@ -99,7 +102,7 @@ export interface CypherEditorProps {
*/
featureFlags?: {
consoleCommands?: boolean;
signatureInfoOnAutoCompletions?: boolean;
cypher25?: boolean;
};
/**
* The schema to use for autocompletion and linting.
Expand Down Expand Up @@ -346,6 +349,10 @@ export class CypherEditor extends Component<
newLineOnEnter,
} = this.props;

if (featureFlags.cypher25) {
_internalFeatureFlags.cypher25 = featureFlags.cypher25;
}

this.schemaRef.current = {
schema,
lint,
Expand Down
77 changes: 41 additions & 36 deletions packages/react-codemirror/src/e2e_tests/autoCompletion.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -312,14 +312,7 @@ test('shows signature help information on auto-completion for procedures', async
page,
mount,
}) => {
await mount(
<CypherEditor
schema={testData.mockSchema}
featureFlags={{
signatureInfoOnAutoCompletions: true,
}}
/>,
);
await mount(<CypherEditor schema={testData.mockSchema} />);
const procName = 'apoc.periodic.iterate';
const procedure = testData.mockSchema.procedures['cypher 5'][procName];

Expand All @@ -337,14 +330,7 @@ test('shows signature help information on auto-completion for functions', async
page,
mount,
}) => {
await mount(
<CypherEditor
schema={testData.mockSchema}
featureFlags={{
signatureInfoOnAutoCompletions: true,
}}
/>,
);
await mount(<CypherEditor schema={testData.mockSchema} />);
const fnName = 'apoc.coll.combinations';
const fn = testData.mockSchema.functions['cypher 5'][fnName];

Expand Down Expand Up @@ -373,9 +359,6 @@ test('shows deprecated procedures as strikethrough on auto-completion', async ({
},
},
}}
featureFlags={{
signatureInfoOnAutoCompletions: true,
}}
/>,
);
const textField = page.getByRole('textbox');
Expand All @@ -401,9 +384,6 @@ test('shows deprecated function as strikethrough on auto-completion', async ({
},
},
}}
featureFlags={{
signatureInfoOnAutoCompletions: true,
}}
/>,
);
const textField = page.getByRole('textbox');
Expand All @@ -418,14 +398,7 @@ test('does not signature help information on auto-completion if docs and signatu
page,
mount,
}) => {
await mount(
<CypherEditor
schema={testData.mockSchema}
featureFlags={{
signatureInfoOnAutoCompletions: true,
}}
/>,
);
await mount(<CypherEditor schema={testData.mockSchema} />);

const textField = page.getByRole('textbox');
await textField.fill('C');
Expand All @@ -452,9 +425,6 @@ test('shows signature help information on auto-completion if description is not
},
},
}}
featureFlags={{
signatureInfoOnAutoCompletions: true,
}}
/>,
);

Expand Down Expand Up @@ -483,9 +453,6 @@ test('shows signature help information on auto-completion if signature is not em
},
},
}}
featureFlags={{
signatureInfoOnAutoCompletions: true,
}}
/>,
);

Expand All @@ -495,3 +462,41 @@ test('shows signature help information on auto-completion if signature is not em
await expect(page.locator('.cm-tooltip-autocomplete')).toBeVisible();
await expect(page.locator('.cm-completionInfo')).toBeVisible();
});

test('completions are cypher version dependant', async ({ page, mount }) => {
await mount(
<CypherEditor
schema={{
functions: {
'cypher 5': {
cypher5Function: {
...testData.emptyFunction,
name: 'cypher5Function',
},
},
'cypher 25': {
cypher25Function: {
...testData.emptyFunction,
name: 'cypher25Function',
},
},
},
}}
featureFlags={{ cypher25: true }}
/>,
);

const textField = page.getByRole('textbox');

await textField.fill('CYPHER 5 RETURN cypher');

await expect(
page.locator('.cm-tooltip-autocomplete').getByText('cypher5Function'),
).toBeVisible();

await textField.fill('CYPHER 25 RETURN cypher');

await expect(
page.locator('.cm-tooltip-autocomplete').getByText('cypher25Function'),
).toBeVisible();
});
1 change: 1 addition & 0 deletions packages/react-codemirror/src/lang-cypher/langCypher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export type CypherConfig = {
showSignatureTooltipBelow?: boolean;
featureFlags?: {
consoleCommands?: boolean;
cypher25?: boolean;
};
schema?: DbSchema;
useLightVersion: boolean;
Expand Down
5 changes: 4 additions & 1 deletion packages/react-codemirror/src/lang-cypher/lintWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import workerpool from 'workerpool';
function lintCypherQuery(
query: string,
dbSchema: DbSchema,
featureFlags: { consoleCommands?: boolean } = {},
featureFlags: { consoleCommands?: boolean; cypher25?: boolean } = {},
) {
// We allow to override the consoleCommands feature flag
if (featureFlags.consoleCommands !== undefined) {
_internalFeatureFlags.consoleCommands = featureFlags.consoleCommands;
}
if (featureFlags.cypher25 !== undefined) {
_internalFeatureFlags.cypher25 = featureFlags.cypher25;
}
return _lintCypherQuery(query, dbSchema);
}

Expand Down
4 changes: 2 additions & 2 deletions packages/vscode-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,8 @@
"build": "tsc -b && npm run gen-textmate && npm run bundle-extension && npm run bundle-language-server && npm run bundle-webview-controllers",
"build:dev": "tsc -b && npm run gen-textmate && npm run bundle-extension:dev && npm run bundle-language-server && npm run bundle-webview-controllers",
"clean": "rm -rf dist",
"test:e2e": "npm run build && npm run test:apiAndUnit && npm run test:webviews",
"test:apiAndUnit": "rm -rf .vscode-test/user-data && node ./dist/tests/runApiAndUnitTests.js",
"test:e2e": "npm run build:dev && npm run test:apiAndUnit && npm run test:webviews",
"test:apiAndUnit": "npm run build:dev && rm -rf .vscode-test/user-data && node ./dist/tests/runApiAndUnitTests.js",
"test:webviews": "wdio run ./dist/tests/runWebviewTests.js"
},
"dependencies": {
Expand Down
37 changes: 37 additions & 0 deletions packages/vscode-extension/tests/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as path from 'path';
import * as vscode from 'vscode';
import { TextDocument, Uri, window, workspace } from 'vscode';
import { Connection } from '../src/connectionService';
import { getNonce } from '../src/getNonce';
Expand All @@ -21,6 +22,8 @@ export async function newUntitledFileWithContent(
// The language server will not be activated automatically
const document = await workspace.openTextDocument({ content: content });
await window.showTextDocument(document);
const editor = vscode.window.activeTextEditor;
await vscode.languages.setTextDocumentLanguage(editor.document, 'cypher');
return document;
} catch (e) {
console.error(e);
Expand Down Expand Up @@ -85,3 +88,37 @@ export function getNeo4jConfiguration() {
password: process.env.NEO4J_PASSWORD || 'password',
};
}

export function rangeToString(range: vscode.Range) {
return `${range.start.line}:${range.start.character} to ${range.end.line}:${range.end.character}`;
}

export function documentationToString(
doc: string | vscode.MarkdownString | undefined,
) {
if (typeof doc === 'string') {
return doc;
} else if (typeof doc === 'undefined') {
return 'undefined';
} else {
return doc.value;
}
}

export function tagsToString(
doc: readonly vscode.CompletionItemTag[] | undefined,
) {
if (!doc) {
return 'undefined';
} else {
return doc.map((tag) => tag.toString()).join(', ');
}
}

export function parameterLabelToString(label: string | [number, number]) {
if (Array.isArray(label)) {
return `${label[0]}:${label[1]}`;
} else {
return label;
}
}
1 change: 1 addition & 0 deletions packages/vscode-extension/tests/runApiAndUnitTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ async function main() {
launchArgs: [path.join(__dirname, '../../tests/fixtures/')],
extensionDevelopmentPath,
extensionTestsPath,
extensionTestsEnv: { CYPHER_25: 'true' },
});
} catch (err) {
console.error('Failed to run integration tests');
Expand Down
Loading

0 comments on commit f3b41a1

Please sign in to comment.