Skip to content

Commit

Permalink
fix: multiple fixes (#109)
Browse files Browse the repository at this point in the history
Co-authored-by: hoonoh <hoonoh@users.noreply.github.com>
  • Loading branch information
hoonoh and hoonoh committed Nov 26, 2021
1 parent 735f1ed commit b443795
Show file tree
Hide file tree
Showing 16 changed files with 314 additions and 74 deletions.
2 changes: 1 addition & 1 deletion .releaserc.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ if (packageName === 'ts-slonik-live-server-plugin') {
console.log('loading config for', packageName);
config = {
extends: 'semantic-release-monorepo',
branches: ['main'],
branches: ['main', { name: 'preview', prerelease: true }],
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"release": "lerna run release",
"build": "lerna run build",
"prepare": "husky install && lerna run prepare && lerna link",
"postinstall": "lerna run postinstall && lerna link",
"postinstall": "patch-package && lerna run postinstall && lerna link",
"lint": "lerna run lint",
"test": "lerna run test",
"test:ci": "lerna run test:ci",
Expand Down Expand Up @@ -69,6 +69,7 @@
"lerna": "4.0.0",
"mockdate": "3.0.5",
"node-pg-migrate": "6.0.0",
"patch-package": "^6.4.7",
"prettier": "2.4.1",
"rimraf": "3.0.2",
"semantic-release": "18.0.0",
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion packages/ts-slonik-live-server-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class TsSlonikPlugin {
this.typescript,
info.languageService,
info.project,
new SqlLanguageService(this.pgInfoService, this.sqlDiagnosticService, this.log),
new SqlLanguageService(this.pgInfoService, this.sqlDiagnosticService, this.log, this.config),
{
tags: ['sql'],
enableForStringWithSubstitutions: true,
Expand Down
24 changes: 21 additions & 3 deletions packages/ts-slonik-live-server-plugin/src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,19 @@ type CostConfig = {
threshold: CostThreshold;
};

type PlauginName = {
pluginName: string;
};

export type PluginConfig = {
dotEnv?: string;
debug?: boolean;
pg: PgConfig;
cost: CostConfig;
};
} & Partial<PlauginName>;

export class Config implements DeepReadonly<PluginConfig> {
private defaultConfig: DeepReadonly<PluginConfig> = {
private defaultConfig: DeepReadonly<PluginConfig & PlauginName> = {
debug: false,
pg: {
uri: 'postgres://localhost/postgres',
Expand All @@ -68,9 +72,10 @@ export class Config implements DeepReadonly<PluginConfig> {
warning: 50,
},
},
pluginName: 'ts-slonik-live-server-plugin',
};

private current: DeepReadonly<PluginConfig>;
private current: DeepReadonly<PluginConfig & PlauginName>;

get debug() {
return !!this.current.debug;
Expand All @@ -84,6 +89,18 @@ export class Config implements DeepReadonly<PluginConfig> {
return this.current.cost as DeepReadonly<CostConfig>;
}

get pluginName() {
return this.current.pluginName;
}

get disableKeyword() {
return this.current.pluginName + '-disable';
}

get disableCostErrorKeyword() {
return this.current.pluginName + '-disable-cost-errors';
}

constructor(private info?: ts.server.PluginCreateInfo, private log?: LanguageServiceLogger) {
this.load(info?.config);
}
Expand Down Expand Up @@ -146,6 +163,7 @@ export class Config implements DeepReadonly<PluginConfig> {
warning: config?.cost?.threshold?.warning ?? this.defaultConfig.cost.threshold?.warning,
},
},
pluginName: config?.pluginName ?? this.defaultConfig.pluginName,
};

const configOutput = JSON.stringify(this.current, null, 2);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum DiagnosticCode {
ok = 9846001,
error = 9846002,
costError = 9846003,
costWarning = 9846004,
}
88 changes: 51 additions & 37 deletions packages/ts-slonik-live-server-plugin/src/lib/language-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@ import {
TemplateLanguageService,
} from 'typescript-template-language-service-decorator';

import { Config } from './config';
import { DiagnosticCode } from './diagnostic-code';
import { LanguageServiceLogger } from './logger';
import { PgInfoService } from './pg-info-service';
import { SqlDiagnosticService } from './sql-diagnostic-service';
import { disableCostErrorKeyword, disableKeyword } from './sql-diagnostic-service/constants';
import { getPreviousLine } from './util';

export class SqlLanguageService implements TemplateLanguageService {
constructor(
private pgInfoService: PgInfoService,
private sqlDiagnosticService: SqlDiagnosticService,
private log: LanguageServiceLogger,
private config: Config,
) {}

getCompletionEntryDetails(
Expand All @@ -33,7 +35,7 @@ export class SqlLanguageService implements TemplateLanguageService {
return {
displayParts: [],
kind: ts.ScriptElementKind.keyword,
kindModifiers: 'ts-slonik-live-server-plugin',
kindModifiers: '',
name,
documentation,
};
Expand All @@ -51,79 +53,91 @@ export class SqlLanguageService implements TemplateLanguageService {
};
}

getSemanticDiagnostics = (context: TemplateContext) => {
getSemanticDiagnostics(context: TemplateContext) {
const diagnostic = this.sqlDiagnosticService.checkSqlNode(
context.node.getSourceFile(),
context.node,
);
if (!diagnostic) return [];
return [diagnostic];
};
}

getSupportedCodeFixes() {
return [
DiagnosticCode.ok,
DiagnosticCode.error,
DiagnosticCode.costError,
DiagnosticCode.costWarning,
];
}

getCodeFixesAtPosition = (
getCodeFixesAtPosition(
context: TemplateContext,
start: number,
end: number,
errorCodes: ReadonlyArray<number>,
formatOptions: ts.FormatCodeSettings,
) => {
) {
const sourceText = context.node.getSourceFile().getFullText();

let disableKeywordStart = sourceText.lastIndexOf('\n', context.node.getStart()) + 1;
let disableKeywordLength = 0;
const newLineCharacter = formatOptions.newLineCharacter || '\n';

const disableKeywordStart =
sourceText.lastIndexOf(newLineCharacter, context.node.getStart()) + 1;

const indentation = formatOptions.convertTabsToSpaces
? sourceText.substr(disableKeywordStart).match(new RegExp(/^( +)/))
: sourceText.substr(disableKeywordStart).match(new RegExp(/^(\t+)/));
? sourceText.substring(disableKeywordStart).match(new RegExp(/^( +)/))
: sourceText.substring(disableKeywordStart).match(new RegExp(/^(\t+)/));

const previousLine = getPreviousLine(sourceText, context.node.getStart());

const rtn: ts.CodeAction[] = [];
const span = {
start: disableKeywordStart - context.node.getStart() - 1,
length: 0,
};

const rtn: (ts.CodeAction | ts.CodeFixAction)[] = [];

if (!previousLine.includes(disableCostErrorKeyword)) {
if (
!previousLine.includes(this.config.disableCostErrorKeyword) &&
(errorCodes.includes(DiagnosticCode.costError) ||
errorCodes.includes(DiagnosticCode.costWarning))
) {
rtn.push({
changes: [
{
fileName: context.fileName,
textChanges: [
{
span: {
start: disableKeywordStart - context.node.getStart() - 1,
length: disableKeywordLength,
},
newText: `${indentation?.[0] || ''}// ${disableCostErrorKeyword}\n`,
span,
newText: `${indentation?.[0] || ''}// ${this.config.disableCostErrorKeyword}\n`,
},
],
},
],
description:
'disable ts-slonik-live-server-plugin cost errors for this sql tagged template',
description: `disable ${this.config.pluginName} cost errors for this sql tagged template`,
});
} else {
disableKeywordStart = sourceText.indexOf(previousLine) + 1;
disableKeywordLength = previousLine.length;
}

return [
...rtn,
{
fixName: 'ts-slonik-live-server-plugin-ignore',
} else if (
!previousLine.includes(this.config.disableKeyword) &&
errorCodes.includes(DiagnosticCode.error)
) {
rtn.push({
fixName: this.config.disableKeyword,
changes: [
{
fileName: context.fileName,
textChanges: [
{
span: {
start: disableKeywordStart - context.node.getStart() - 1,
length: disableKeywordLength,
},
newText: `${indentation?.[0] || ''}// ${disableKeyword}\n`,
span,
newText: `${indentation?.[0] || ''}// ${this.config.disableKeyword}\n`,
},
],
},
],
description: 'disable ts-slonik-live-server-plugin for this sql tagged template',
},
];
};
description: `disable ${this.config.pluginName} for this sql tagged template`,
});
}

return rtn;
}
}
8 changes: 4 additions & 4 deletions packages/ts-slonik-live-server-plugin/src/lib/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class LanguageServiceLogger implements Logger {
}

static log(msg: string) {
LanguageServiceLogger.logger?.info(`[${LanguageServiceLogger.head}] ${msg}`);
LanguageServiceLogger.logger?.info(`${LanguageServiceLogger.head} ${msg}`);
}

static debugGroupStart() {
Expand All @@ -85,14 +85,14 @@ export class LanguageServiceLogger implements Logger {
static debug(msg: MessageType): void;
static debug(msgGenerator: () => MessageType | MessageType[]): void;
static debug(stringOrGenerator: any) {
if (LanguageServiceLogger.isDebugEnabled) {
if (typeof stringOrGenerator === 'string') {
if (LanguageServiceLogger.logger?.loggingEnabled() && LanguageServiceLogger.isDebugEnabled) {
if (typeof stringOrGenerator !== 'function') {
LanguageServiceLogger.logger?.info(
`${LanguageServiceLogger.head}debug: ${' '.repeat(
LanguageServiceLogger.debugGroup * 2,
)}${LanguageServiceLogger.parseMessage(stringOrGenerator)}`,
);
} else if (LanguageServiceLogger.logger?.loggingEnabled()) {
} else {
LanguageServiceLogger.logger?.info(
`${LanguageServiceLogger.head}debug: ${' '.repeat(
LanguageServiceLogger.debugGroup * 2,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
/* eslint-disable class-methods-use-this */
import { createHash } from 'crypto';
import { QueryResult } from 'pg';
import ts from 'typescript/lib/tsserverlibrary';

import { Config } from '../config';
import { DiagnosticCode } from '../diagnostic-code';
import { LanguageServiceLogger } from '../logger';
import { PgError, pgQuery } from '../pg/query';
import { getPreviousLine } from '../util';
import { disableCostErrorKeyword, disableKeyword, disablerErrorCode } from './constants';
import { SqlTemplteLiteralHandler } from './handlers/sql-template-literal';
import { SqlDiagnostic, SqlInfo } from './types';
import { getErrorPosition } from './util/error-position';
Expand Down Expand Up @@ -79,14 +78,15 @@ export class SqlDiagnosticService {

findSqlNodes = (sourceFile: ts.SourceFile, includeAll = false) => {
const result: ts.Node[] = [];
const config = this.config;
function recurse(node: ts.Node) {
if (ts.isTaggedTemplateExpression(node) && node.tag.getText() === 'sql') {
// check if previous line includes disable statment
const lastLine = getPreviousLine(sourceFile.text, node.getStart());
if (
includeAll ||
lastLine.includes(disableCostErrorKeyword) ||
!lastLine.includes(disableKeyword)
lastLine.includes(config.disableCostErrorKeyword) ||
!lastLine.includes(config.disableKeyword)
) {
result.push(node);
}
Expand All @@ -106,8 +106,8 @@ export class SqlDiagnosticService {
if (!typeChecker) throw new Error('typechecker not found?');

const previousLine = getPreviousLine(sourceFile.text, sqlNode.getStart());
const costErrorEnabled = !previousLine.includes(disableCostErrorKeyword);
const checkEnabled = !costErrorEnabled || !previousLine.includes(disableKeyword);
const costErrorEnabled = !previousLine.includes(this.config.disableCostErrorKeyword);
const checkEnabled = !costErrorEnabled || !previousLine.includes(this.config.disableKeyword);
if (!checkEnabled) return undefined;

this.log.debug(() => [`checkSqlNodes start`]);
Expand Down Expand Up @@ -180,14 +180,26 @@ export class SqlDiagnosticService {
category: ts.DiagnosticCategory,
messageText: string,
position?: { start: number; length: number },
isCostErrorEnabled = true,
isCostError = false,
) => {
if (!position && category === ts.DiagnosticCategory.Suggestion) {
position = {
start: -sqlNode.parent.getText().indexOf(sqlNode.getText()) - 1,
length: 3, // vscode seems to always set length to 1 when diagnostic category is suggestion
};
}

let code = DiagnosticCode.ok;
if (isCostError) {
if (category === ts.DiagnosticCategory.Warning) {
code = DiagnosticCode.costWarning;
} else if (category === ts.DiagnosticCategory.Error) {
code = DiagnosticCode.costError;
}
} else if (ts.DiagnosticCategory.Error) {
code = DiagnosticCode.error;
}

const sqlDiagnostic: SqlDiagnostic = {
...sqlInfoPartial,
raw,
Expand All @@ -197,12 +209,12 @@ export class SqlDiagnosticService {
file: sourceFile,
start: position?.start ?? 0,
length: position?.length ?? sqlNode.getEnd() - sqlNode.getStart(),
source: 'ts-slonik-live-server-plugin',
code: disablerErrorCode,
category: !isCostErrorEnabled ? ts.DiagnosticCategory.Suggestion : category,
source: this.config.pluginName,
code,
category: isCostError && !costErrorEnabled ? ts.DiagnosticCategory.Suggestion : category,
messageText,
},
costErrorEnabled: isCostErrorEnabled,
costErrorEnabled,
};
this.updateCachedDiagnostic(sqlDiagnostic);
this.log.debug(() => [`took`, Date.now() - now]);
Expand Down Expand Up @@ -312,7 +324,7 @@ export class SqlDiagnosticService {
ts.DiagnosticCategory.Error,
`explain cost error threshold: ${cost}${debugQuery(raw)}`,
undefined,
costErrorEnabled,
true,
);
}
if (this.config.cost.threshold.warning && cost > this.config.cost.threshold.warning) {
Expand All @@ -321,7 +333,7 @@ export class SqlDiagnosticService {
ts.DiagnosticCategory.Warning,
`explain cost warning: ${cost}${debugQuery(raw)}`,
undefined,
costErrorEnabled,
true,
);
}
if (this.config.cost.info) {
Expand Down
Loading

0 comments on commit b443795

Please sign in to comment.