Skip to content

Commit c1053fd

Browse files
committed
fix log level, keep things relevant
1 parent 9b6304c commit c1053fd

File tree

8 files changed

+179
-41
lines changed

8 files changed

+179
-41
lines changed

packages/graphql-language-service-server/src/Logger.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,48 @@ import { Logger as VSCodeLogger } from 'vscode-jsonrpc';
1111
import { Connection } from 'vscode-languageserver';
1212

1313
export class Logger implements VSCodeLogger {
14-
constructor(private _connection: Connection) {}
14+
// TODO: allow specifying exact log level?
15+
// for now this is to handle the debug setting
16+
private logLevel: number;
17+
constructor(
18+
private _connection: Connection,
19+
debug?: boolean,
20+
) {
21+
this.logLevel = debug ? 1 : 0;
22+
// first detect the debug flag on initialization
23+
void (async () => {
24+
try {
25+
const config = await this._connection?.workspace?.getConfiguration(
26+
'vscode-graphql',
27+
);
28+
const debugSetting = config?.get('debug');
29+
if (debugSetting === true) {
30+
this.logLevel = 1;
31+
}
32+
if (debugSetting === false || debugSetting === null) {
33+
this.logLevel = 0;
34+
}
35+
} catch {
36+
// ignore
37+
}
38+
})();
39+
// then watch for it to change. doesn't require re-creating the logger!
40+
this._connection?.onDidChangeConfiguration(config => {
41+
const debugSetting =
42+
config?.settings && config.settings['vscode-graphql']?.debug;
43+
// if it's undefined, it's not being passed
44+
if (debugSetting === undefined) {
45+
return;
46+
}
47+
// if it's true, set it to 1, we will eventually do log levels properly
48+
if (debugSetting === true) {
49+
this.logLevel = 1;
50+
}
51+
if (debugSetting === false || debugSetting === null) {
52+
this.logLevel = 0;
53+
}
54+
});
55+
}
1556

1657
error(message: string): void {
1758
this._connection.console.error(message);
@@ -26,7 +67,9 @@ export class Logger implements VSCodeLogger {
2667
}
2768

2869
log(message: string): void {
29-
this._connection.console.log(message);
70+
if (this.logLevel > 0) {
71+
this._connection.console.log(message);
72+
}
3073
}
3174
}
3275

packages/graphql-language-service-server/src/MessageProcessor.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,14 @@ export class MessageProcessor {
255255
const config = this._graphQLCache.getGraphQLConfig();
256256
if (config) {
257257
await this._cacheAllProjectFiles(config);
258+
// TODO: per project lazy instantiation.
259+
// we had it working before, but it seemed like it caused bugs
260+
// which were caused by something else.
261+
// thus. _isInitialized should be replaced with something like
262+
// projectHasInitialized: (projectName: string) => boolean
258263
this._isInitialized = true;
259264
this._isGraphQLConfigMissing = false;
265+
this._logger.info('GraphQL Language Server caches initialized');
260266
}
261267
} catch (err) {
262268
this._handleConfigError({ err });
@@ -387,9 +393,6 @@ export class MessageProcessor {
387393
// i think this is because if the file change is empty, it doesn't get parsed
388394
// TODO: this could be related to a bug in how we are calling didOpenOrSave in our tests
389395
// that doesn't reflect the real runtime behavior
390-
// if (!text || text.length < 1) {
391-
// return { uri, diagnostics };
392-
// }
393396

394397
const { contents } = await this._parseAndCacheFile(
395398
uri,
@@ -963,8 +966,8 @@ export class MessageProcessor {
963966
await this._invalidateCache({ version, uri }, uri, contents);
964967
await this._updateObjectTypeDefinition(uri, contents, project);
965968
}
966-
} catch {
967-
// this._logger.error(String(err));
969+
} catch (err) {
970+
this._logger.error(String(err));
968971
}
969972
}
970973
private async _cacheSchemaFile(
@@ -1158,8 +1161,19 @@ export class MessageProcessor {
11581161
return Promise.all(
11591162
Object.keys(config.projects).map(async projectName => {
11601163
const project = config.getProject(projectName);
1164+
11611165
await this._cacheSchemaFilesForProject(project);
1162-
await this._cacheDocumentFilesforProject(project);
1166+
if (project.documents?.length) {
1167+
await this._cacheDocumentFilesforProject(project);
1168+
} else {
1169+
this._logger.warn(
1170+
[
1171+
`No 'documents' config found for project: ${projectName}.`,
1172+
'Fragments and query documents cannot be detected.',
1173+
'LSP server will only perform some partial validation and SDL features.',
1174+
].join('\n'),
1175+
);
1176+
}
11631177
}),
11641178
);
11651179
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Logger } from '../Logger';
2+
3+
describe('Logger', () => {
4+
const connection = {
5+
console: {
6+
error: jest.fn(),
7+
warn: jest.fn(),
8+
info: jest.fn(),
9+
log: jest.fn(),
10+
},
11+
onDidChangeConfiguration: jest.fn(),
12+
workspace: {
13+
getConfiguration: jest.fn(),
14+
},
15+
};
16+
17+
beforeEach(() => {
18+
jest.clearAllMocks();
19+
});
20+
21+
it('should initialize with default log level, and ignore .log intentionally', () => {
22+
const logger = new Logger(connection as any);
23+
expect(logger).toBeDefined();
24+
expect(connection.onDidChangeConfiguration).toHaveBeenCalledTimes(1);
25+
expect(logger.logLevel).toBe(0);
26+
logger.log('test');
27+
expect(connection.console.log).toHaveBeenCalledTimes(0);
28+
});
29+
30+
it('should initialize with default log level, then change to logging with new settings, then back when they are disabled', () => {
31+
const logger = new Logger(connection as any);
32+
expect(logger).toBeDefined();
33+
expect(connection.onDidChangeConfiguration).toHaveBeenCalledTimes(1);
34+
expect(logger.logLevel).toBe(0);
35+
logger.log('test');
36+
expect(connection.console.log).toHaveBeenCalledTimes(0);
37+
connection.onDidChangeConfiguration.mock.calls[0][0]({
38+
settings: { 'vscode-graphql': { debug: true } },
39+
});
40+
expect(logger.logLevel).toBe(1);
41+
logger.log('test');
42+
expect(connection.console.log).toHaveBeenCalledTimes(1);
43+
connection.onDidChangeConfiguration.mock.calls[0][0]({
44+
settings: { 'vscode-graphql': { debug: false } },
45+
});
46+
expect(logger.logLevel).toBe(0);
47+
logger.log('test');
48+
// and not a second time
49+
expect(connection.console.log).toHaveBeenCalledTimes(1);
50+
});
51+
52+
it('should not change log level when settings are not passed', () => {
53+
const logger = new Logger(connection as any, true);
54+
expect(logger).toBeDefined();
55+
expect(connection.onDidChangeConfiguration).toHaveBeenCalledTimes(1);
56+
expect(logger.logLevel).toBe(1);
57+
logger.log('test');
58+
expect(connection.console.log).toHaveBeenCalledTimes(1);
59+
connection.onDidChangeConfiguration.mock.calls[0][0]({});
60+
expect(logger.logLevel).toBe(1);
61+
logger.log('test');
62+
expect(connection.console.log).toHaveBeenCalledTimes(2);
63+
});
64+
65+
it('should initialize with debug log level, and .log is visible now', () => {
66+
const logger = new Logger(connection as any, true);
67+
expect(logger).toBeDefined();
68+
expect(connection.onDidChangeConfiguration).toHaveBeenCalledTimes(1);
69+
expect(logger.logLevel).toBe(1);
70+
logger.log('test');
71+
expect(connection.console.log).toHaveBeenCalledTimes(1);
72+
});
73+
});

packages/graphql-language-service-server/src/parsers/astro.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ function parseAstro(source: string): ParseAstroResult {
4141
return { type: 'error', errors: ['Could not find frontmatter block'] };
4242
}
4343

44-
export const astroParser: SourceParser = (text, _uri, _logger) => {
44+
export const astroParser: SourceParser = (text, uri, logger) => {
4545
const parseAstroResult = parseAstro(text);
4646
if (parseAstroResult.type === 'error') {
47-
// logger.error(
48-
// `Could not parse the astro file at ${uri} to extract the graphql tags:`,
49-
// );
50-
// for (const error of parseAstroResult.errors) {
51-
// logger.error(String(error));
52-
// }
47+
logger.info(
48+
`Could not parse the astro file at ${uri} to extract the graphql tags:`,
49+
);
50+
for (const error of parseAstroResult.errors) {
51+
logger.info(String(error));
52+
}
5353
return null;
5454
}
5555

packages/graphql-language-service-server/src/parsers/babel.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,26 @@ export const babelParser = (text: string, plugins?: ParserPlugin[]) => {
1111
return parse(text, PARSER_OPTIONS);
1212
};
1313

14-
export const ecmaParser: SourceParser = (text, _uri, _logger) => {
14+
export const ecmaParser: SourceParser = (text, uri, logger) => {
1515
try {
1616
return { asts: [babelParser(text, ['flow', 'flowComments'])] };
17-
} catch {
18-
// logger.error(
19-
// `Could not parse the JavaScript file at ${uri} to extract the graphql tags:`,
20-
// );
21-
// logger.error(String(error));
17+
} catch (error) {
18+
logger.info(
19+
`Could not parse the JavaScript file at ${uri} to extract the graphql tags:`,
20+
);
21+
logger.info(String(error));
2222
return null;
2323
}
2424
};
2525

26-
export const tsParser: SourceParser = (text, _uri, _logger) => {
26+
export const tsParser: SourceParser = (text, uri, logger) => {
2727
try {
2828
return { asts: [babelParser(text, ['typescript'])] };
29-
} catch {
30-
// logger.error(
31-
// `Could not parse the TypeScript file at ${uri} to extract the graphql tags:`,
32-
// );
33-
// logger.error(String(error));
29+
} catch (error) {
30+
logger.info(
31+
`Could not parse the TypeScript file at ${uri} to extract the graphql tags:`,
32+
);
33+
logger.info(String(error));
3434
return null;
3535
}
3636
};

packages/graphql-language-service-server/src/parsers/svelte.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { SourceMapConsumer } from 'source-map-js';
44
import { Position, Range } from 'graphql-language-service';
55
import type { RangeMapper, SourceParser } from './types';
66

7-
export const svelteParser: SourceParser = (text, uri, _logger) => {
7+
export const svelteParser: SourceParser = (text, uri, logger) => {
88
const svelteResult = svelte2tsx(text, {
99
filename: uri,
1010
});
@@ -35,11 +35,11 @@ export const svelteParser: SourceParser = (text, uri, _logger) => {
3535
asts: [babelParser(svelteResult.code, ['typescript'])],
3636
rangeMapper,
3737
};
38-
} catch {
39-
// logger.error(
40-
// `Could not parse the Svelte file at ${uri} to extract the graphql tags:`,
41-
// );
42-
// logger.error(String(error));
38+
} catch (error) {
39+
logger.info(
40+
`Could not parse the Svelte file at ${uri} to extract the graphql tags:`,
41+
);
42+
logger.info(String(error));
4343
return null;
4444
}
4545
};

packages/graphql-language-service-server/src/parsers/vue.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,16 @@ export function parseVueSFC(source: string): ParseVueSFCResult {
4545
};
4646
}
4747

48-
export const vueParser: SourceParser = (text, _uri, _logger) => {
48+
export const vueParser: SourceParser = (text, uri, logger) => {
4949
const asts = [];
5050
const parseVueSFCResult = parseVueSFC(text);
5151
if (parseVueSFCResult.type === 'error') {
52-
// logger.error(
53-
// `Could not parse the vue file at ${uri} to extract the graphql tags:`,
54-
// );
55-
// for (const error of parseVueSFCResult.errors) {
56-
// logger.error(String(error));
57-
// }
52+
logger.info(
53+
`Could not parse the vue file at ${uri} to extract the graphql tags:`,
54+
);
55+
for (const error of parseVueSFCResult.errors) {
56+
logger.info(String(error));
57+
}
5858
return null;
5959
}
6060

packages/graphql-language-service-server/src/startServer.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,14 @@ export interface ServerOptions {
102102
* the temporary directory that the server writes to for logs and caching schema
103103
*/
104104
tmpDir?: string;
105+
106+
/**
107+
* debug mode
108+
*
109+
* same as with the client reference implementation, the debug setting controls logging output
110+
* this allows all logger.info() messages to come through. by default, the highest level is warn
111+
*/
112+
debug?: true;
105113
}
106114

107115
/**
@@ -217,7 +225,7 @@ async function initializeHandlers({
217225
options,
218226
}: InitializerParams): Promise<Connection> {
219227
const connection = createConnection(reader, writer);
220-
const logger = new Logger(connection);
228+
const logger = new Logger(connection, options.debug);
221229

222230
try {
223231
await addHandlers({ connection, logger, ...options });

0 commit comments

Comments
 (0)