Skip to content

Commit f1540d2

Browse files
authored
Merge pull request #970 from senithkay/fix-field-access-completions
fix completions not displayed for field access
2 parents 83593d2 + 2617d7c commit f1540d2

File tree

2 files changed

+31
-11
lines changed

2 files changed

+31
-11
lines changed

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -397,22 +397,24 @@ export const buildOnChangeListner = (onTrigeer: (newValue: string, cursor: Curso
397397
return onChangeListner;
398398
}
399399

400-
export const buildCompletionSource = (getCompletions: () => CompletionItem[]) => {
401-
return (context: CompletionContext): CompletionResult | null => {
400+
export const buildCompletionSource = (getCompletions: () => Promise<CompletionItem[]>) => {
401+
return async (context: CompletionContext): Promise<CompletionResult | null> => {
402+
const textBeforeCursor = context.state.doc.toString().slice(0, context.pos);
403+
const lastNonSpaceChar = textBeforeCursor.trimEnd().slice(-1);
404+
402405
const word = context.matchBefore(/\w*/);
403-
if (!word || (word.from === word.to && !context.explicit)) {
406+
if (lastNonSpaceChar !== '.' && (
407+
!word || (word.from === word.to && !context.explicit)
408+
)) {
404409
return null;
405410
}
406411

407-
const textBeforeCursor = context.state.doc.toString().slice(0, context.pos);
408-
const lastNonSpaceChar = textBeforeCursor.trimEnd().slice(-1);
409-
410412
// Don't show completions for trigger characters
411-
if (lastNonSpaceChar === '+' || lastNonSpaceChar === ':') {
413+
if (lastNonSpaceChar === '+') {
412414
return null;
413415
}
414416

415-
const completions = getCompletions();
417+
const completions = await getCompletions();
416418
const prefix = word.text;
417419
const filteredCompletions = filterCompletionsByPrefixAndType(completions, prefix);
418420

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import { EditorState } from "@codemirror/state";
2020
import { EditorView, keymap, tooltips } from "@codemirror/view";
21-
import React, { useEffect, useRef, useState } from "react";
21+
import React, { useEffect, useMemo, useRef, useState } from "react";
2222
import { useFormContext } from "../../../../../context";
2323
import {
2424
buildNeedTokenRefetchListner,
@@ -88,8 +88,9 @@ export const ChipExpressionEditorComponent = (props: ChipExpressionEditorCompone
8888
const fieldContainerRef = useRef<HTMLDivElement>(null);
8989
const viewRef = useRef<EditorView | null>(null);
9090
const [isTokenUpdateScheduled, setIsTokenUpdateScheduled] = useState(true);
91-
const completionsRef = useRef(props.completions);
91+
const completionsRef = useRef<CompletionItem[]>(props.completions);
9292
const helperPaneToggleButtonRef = useRef<HTMLButtonElement>(null);
93+
const completionsFetchScheduledRef = useRef<boolean>(false);
9394

9495
const { expressionEditor } = useFormContext();
9596
const expressionEditorRpcManager = expressionEditor?.rpcManager;
@@ -99,6 +100,7 @@ export const ChipExpressionEditorComponent = (props: ChipExpressionEditorCompone
99100
});
100101

101102
const handleChangeListner = buildOnChangeListner((newValue, cursor) => {
103+
completionsFetchScheduledRef.current = true;
102104
props.onChange(newValue, cursor.position.to);
103105
const textBeforeCursor = newValue.slice(0, cursor.position.to);
104106
const lastNonSpaceChar = textBeforeCursor.trimEnd().slice(-1);
@@ -124,7 +126,22 @@ export const ChipExpressionEditorComponent = (props: ChipExpressionEditorCompone
124126
setIsTokenUpdateScheduled(true);
125127
});
126128

127-
const completionSource = buildCompletionSource(() => completionsRef.current);
129+
const waitForStateChange = (): Promise<CompletionItem[]> => {
130+
return new Promise((resolve) => {
131+
const checkState = () => {
132+
if (!completionsFetchScheduledRef.current) {
133+
resolve(completionsRef.current);
134+
} else {
135+
requestAnimationFrame(checkState);
136+
}
137+
};
138+
checkState();
139+
});
140+
};
141+
142+
const completionSource = useMemo(() => {
143+
return buildCompletionSource(waitForStateChange);
144+
}, [props.completions]);
128145

129146
const helperPaneKeymap = buildHelperPaneKeymap(() => helperPaneState.isOpen, () => {
130147
setHelperPaneState(prev => ({ ...prev, isOpen: false }));
@@ -284,6 +301,7 @@ export const ChipExpressionEditorComponent = (props: ChipExpressionEditorCompone
284301
// just don't touch this.
285302
useEffect(() => {
286303
completionsRef.current = props.completions;
304+
completionsFetchScheduledRef.current = false;
287305
}, [props.completions]);
288306

289307
useEffect(() => {

0 commit comments

Comments
 (0)