chore: CE changes for module input autocomplete (#28221)

This commit is contained in:
Rishabh Rathod 2023-10-20 17:02:24 +05:30 committed by GitHub
parent cc01f7b1c9
commit 68df2a18a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 326 additions and 255 deletions

View File

@ -12,7 +12,7 @@ import moment from "moment";
import type { DerivedPropertiesMap } from "WidgetProvider/factory";
import type { WidgetFeatures } from "utils/WidgetFeatures";
import type { WidgetProps } from "../widgets/BaseWidget";
import type { ExtraDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import type { ExtraDef } from "utils/autocomplete/defCreatorUtils";
import type { WidgetEntityConfig } from "@appsmith/entities/DataTree/types";
import type {
WidgetQueryConfig,

View File

@ -1,5 +1,5 @@
import type { ExtraDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import { generateTypeDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import type { ExtraDef } from "utils/autocomplete/defCreatorUtils";
import { generateTypeDef } from "utils/autocomplete/defCreatorUtils";
import type { AppsmithEntity } from "@appsmith/entities/DataTree/types";
import _ from "lodash";
import { EVALUATION_PATH } from "utils/DynamicBindingUtils";

View File

@ -0,0 +1,140 @@
import {
type WidgetEntityConfig,
type JSActionEntityConfig,
type WidgetEntity,
type ActionEntity,
type AppsmithEntity,
type JSActionEntity,
ENTITY_TYPE_VALUE,
} from "@appsmith/entities/DataTree/types";
import type {
ConfigTree,
DataTreeEntity,
} from "entities/DataTree/dataTreeTypes";
import { isFunction } from "lodash";
import { entityDefinitions } from "@appsmith/utils/autocomplete/EntityDefinitions";
import type { Def } from "tern";
import type { DataTreeDefEntityInformation } from "utils/autocomplete/CodemirrorTernService";
import WidgetFactory from "WidgetProvider/factory";
import {
addSettersToDefinitions,
generateJSFunctionTypeDef,
generateTypeDef,
flattenDef,
} from "utils/autocomplete/defCreatorUtils";
export type EntityMap = Map<string, DataTreeDefEntityInformation>;
interface DefGeneratorProps {
entity: DataTreeEntity;
configTree: ConfigTree;
entityName: string;
extraDefsToDefine: Def;
entityMap: EntityMap;
def: Def;
jsData: Record<string, unknown>;
}
export type EntityDefGeneratorMap = Record<
string,
(props: DefGeneratorProps) => void
>;
export const entityDefGeneratorMap: EntityDefGeneratorMap = {
[ENTITY_TYPE_VALUE.ACTION]: (props) => {
const { def, entity, entityMap, entityName, extraDefsToDefine } = props;
def[entityName] = entityDefinitions.ACTION(
entity as ActionEntity,
extraDefsToDefine,
);
flattenDef(def, entityName);
entityMap.set(entityName, {
type: ENTITY_TYPE_VALUE.ACTION,
subType: "ACTION",
});
},
[ENTITY_TYPE_VALUE.APPSMITH]: (props) => {
const { def, entity, entityMap, extraDefsToDefine } = props;
def.appsmith = entityDefinitions.APPSMITH(
entity as AppsmithEntity,
extraDefsToDefine,
);
entityMap.set("appsmith", {
type: ENTITY_TYPE_VALUE.APPSMITH,
subType: ENTITY_TYPE_VALUE.APPSMITH,
});
},
[ENTITY_TYPE_VALUE.JSACTION]: (props) => {
const {
configTree,
def,
entity,
entityMap,
entityName,
extraDefsToDefine,
jsData,
} = props;
const entityConfig = configTree[entityName] as JSActionEntityConfig;
const metaObj = entityConfig.meta;
const jsPropertiesDef: Def = {};
for (const funcName in metaObj) {
const funcTypeDef = generateJSFunctionTypeDef(
jsData,
`${entityName}.${funcName}`,
extraDefsToDefine,
);
jsPropertiesDef[funcName] = funcTypeDef;
// To also show funcName.data in autocompletion hint, we explictly add it here
jsPropertiesDef[`${funcName}.data`] = funcTypeDef.data;
}
for (let i = 0; i < entityConfig?.variables?.length; i++) {
const varKey = entityConfig?.variables[i];
const varValue = (entity as JSActionEntity)[varKey];
jsPropertiesDef[varKey] = generateTypeDef(varValue, extraDefsToDefine);
}
def[entityName] = jsPropertiesDef;
entityMap.set(entityName, {
type: ENTITY_TYPE_VALUE.JSACTION,
subType: "JSACTION",
});
},
[ENTITY_TYPE_VALUE.WIDGET]: (props) => {
const {
configTree,
def,
entity,
entityMap,
entityName,
extraDefsToDefine,
} = props;
const widgetType = (entity as WidgetEntity).type;
const autocompleteDefinitions =
WidgetFactory.getAutocompleteDefinitions(widgetType);
if (autocompleteDefinitions) {
const entityConfig = configTree[entityName] as WidgetEntityConfig;
if (isFunction(autocompleteDefinitions)) {
def[entityName] = autocompleteDefinitions(
entity as WidgetEntity,
extraDefsToDefine,
entityConfig,
);
} else {
def[entityName] = autocompleteDefinitions;
}
addSettersToDefinitions(def[entityName] as Def, entity, entityConfig);
flattenDef(def, entityName);
entityMap.set(entityName, {
type: ENTITY_TYPE_VALUE.WIDGET,
subType: widgetType,
});
}
},
};

View File

@ -0,0 +1 @@
export * from "ce/utils/autocomplete/entityDefGeneratorMap";

View File

@ -7,7 +7,7 @@ import type { EntityDefinitionsOptions } from "@appsmith/utils/autocomplete/Enti
import { isFunction } from "lodash";
import type { Def } from "tern";
import WidgetFactory from "WidgetProvider/factory";
import { addSettersToDefinitions } from "utils/autocomplete/dataTreeTypeDefCreator";
import { addSettersToDefinitions } from "utils/autocomplete/defCreatorUtils";
export const getWidgetChildrenPeekData = (
widgetName: string,

View File

@ -1,6 +1,6 @@
import type { Def } from "tern";
import type { TruthyPrimitiveTypes } from "utils/TypeHelpers";
import { generateTypeDef } from "./dataTreeTypeDefCreator";
import { generateTypeDef } from "./defCreatorUtils";
export type AdditionalDynamicDataTree = Record<
string,

View File

@ -1,9 +1,4 @@
import {
generateTypeDef,
dataTreeTypeDefCreator,
flattenDef,
getFunctionsArgsType,
} from "utils/autocomplete/dataTreeTypeDefCreator";
import { dataTreeTypeDefCreator } from "utils/autocomplete/dataTreeTypeDefCreator";
import type {
WidgetEntity,
WidgetEntityConfig,
@ -15,6 +10,11 @@ import {
import InputWidget from "widgets/InputWidgetV2";
import { registerWidgets } from "WidgetProvider/factory/registrationHelper";
import {
flattenDef,
generateTypeDef,
getFunctionsArgsType,
} from "./defCreatorUtils";
describe("dataTreeTypeDefCreator", () => {
it("creates the right def for a widget", () => {

View File

@ -1,32 +1,8 @@
import type {
WidgetEntityConfig,
JSActionEntityConfig,
WidgetEntity,
} from "@appsmith/entities/DataTree/types";
import type {
ConfigTree,
DataTree,
DataTreeEntity,
} from "entities/DataTree/dataTreeTypes";
import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory";
import { uniqueId, isFunction, isObject } from "lodash";
import { entityDefinitions } from "@appsmith/utils/autocomplete/EntityDefinitions";
import { getType, Types } from "utils/TypeHelpers";
import type { DataTreeEntityObject } from "@appsmith/entities/DataTree/types";
import type { EntityMap } from "@appsmith/utils/autocomplete/entityDefGeneratorMap";
import { entityDefGeneratorMap } from "@appsmith/utils/autocomplete/entityDefGeneratorMap";
import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes";
import type { Def } from "tern";
import {
isAction,
isAppsmithEntity,
isJSAction,
isTrueObject,
isWidget,
} from "@appsmith/workers/Evaluation/evaluationUtils";
import type { DataTreeDefEntityInformation } from "utils/autocomplete/CodemirrorTernService";
export type ExtraDef = Record<string, Def | string>;
import type { Variable } from "entities/JSCollection";
import WidgetFactory from "WidgetProvider/factory";
import { shouldAddSetter } from "workers/Evaluation/evaluate";
// Def names are encoded with information about the entity
// This so that we have more info about them
@ -38,82 +14,26 @@ export const dataTreeTypeDefCreator = (
dataTree: DataTree,
jsData: Record<string, unknown> = {},
configTree: ConfigTree,
): { def: Def; entityInfo: Map<string, DataTreeDefEntityInformation> } => {
): { def: Def; entityInfo: EntityMap } => {
// When there is a complex data type, we store it in extra def and refer to it in the def
const extraDefsToDefine: Def = {};
const def: Def = {
"!name": "DATA_TREE",
};
const entityMap: Map<string, DataTreeDefEntityInformation> = new Map();
const entityMap: EntityMap = new Map();
Object.entries(dataTree).forEach(([entityName, entity]) => {
if (isWidget(entity)) {
const widgetType = entity.type;
const autocompleteDefinitions =
WidgetFactory.getAutocompleteDefinitions(widgetType);
if (autocompleteDefinitions) {
const entityConfig = configTree[entityName] as WidgetEntityConfig;
if (isFunction(autocompleteDefinitions)) {
def[entityName] = autocompleteDefinitions(
entity as WidgetEntity,
extraDefsToDefine,
entityConfig,
);
} else {
def[entityName] = autocompleteDefinitions;
}
addSettersToDefinitions(def[entityName] as Def, entity, entityConfig);
flattenDef(def, entityName);
entityMap.set(entityName, {
type: ENTITY_TYPE_VALUE.WIDGET,
subType: widgetType,
});
}
} else if (isAction(entity)) {
def[entityName] = entityDefinitions.ACTION(entity, extraDefsToDefine);
flattenDef(def, entityName);
entityMap.set(entityName, {
type: ENTITY_TYPE_VALUE.ACTION,
subType: "ACTION",
});
} else if (isAppsmithEntity(entity)) {
def.appsmith = entityDefinitions.APPSMITH(entity, extraDefsToDefine);
entityMap.set("appsmith", {
type: ENTITY_TYPE_VALUE.APPSMITH,
subType: ENTITY_TYPE_VALUE.APPSMITH,
});
} else if (isJSAction(entity)) {
const entityConfig = configTree[entityName] as JSActionEntityConfig;
const metaObj = entityConfig.meta;
const jsPropertiesDef: Def = {};
for (const funcName in metaObj) {
const funcTypeDef = generateJSFunctionTypeDef(
jsData,
`${entityName}.${funcName}`,
extraDefsToDefine,
);
jsPropertiesDef[funcName] = funcTypeDef;
// To also show funcName.data in autocompletion hint, we explictly add it here
jsPropertiesDef[`${funcName}.data`] = funcTypeDef.data;
}
for (let i = 0; i < entityConfig?.variables?.length; i++) {
const varKey = entityConfig?.variables[i];
const varValue = entity[varKey];
jsPropertiesDef[varKey] = generateTypeDef(varValue, extraDefsToDefine);
}
def[entityName] = jsPropertiesDef;
entityMap.set(entityName, {
type: ENTITY_TYPE_VALUE.JSACTION,
subType: "JSACTION",
const entityType = (entity as DataTreeEntityObject).ENTITY_TYPE;
if (entityType && entityDefGeneratorMap[entityType]) {
entityDefGeneratorMap[entityType]({
entity,
configTree,
entityName,
extraDefsToDefine,
entityMap,
def,
jsData,
});
}
});
@ -124,137 +44,3 @@ export const dataTreeTypeDefCreator = (
return { def, entityInfo: entityMap };
};
export function generateTypeDef(
value: unknown,
extraDefsToDefine?: ExtraDef,
depth = 0,
): Def | string {
switch (getType(value)) {
case Types.ARRAY: {
const array = value as [unknown];
if (depth > 5) {
return `[?]`;
}
const arrayElementType = generateTypeDef(
array[0],
extraDefsToDefine,
depth + 1,
);
if (isObject(arrayElementType)) {
if (extraDefsToDefine) {
const uniqueDefName = uniqueId("def_");
extraDefsToDefine[uniqueDefName] = arrayElementType;
return `[${uniqueDefName}]`;
}
return `[?]`;
}
return `[${arrayElementType}]`;
}
case Types.OBJECT: {
const objType: Def = {};
const object = value as Record<string, unknown>;
Object.keys(object).forEach((k) => {
objType[k] = generateTypeDef(object[k], extraDefsToDefine, depth);
});
return objType;
}
case Types.STRING:
return "string";
case Types.NUMBER:
return "number";
case Types.BOOLEAN:
return "bool";
case Types.NULL:
case Types.UNDEFINED:
return "?";
default:
return "?";
}
}
export const flattenDef = (def: Def, entityName: string): Def => {
const flattenedDef = def;
if (!isTrueObject(def[entityName])) return flattenedDef;
Object.entries(def[entityName]).forEach(([key, value]) => {
if (key.startsWith("!")) return;
const keyIsValid = isValidVariableName(key);
const parentCompletion = !keyIsValid
? `${entityName}["${key}"]`
: `${entityName}.${key}`;
flattenedDef[parentCompletion] = value;
if (!isTrueObject(value)) return;
Object.entries(value).forEach(([subKey, subValue]) => {
if (subKey.startsWith("!")) return;
const childKeyIsValid = isValidVariableName(subKey);
const childCompletion = !childKeyIsValid
? `${parentCompletion}["${subKey}"]`
: `${parentCompletion}.${subKey}`;
flattenedDef[childCompletion] = subValue;
});
});
return flattenedDef;
};
const VALID_VARIABLE_NAME_REGEX = /^([a-zA-Z_$][a-zA-Z\d_$]*)$/;
export const isValidVariableName = (variableName: string) =>
VALID_VARIABLE_NAME_REGEX.test(variableName);
export const getFunctionsArgsType = (args: Variable[]): string => {
// skip same name args to avoiding creating invalid type
const argNames = new Set<string>();
// skip invalid args name
args.forEach((arg) => {
if (arg.name && isValidVariableName(arg.name)) argNames.add(arg.name);
});
const argNamesArray = [...argNames];
const argsTypeString = argNamesArray.reduce(
(accumulatedArgType, argName, currentIndex) => {
switch (currentIndex) {
case 0:
return `${argName}: ?`;
case 1:
return `${accumulatedArgType}, ${argName}: ?`;
default:
return `${accumulatedArgType}, ${argName}: ?`;
}
},
argNamesArray[0],
);
return argsTypeString ? `fn(${argsTypeString})` : `fn()`;
};
export function generateJSFunctionTypeDef(
jsData: Record<string, unknown> = {},
fullFunctionName: string,
extraDefs: ExtraDef,
) {
return {
"!type": getFunctionsArgsType([]),
data: generateTypeDef(jsData[fullFunctionName], extraDefs),
};
}
export function addSettersToDefinitions(
definitions: Def,
entity: DataTreeEntity,
entityConfig?: WidgetEntityConfig,
) {
if (entityConfig && entityConfig.__setters) {
const setters = Object.keys(entityConfig.__setters);
setters.forEach((setterName: string) => {
const setter = entityConfig.__setters?.[setterName];
const setterType = entityConfig.__setters?.[setterName].type;
if (shouldAddSetter(setter, entity)) {
definitions[
setterName
] = `fn(value:${setterType}) -> +Promise[:t=[!0.<i>.:t]]`;
}
});
}
}

View File

@ -0,0 +1,144 @@
import { isTrueObject } from "@shared/ast/src/utils";
import type { WidgetEntityConfig } from "@appsmith/entities/DataTree/types";
import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes";
import type { Variable } from "entities/JSCollection";
import { isObject, uniqueId } from "lodash";
import type { Def } from "tern";
import { Types, getType } from "utils/TypeHelpers";
import { shouldAddSetter } from "workers/Evaluation/evaluate";
export type ExtraDef = Record<string, Def | string>;
export const flattenDef = (def: Def, entityName: string): Def => {
const flattenedDef = def;
if (!isTrueObject(def[entityName])) return flattenedDef;
Object.entries(def[entityName]).forEach(([key, value]) => {
if (key.startsWith("!")) return;
const keyIsValid = isValidVariableName(key);
const parentCompletion = !keyIsValid
? `${entityName}["${key}"]`
: `${entityName}.${key}`;
flattenedDef[parentCompletion] = value;
if (!isTrueObject(value)) return;
Object.entries(value).forEach(([subKey, subValue]) => {
if (subKey.startsWith("!")) return;
const childKeyIsValid = isValidVariableName(subKey);
const childCompletion = !childKeyIsValid
? `${parentCompletion}["${subKey}"]`
: `${parentCompletion}.${subKey}`;
flattenedDef[childCompletion] = subValue;
});
});
return flattenedDef;
};
export function generateTypeDef(
value: unknown,
extraDefsToDefine?: ExtraDef,
depth = 0,
): Def | string {
switch (getType(value)) {
case Types.ARRAY: {
const array = value as [unknown];
if (depth > 5) {
return `[?]`;
}
const arrayElementType = generateTypeDef(
array[0],
extraDefsToDefine,
depth + 1,
);
if (isObject(arrayElementType)) {
if (extraDefsToDefine) {
const uniqueDefName = uniqueId("def_");
extraDefsToDefine[uniqueDefName] = arrayElementType;
return `[${uniqueDefName}]`;
}
return `[?]`;
}
return `[${arrayElementType}]`;
}
case Types.OBJECT: {
const objType: Def = {};
const object = value as Record<string, unknown>;
Object.keys(object).forEach((k) => {
objType[k] = generateTypeDef(object[k], extraDefsToDefine, depth);
});
return objType;
}
case Types.STRING:
return "string";
case Types.NUMBER:
return "number";
case Types.BOOLEAN:
return "bool";
case Types.NULL:
case Types.UNDEFINED:
return "?";
default:
return "?";
}
}
const VALID_VARIABLE_NAME_REGEX = /^([a-zA-Z_$][a-zA-Z\d_$]*)$/;
export const isValidVariableName = (variableName: string) =>
VALID_VARIABLE_NAME_REGEX.test(variableName);
export const getFunctionsArgsType = (args: Variable[]): string => {
// skip same name args to avoiding creating invalid type
const argNames = new Set<string>();
// skip invalid args name
args.forEach((arg) => {
if (arg.name && isValidVariableName(arg.name)) argNames.add(arg.name);
});
const argNamesArray = [...argNames];
const argsTypeString = argNamesArray.reduce(
(accumulatedArgType, argName, currentIndex) => {
switch (currentIndex) {
case 0:
return `${argName}: ?`;
case 1:
return `${accumulatedArgType}, ${argName}: ?`;
default:
return `${accumulatedArgType}, ${argName}: ?`;
}
},
argNamesArray[0],
);
return argsTypeString ? `fn(${argsTypeString})` : `fn()`;
};
export function generateJSFunctionTypeDef(
jsData: Record<string, unknown> = {},
fullFunctionName: string,
extraDefs: ExtraDef,
) {
return {
"!type": getFunctionsArgsType([]),
data: generateTypeDef(jsData[fullFunctionName], extraDefs),
};
}
export function addSettersToDefinitions(
definitions: Def,
entity: DataTreeEntity,
entityConfig?: WidgetEntityConfig,
) {
if (entityConfig && entityConfig.__setters) {
const setters = Object.keys(entityConfig.__setters);
setters.forEach((setterName: string) => {
const setter = entityConfig.__setters?.[setterName];
const setterType = entityConfig.__setters?.[setterName].type;
if (shouldAddSetter(setter, entity)) {
definitions[
setterName
] = `fn(value:${setterType}) -> +Promise[:t=[!0.<i>.:t]]`;
}
});
}
}

View File

@ -12,8 +12,8 @@ import {
ResponsiveBehavior,
} from "layoutSystems/common/utils/constants";
import { DefaultAutocompleteDefinitions } from "widgets/WidgetUtils";
import type { ExtraDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import { generateTypeDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import type { ExtraDef } from "utils/autocomplete/defCreatorUtils";
import { generateTypeDef } from "utils/autocomplete/defCreatorUtils";
import type {
AnvilConfig,
AutocompletionDefinitions,

View File

@ -6,7 +6,7 @@ import type { WidgetState } from "widgets/BaseWidget";
import BaseWidget from "widgets/BaseWidget";
import IframeComponent from "../component";
import type { IframeWidgetProps } from "../constants";
import { generateTypeDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import { generateTypeDef } from "utils/autocomplete/defCreatorUtils";
import { DefaultAutocompleteDefinitions } from "widgets/WidgetUtils";
import type {
AnvilConfig,

View File

@ -32,7 +32,7 @@ import type {
} from "entities/AppTheming";
import type { BatchPropertyUpdatePayload } from "actions/controlActions";
import { isAutoHeightEnabledForWidget } from "widgets/WidgetUtils";
import { generateTypeDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import { generateTypeDef } from "utils/autocomplete/defCreatorUtils";
import type {
AnvilConfig,
AutocompletionDefinitions,

View File

@ -34,8 +34,8 @@ import {
} from "utils/DynamicBindingUtils";
import { removeFalsyEntries } from "utils/helpers";
import { DefaultAutocompleteDefinitions } from "widgets/WidgetUtils";
import { generateTypeDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import type { ExtraDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import { generateTypeDef } from "utils/autocomplete/defCreatorUtils";
import type { ExtraDef } from "utils/autocomplete/defCreatorUtils";
import WidgetFactory from "WidgetProvider/factory";
import type { WidgetProps, WidgetState } from "widgets/BaseWidget";
import BaseWidget from "widgets/BaseWidget";

View File

@ -46,9 +46,9 @@ import type {
} from "widgets/TabsWidget/constants";
import { getMetaFlexLayers, isTargetElementClickable } from "./helper";
import { DefaultAutocompleteDefinitions } from "widgets/WidgetUtils";
import type { ExtraDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import type { ExtraDef } from "utils/autocomplete/defCreatorUtils";
import { LayoutSystemTypes } from "layoutSystems/types";
import { generateTypeDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import { generateTypeDef } from "utils/autocomplete/defCreatorUtils";
import defaultProps from "./defaultProps";
import IconSVG from "../icon.svg";

View File

@ -41,8 +41,8 @@ import { OperatorTypes } from "../component/Constants";
import type { TableWidgetProps } from "../constants";
import derivedProperties from "./parseDerivedProperties";
import { selectRowIndex, selectRowIndices } from "./utilities";
import type { ExtraDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import { generateTypeDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import type { ExtraDef } from "utils/autocomplete/defCreatorUtils";
import { generateTypeDef } from "utils/autocomplete/defCreatorUtils";
import type {
ColumnProperties,

View File

@ -119,8 +119,8 @@ import type {
transformDataWithEditableCell,
} from "./reactTableUtils/transformDataPureFn";
import { getMemoiseTransformDataWithEditableCell } from "./reactTableUtils/transformDataPureFn";
import type { ExtraDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import { generateTypeDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import type { ExtraDef } from "utils/autocomplete/defCreatorUtils";
import { generateTypeDef } from "utils/autocomplete/defCreatorUtils";
import type {
AnvilConfig,
AutocompletionDefinitions,

View File

@ -119,8 +119,8 @@ import type {
transformDataWithEditableCell,
} from "./reactTableUtils/transformDataPureFn";
import { getMemoiseTransformDataWithEditableCell } from "./reactTableUtils/transformDataPureFn";
import type { ExtraDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import { generateTypeDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import type { ExtraDef } from "utils/autocomplete/defCreatorUtils";
import { generateTypeDef } from "utils/autocomplete/defCreatorUtils";
import type {
AutocompletionDefinitions,
PropertyUpdates,