"use strict"; const codemirror = require("./codemirror.cjs.js"); const graphql = require("graphql"); const forEachState = require("./forEachState.cjs.js"); function hintList(cursor, token, list) { const hints = filterAndSortList(list, normalizeText(token.string)); if (!hints) { return; } const tokenStart = token.type !== null && /"|\w/.test(token.string[0]) ? token.start : token.end; return { list: hints, from: { line: cursor.line, ch: tokenStart }, to: { line: cursor.line, ch: token.end } }; } function filterAndSortList(list, text) { if (!text) { return filterNonEmpty(list, (entry) => !entry.isDeprecated); } const byProximity = list.map((entry) => ({ proximity: getProximity(normalizeText(entry.text), text), entry })); const conciseMatches = filterNonEmpty(filterNonEmpty(byProximity, (pair) => pair.proximity <= 2), (pair) => !pair.entry.isDeprecated); const sortedMatches = conciseMatches.sort((a, b) => (a.entry.isDeprecated ? 1 : 0) - (b.entry.isDeprecated ? 1 : 0) || a.proximity - b.proximity || a.entry.text.length - b.entry.text.length); return sortedMatches.map((pair) => pair.entry); } function filterNonEmpty(array, predicate) { const filtered = array.filter(predicate); return filtered.length === 0 ? array : filtered; } function normalizeText(text) { return text.toLowerCase().replaceAll(/\W/g, ""); } function getProximity(suggestion, text) { let proximity = lexicalDistance(text, suggestion); if (suggestion.length > text.length) { proximity -= suggestion.length - text.length - 1; proximity += suggestion.indexOf(text) === 0 ? 0 : 0.5; } return proximity; } function lexicalDistance(a, b) { let i; let j; const d = []; const aLength = a.length; const bLength = b.length; for (i = 0; i <= aLength; i++) { d[i] = [i]; } for (j = 1; j <= bLength; j++) { d[0][j] = j; } for (i = 1; i <= aLength; i++) { for (j = 1; j <= bLength; j++) { const cost = a[i - 1] === b[j - 1] ? 0 : 1; d[i][j] = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost); if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) { d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost); } } } return d[aLength][bLength]; } codemirror.CodeMirror.registerHelper("hint", "graphql-variables", (editor, options) => { const cur = editor.getCursor(); const token = editor.getTokenAt(cur); const results = getVariablesHint(cur, token, options); if ((results === null || results === void 0 ? void 0 : results.list) && results.list.length > 0) { results.from = codemirror.CodeMirror.Pos(results.from.line, results.from.ch); results.to = codemirror.CodeMirror.Pos(results.to.line, results.to.ch); codemirror.CodeMirror.signal(editor, "hasCompletion", editor, results, token); } return results; }); function getVariablesHint(cur, token, options) { const state = token.state.kind === "Invalid" ? token.state.prevState : token.state; const { kind, step } = state; if (kind === "Document" && step === 0) { return hintList(cur, token, [{ text: "{" }]); } const { variableToType } = options; if (!variableToType) { return; } const typeInfo = getTypeInfo(variableToType, token.state); if (kind === "Document" || kind === "Variable" && step === 0) { const variableNames = Object.keys(variableToType); return hintList(cur, token, variableNames.map((name) => ({ text: `"${name}": `, type: variableToType[name] }))); } if ((kind === "ObjectValue" || kind === "ObjectField" && step === 0) && typeInfo.fields) { const inputFields = Object.keys(typeInfo.fields).map((fieldName) => typeInfo.fields[fieldName]); return hintList(cur, token, inputFields.map((field) => ({ text: `"${field.name}": `, type: field.type, description: field.description }))); } if (kind === "StringValue" || kind === "NumberValue" || kind === "BooleanValue" || kind === "NullValue" || kind === "ListValue" && step === 1 || kind === "ObjectField" && step === 2 || kind === "Variable" && step === 2) { const namedInputType = typeInfo.type ? graphql.getNamedType(typeInfo.type) : void 0; if (namedInputType instanceof graphql.GraphQLInputObjectType) { return hintList(cur, token, [{ text: "{" }]); } if (namedInputType instanceof graphql.GraphQLEnumType) { const values = namedInputType.getValues(); return hintList(cur, token, values.map((value) => ({ text: `"${value.name}"`, type: namedInputType, description: value.description }))); } if (namedInputType === graphql.GraphQLBoolean) { return hintList(cur, token, [ { text: "true", type: graphql.GraphQLBoolean, description: "Not false." }, { text: "false", type: graphql.GraphQLBoolean, description: "Not true." } ]); } } } function getTypeInfo(variableToType, tokenState) { const info = { type: null, fields: null }; forEachState.forEachState(tokenState, (state) => { switch (state.kind) { case "Variable": { info.type = variableToType[state.name]; break; } case "ListValue": { const nullableType = info.type ? graphql.getNullableType(info.type) : void 0; info.type = nullableType instanceof graphql.GraphQLList ? nullableType.ofType : null; break; } case "ObjectValue": { const objectType = info.type ? graphql.getNamedType(info.type) : void 0; info.fields = objectType instanceof graphql.GraphQLInputObjectType ? objectType.getFields() : null; break; } case "ObjectField": { const objectField = state.name && info.fields ? info.fields[state.name] : null; info.type = objectField === null || objectField === void 0 ? void 0 : objectField.type; break; } } }); return info; } //# sourceMappingURL=hint.cjs2.js.map