Skip to content

Commit

Permalink
feat: Use native LSP logger (graphql#3148)
Browse files Browse the repository at this point in the history
  • Loading branch information
mskelton authored May 9, 2023
1 parent 083ca10 commit 0600749
Show file tree
Hide file tree
Showing 14 changed files with 47 additions and 196 deletions.
7 changes: 7 additions & 0 deletions .changeset/stale-experts-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"graphql-language-service-cli": patch
"graphql-language-service-server": minor
"graphql-language-service": patch
---

Use native LSP logger instead of manual file based logging. This fixes errors in Neovim when using the GraphQL LSP.
7 changes: 4 additions & 3 deletions packages/graphql-language-service-cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import yargs from 'yargs';
import client from './client';

import { Logger, startServer } from 'graphql-language-service-server';
import { startServer } from 'graphql-language-service-server';

const { argv } = yargs
.usage(
Expand Down Expand Up @@ -128,8 +128,9 @@ if (command === 'server') {
}
// eslint-disable-next-line promise/prefer-await-to-then -- don't know if I can use top level await here
startServer(options).catch(error => {
const logger = new Logger();
logger.error(String(error));
process.stderr.write(
'An error was thrown from GraphQL language service: ' + String(error),
);
});
} else {
client(command as string, argv as Record<string, string>);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type {
ObjectTypeInfo,
Uri,
} from 'graphql-language-service';
import type { Logger } from 'vscode-languageserver';

import * as fs from 'node:fs';
import { readFile } from 'node:fs/promises';
Expand All @@ -41,7 +42,6 @@ import stringToHash from './stringToHash';
import glob from 'glob';
import { LoadConfigOptions } from './types';
import { URI } from 'vscode-uri';
import { Logger } from './Logger';

// Maximum files to read when processing GraphQL files.
const MAX_READS = 200;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,13 @@ import {

import { GraphQLConfig, GraphQLProjectConfig } from 'graphql-config';

import type { Logger } from 'vscode-languageserver';
import {
Hover,
SymbolInformation,
SymbolKind,
} from 'vscode-languageserver-types';

import { Logger } from './Logger';

const KIND_TO_SYMBOL_KIND: { [key: string]: SymbolKind } = {
[Kind.FIELD]: SymbolKind.Field,
[Kind.OPERATION_DEFINITION]: SymbolKind.Class,
Expand Down
85 changes: 11 additions & 74 deletions packages/graphql-language-service-server/src/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,94 +8,31 @@
*/

import { Logger as VSCodeLogger } from 'vscode-jsonrpc';
import { DiagnosticSeverity } from 'vscode-languageserver';

import * as fs from 'node:fs';
import * as os from 'node:os';
import { join } from 'node:path';
import { Socket } from 'node:net';

import {
DIAGNOSTIC_SEVERITY,
SeverityEnum,
SEVERITY,
} from 'graphql-language-service';
import { Connection } from 'vscode-languageserver';

export class Logger implements VSCodeLogger {
_logFilePath: string;
_stderrOnly: boolean;

constructor(tmpDir?: string, stderrOnly?: boolean) {
const dir = join(tmpDir || os.tmpdir(), 'graphql-language-service-logs');
try {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
} catch {
// intentionally no-op. Don't block the language server even if
// the necessary setup cannot be completed for logger.
}

this._logFilePath = join(
dir,
`graphql-language-service-log-${
os.userInfo().username
}-${getDateString()}.log`,
);

this._stderrOnly = stderrOnly || false;
}
constructor(private _connection: Connection) {}

error(message: string): void {
this._log(message, SEVERITY.Error);
this._connection.console.error(message);
}

warn(message: string): void {
this._log(message, SEVERITY.Warning);
this._connection.console.warn(message);
}

info(message: string): void {
this._log(message, SEVERITY.Information);
this._connection.console.info(message);
}

log(message: string): void {
this._log(message, SEVERITY.Hint);
}

_log(message: string, severityKey: SeverityEnum): void {
const timestamp = new Date().toLocaleString();
const severity = DIAGNOSTIC_SEVERITY[severityKey];
const { pid } = process;

const stringMessage = String(message).trim();
const logMessage = `${timestamp} [${severity}] (pid: ${pid}) graphql-language-service-usage-logs: ${stringMessage}\n`;
// write to the file in tmpdir
fs.appendFile(this._logFilePath, logMessage, _error => {});
// @TODO: enable with debugging
if (severityKey !== SEVERITY.Hint) {
this._getOutputStream(severity).write(logMessage, err => {
if (err) {
// eslint-disable-next-line no-console
console.error(err);
}
});
}
}

_getOutputStream(severity: DiagnosticSeverity): Socket {
if (this._stderrOnly || severity === DIAGNOSTIC_SEVERITY.Error) {
return process.stderr;
}

return process.stdout;
this._connection.console.log(message);
}
}

// function getUnixTime() {
// return new Date().getTime() / 1000;
// }

function getDateString() {
const date = new Date();
return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
export class NoopLogger implements VSCodeLogger {
error() {}
warn() {}
info() {}
log() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ import type {
WorkspaceSymbolParams,
Connection,
DidChangeConfigurationRegistrationOptions,
Logger,
} from 'vscode-languageserver/node';

import type { UnnormalizedTypeDefPointer } from '@graphql-tools/load';

import { getGraphQLCache, GraphQLCache } from './GraphQLCache';
import { parseDocument, DEFAULT_SUPPORTED_EXTENSIONS } from './parseDocument';

import { Logger } from './Logger';
import { printSchema, visit, parse, FragmentDefinitionNode } from 'graphql';
import { tmpdir } from 'node:os';
import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { GraphQLConfig } from 'graphql-config';
import { GraphQLLanguageService } from '../GraphQLLanguageService';
import { SymbolKind } from 'vscode-languageserver-protocol';
import { Position } from 'graphql-language-service';
import { Logger } from '../Logger';
import { NoopLogger } from '../Logger';

const MOCK_CONFIG = {
filepath: join(__dirname, '.graphqlrc.yml'),
Expand Down Expand Up @@ -122,7 +122,7 @@ describe('GraphQLLanguageService', () => {
beforeEach(() => {
languageService = new GraphQLLanguageService(
mockCache as any,
new Logger(),
new NoopLogger(),
);
});

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* LICENSE file in the root directory of this source tree.
*
*/
import { tmpdir } from 'node:os';
import { SymbolKind } from 'vscode-languageserver';
import { FileChangeType } from 'vscode-languageserver-protocol';
import { Position, Range } from 'graphql-language-service';
Expand All @@ -22,7 +21,7 @@ import { loadConfig } from 'graphql-config';

import type { DefinitionQueryResult, Outline } from 'graphql-language-service';

import { Logger } from '../Logger';
import { NoopLogger } from '../Logger';
import { pathToFileURL } from 'node:url';

jest.mock('node:fs', () => ({
Expand All @@ -31,7 +30,7 @@ jest.mock('node:fs', () => ({
}));

describe('MessageProcessor', () => {
const logger = new Logger(tmpdir());
const logger = new NoopLogger();
const messageProcessor = new MessageProcessor({
// @ts-ignore
connection: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@
* LICENSE file in the root directory of this source tree.
*
*/
import { tmpdir } from 'node:os';

import { findGraphQLTags as baseFindGraphQLTags } from '../findGraphQLTags';

jest.mock('../Logger');

import { Logger } from '../Logger';
import { NoopLogger } from '../Logger';

describe('findGraphQLTags', () => {
const logger = new Logger(tmpdir());
const logger = new NoopLogger();
const findGraphQLTags = (text: string, ext: string) =>
baseFindGraphQLTags(text, ext, '', logger);

Expand Down Expand Up @@ -296,12 +295,7 @@ query {id}`);
.spyOn(process.stderr, 'write')
.mockImplementation(() => true);

const contents = baseFindGraphQLTags(
text,
'.svelte',
'',
new Logger(tmpdir(), false),
);
const contents = baseFindGraphQLTags(text, '.svelte', '', new NoopLogger());
// We should have no contents
expect(contents).toMatchObject([]);

Expand All @@ -318,12 +312,7 @@ query {id}`);
.spyOn(process.stderr, 'write')
.mockImplementation(() => true);

const contents = baseFindGraphQLTags(
text,
'.svelte',
'',
new Logger(tmpdir(), false),
);
const contents = baseFindGraphQLTags(text, '.svelte', '', new NoopLogger());
// We should have no contents
expect(contents).toMatchObject([]);

Expand All @@ -340,12 +329,7 @@ query {id}`);
.spyOn(process.stderr, 'write')
.mockImplementation(() => true);

const contents = baseFindGraphQLTags(
text,
'.svelte',
'',
new Logger(tmpdir(), false),
);
const contents = baseFindGraphQLTags(text, '.svelte', '', new NoopLogger());
// We should have no contents
expect(contents).toMatchObject([]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { Position, Range } from 'graphql-language-service';

import { parse, ParserOptions, ParserPlugin } from '@babel/parser';
import * as VueParser from '@vue/compiler-sfc';
import { Logger } from './Logger';
import type { Logger } from 'vscode-languageserver';

// Attempt to be as inclusive as possible of source text.
const PARSER_OPTIONS: ParserOptions = {
Expand Down
2 changes: 0 additions & 2 deletions packages/graphql-language-service-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ export { MessageProcessor } from './MessageProcessor';

export { default as startServer } from './startServer';

export { Logger } from './Logger';

export * from './GraphQLCache';
export * from './parseDocument';
export * from './findGraphQLTags';
5 changes: 3 additions & 2 deletions packages/graphql-language-service-server/src/parseDocument.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { extname } from 'node:path';
import type { CachedContent } from 'graphql-language-service';
import { Range, Position } from 'graphql-language-service';
import type { Logger } from 'vscode-languageserver';

import { findGraphQLTags, DEFAULT_TAGS } from './findGraphQLTags';
import { Logger } from './Logger';
import { NoopLogger } from './Logger';

export const DEFAULT_SUPPORTED_EXTENSIONS = [
'.js',
Expand Down Expand Up @@ -48,7 +49,7 @@ export function parseDocument(
uri: string,
fileExtensions: string[] = DEFAULT_SUPPORTED_EXTENSIONS,
graphQLFileExtensions: string[] = DEFAULT_SUPPORTED_GRAPHQL_EXTENSIONS,
logger: Logger = new Logger(),
logger: Logger = new NoopLogger(),
): CachedContent[] {
// Check if the text content includes a GraphQLV query.
// If the text doesn't include GraphQL queries, do not proceed.
Expand Down
Loading

0 comments on commit 0600749

Please sign in to comment.