<commit_before>import { buildClientSchema } from 'graphql';
import {
  CompletionItem,
  Diagnostic,
  getAutocompleteSuggestions,
  getDiagnostics,
  Position,
} from 'graphql-language-service-interface';
import * as ts from 'typescript/lib/tsserverlibrary';
import { isTagged, TagCondition } from './ts-util/index';

export interface GraphQLLanguageServiceAdapterCreateOptions {
  schema?: any;
  logger?: (msg: string) => void;
  tag?: string;
}

export type GetCompletionAtPosition = ts.LanguageService['getCompletionsAtPosition'];
export type GetSemanticDiagnostics = ts.LanguageService['getSemanticDiagnostics'];

export interface ScriptSourceHelper {
  // getSource: (fileName: string) => ts.SourceFile;
  getAllNodes: (fileName: string, condition) => ts.Node[];
  getNode: (fileName: string, position) => ts.Node;
  getLineAndChar: (fileName: string, position) => ts.LineAndCharacter;
}

export class GraphQLLanguageServiceAdapter {

  private _schema: any;
  private _tagCondition: TagCondition = null;

  constructor(
    private _helper: ScriptSourceHelper,
    opt: GraphQLLanguageServiceAdapterCreateOptions = { },
  ) {
      if (opt.logger) this._logger = opt.logger;
      if (opt.schema) this.updateSchema(opt.schema);
      if (opt.tag) this._tagCondition = opt.tag;
  }

  updateSchema(schema: { data: any }) {
    try {
      this._schema = buildClientSchema(schema.data);
    } catch (err) {
      this._logger('Fail to build schema...');
      this._logger(err);
      this._schema = null;
    }
  }

  getCompletionAtPosition(delegate: GetCompletionAtPosition, fileName: string, position: number ) {
    if (!this._schema) return delegate(fileName, position);
    const node = this._helper.getNode(fileName, position);
    if (!node || node.kind !== ts.SyntaxKind.NoSubstitutionTemplateLiteral) {
      return delegate(fileName, position);
    }
    if (this._tagCondition && !isTagged(node, this._tagCondition)) {
      return delegate(fileName, position);
    }
    const cursor = position - node.getStart();
    const baseLC = this._helper.getLineAndChar(fileName, node.getStart());
    const cursorLC = this._helper.getLineAndChar(fileName, position);
    const relativeLC = { line: cursorLC.line - baseLC.line, character: cursorLC.character - baseLC.character + 1 };
    const p = new SimplePosition(relativeLC);
    const text = node.getText().slice(1, cursor + 1);  // remove the backquote char
    this._logger('Search text: "' + text + '" at ' + cursor + ' position');
    const gqlCompletionItems = getAutocompleteSuggestions(this._schema, text, p);
    this._logger(JSON.stringify(gqlCompletionItems));
    return translateCompletionItems(gqlCompletionItems);
  }

  getSemanticDiagnostics(delegate: GetSemanticDiagnostics, fileName: string) {
    const errors = delegate(fileName) || [];<commit_msg>chore: add logging<commit_after>import { buildClientSchema } from 'graphql';
import {
  CompletionItem,
  Diagnostic,
  getAutocompleteSuggestions,
  getDiagnostics,
  Position,
} from 'graphql-language-service-interface';
import * as ts from 'typescript/lib/tsserverlibrary';
import { isTagged, TagCondition } from './ts-util/index';

export interface GraphQLLanguageServiceAdapterCreateOptions {
  schema?: any;
  logger?: (msg: string) => void;
  tag?: string;
}

export type GetCompletionAtPosition = ts.LanguageService['getCompletionsAtPosition'];
export type GetSemanticDiagnostics = ts.LanguageService['getSemanticDiagnostics'];

export interface ScriptSourceHelper {
  // getSource: (fileName: string) => ts.SourceFile;
  getAllNodes: (fileName: string, condition) => ts.Node[];
  getNode: (fileName: string, position) => ts.Node;
  getLineAndChar: (fileName: string, position) => ts.LineAndCharacter;
}

export class GraphQLLanguageServiceAdapter {

  private _schema: any;
  private _tagCondition: TagCondition = null;

  constructor(
    private _helper: ScriptSourceHelper,
    opt: GraphQLLanguageServiceAdapterCreateOptions = { },
  ) {
      if (opt.logger) this._logger = opt.logger;
      if (opt.schema) this.updateSchema(opt.schema);
      if (opt.tag) this._tagCondition = opt.tag;
  }

  updateSchema(schema: { data: any }) {
    try {
      this._schema = buildClientSchema(schema.data);
      this._logger('Build client schema.');
    } catch (err) {
      this._logger('Fail to build schema...');
      this._logger(err);
      this._schema = null;
    }
  }

  getCompletionAtPosition(delegate: GetCompletionAtPosition, fileName: string, position: number ) {
    if (!this._schema) return delegate(fileName, position);
    const node = this._helper.getNode(fileName, position);
    if (!node || node.kind !== ts.SyntaxKind.NoSubstitutionTemplateLiteral) {
      return delegate(fileName, position);
    }
    if (this._tagCondition && !isTagged(node, this._tagCondition)) {
      return delegate(fileName, position);
    }
    const cursor = position - node.getStart();
    const baseLC = this._helper.getLineAndChar(fileName, node.getStart());
    const cursorLC = this._helper.getLineAndChar(fileName, position);
    const relativeLC = { line: cursorLC.line - baseLC.line, character: cursorLC.character - baseLC.character + 1 };
    const p = new SimplePosition(relativeLC);
    const text = node.getText().slice(1, cursor + 1);  // remove the backquote char
    this._logger('Search text: "' + text + '" at ' + cursor + ' position');
    const gqlCompletionItems = getAutocompleteSuggestions(this._schema, text, p);
    this._logger(JSON.stringify(gqlCompletionItems));
    return translateCompletionItems(gqlCompletionItems);
  }

  getSemanticDiagnostics(delegate: GetSemanticDiagnostics, fileName: string) {
    const errors = delegate(fileName) || [];
{'fraction_non_alphanumeric': 0.12069267098128389, 'fraction_numerical': 0.001049501486793773, 'mean_word_length': 4.3841807909604515, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5550097', 'n_tokens_mistral': 1629, 'n_tokens_neox': 1645, 'n_words': 383}