Skip to content

Commit 3bf0cd6

Browse files
committed
Refactor SQL syntax checker to improve document size handling and error messaging
Signed-off-by: worksofliam <[email protected]>
1 parent e4d298a commit 3bf0cd6

File tree

1 file changed

+108
-99
lines changed

1 file changed

+108
-99
lines changed

src/language/providers/problemProvider.ts

Lines changed: 108 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export const problemProvider = [
8686
if (isSql) {
8787
if (checkerAvailable() && !isSafeDocument(e)) {
8888
const basename = e.fileName ? path.basename(e.fileName) : `Untitled`;
89-
window.showWarningMessage(`${basename}: the SQL syntax checker is disabled for this document because it is too large.`);
89+
documentLargeError(basename);
9090
}
9191

9292
if (checkOnOpen()) {
@@ -121,132 +121,137 @@ interface SqlDiagnostic extends Diagnostic {
121121
async function validateSqlDocument(document: TextDocument, specificStatement?: number) {
122122
const checker = SQLStatementChecker.get();
123123
if (remoteAssistIsEnabled() && checker && !checkerRunning) {
124-
setCheckerRunningContext(true);
125-
const sqlDocument = getSqlDocument(document);
126-
127-
if (sqlDocument) {
128-
const allGroups = sqlDocument.getStatementGroups();
129-
130-
let statementRanges: StatementRange[] = [];
131-
132-
for (let i = 0; i < allGroups.length; i++) {
133-
const group = allGroups[i];
134-
if (specificStatement) {
135-
// If specificStatement is outside this group, continue
136-
if (
137-
specificStatement < group.range.start ||
138-
(specificStatement > (allGroups[i + 1] ? allGroups[i + 1].range.start : group.range.end))
139-
) {
140-
continue;
124+
const basename = document.fileName ? path.basename(document.fileName) : `Untitled`;
125+
if (isSafeDocument(document)) {
126+
setCheckerRunningContext(true);
127+
const sqlDocument = getSqlDocument(document);
128+
129+
if (sqlDocument) {
130+
const allGroups = sqlDocument.getStatementGroups();
131+
132+
let statementRanges: StatementRange[] = [];
133+
134+
for (let i = 0; i < allGroups.length; i++) {
135+
const group = allGroups[i];
136+
if (specificStatement) {
137+
// If specificStatement is outside this group, continue
138+
if (
139+
specificStatement < group.range.start ||
140+
(specificStatement > (allGroups[i + 1] ? allGroups[i + 1].range.start : group.range.end))
141+
) {
142+
continue;
143+
}
141144
}
142-
}
143145

144-
const range = getStatementRangeFromGroup(group, i);
146+
const range = getStatementRangeFromGroup(group, i);
145147

146-
if (range) {
147-
statementRanges.push(range);
148-
}
148+
if (range) {
149+
statementRanges.push(range);
150+
}
149151

150-
// We also add the surrounding ranges, as we need to check the end of the statement
151-
if (specificStatement) {
152-
for (let j = i - 1; j <= i + 1; j++) {
153-
if (allGroups[j]) {
154-
const nextRange = getStatementRangeFromGroup(allGroups[j], j);
155-
if (nextRange && !statementRanges.some(r => r.groupId === nextRange.groupId)) {
156-
statementRanges.push(nextRange);
152+
// We also add the surrounding ranges, as we need to check the end of the statement
153+
if (specificStatement) {
154+
for (let j = i - 1; j <= i + 1; j++) {
155+
if (allGroups[j]) {
156+
const nextRange = getStatementRangeFromGroup(allGroups[j], j);
157+
if (nextRange && !statementRanges.some(r => r.groupId === nextRange.groupId)) {
158+
statementRanges.push(nextRange);
159+
}
157160
}
158161
}
159-
}
160-
161-
break;
162-
}
163-
}
164162

165-
166-
if (statementRanges.length > 0) {
167-
const basename = document.fileName ? path.basename(document.fileName) : `Untitled`;
168-
const validStatements = statementRanges.filter(r => r.validate);
169-
170-
if (validStatements.length > MAX_STATEMENT_COUNT) {
171-
window.showWarningMessage(`${basename}: the SQL syntax checker cannot run because the statement limit has been reached (${validStatements.length} of ${MAX_STATEMENT_COUNT} max).`);
172-
return;
163+
break;
164+
}
173165
}
174166

175-
const invalidStatements = statementRanges.filter(r => !r.validate);
176-
const sqlStatementContents = validStatements.map(range => sqlDocument.content.substring(range.start, range.end));
177167

178-
if (validStatements.length > 0) {
179-
const se = performance.now();
168+
if (statementRanges.length > 0) {
169+
const validStatements = statementRanges.filter(r => r.validate);
180170

181-
let syntaxChecked: SqlSyntaxError[]|undefined;
182-
try {
183-
syntaxChecked = await window.withProgress({ location: ProgressLocation.Window, title: `$(sync-spin) Checking SQL Syntax` }, () => { return checker.checkMultipleStatements(sqlStatementContents) });
184-
} catch (e) {
185-
window.showErrorMessage(`${basename}: the SQL syntax checker failed to run. ${e.message}`);
186-
syntaxChecked = undefined;
187-
}
171+
if (validStatements.length > MAX_STATEMENT_COUNT) {
172+
window.showWarningMessage(`${basename}: the SQL syntax checker cannot run because the statement limit has been reached (${validStatements.length} of ${MAX_STATEMENT_COUNT} max).`);
173+
174+
} else {
188175

189-
const ee = performance.now();
176+
const invalidStatements = statementRanges.filter(r => !r.validate);
177+
const sqlStatementContents = validStatements.map(range => sqlDocument.content.substring(range.start, range.end));
190178

191-
if (syntaxChecked) {
192-
if (syntaxChecked.length > 0) {
193-
let currentErrors: SqlDiagnostic[] = specificStatement ? languages.getDiagnostics(document.uri) as SqlDiagnostic[] : [];
179+
if (validStatements.length > 0) {
180+
const se = performance.now();
194181

195-
// Remove old CL errors.
196-
for (const invalidStatement of invalidStatements) {
197-
const existingError = currentErrors.findIndex(e => e.groupId === invalidStatement.groupId);
198-
if (existingError >= 0) {
199-
currentErrors.splice(existingError, 1);
200-
}
182+
let syntaxChecked: SqlSyntaxError[] | undefined;
183+
try {
184+
syntaxChecked = await window.withProgress({ location: ProgressLocation.Window, title: `$(sync-spin) Checking SQL Syntax` }, () => { return checker.checkMultipleStatements(sqlStatementContents) });
185+
} catch (e) {
186+
window.showErrorMessage(`${basename}: the SQL syntax checker failed to run. ${e.message}`);
187+
syntaxChecked = undefined;
201188
}
202189

203-
for (let i = 0; i < validStatements.length; i++) {
204-
const currentRange = validStatements[i];
205-
const groupError = syntaxChecked[i];
206-
let existingError: number = currentErrors.findIndex(e => e.groupId === currentRange.groupId);
190+
const ee = performance.now();
207191

208-
if (groupError.type === `none`) {
209-
if (existingError !== -1) {
210-
currentErrors.splice(existingError, 1);
211-
}
212-
213-
} else if (shouldShowError(groupError)) {
214-
let baseIndex = () => { return currentRange.start + groupError.offset };
192+
if (syntaxChecked) {
193+
if (syntaxChecked.length > 0) {
194+
let currentErrors: SqlDiagnostic[] = specificStatement ? languages.getDiagnostics(document.uri) as SqlDiagnostic[] : [];
215195

216-
if (baseIndex() > currentRange.end) {
217-
// This is a syntax error that is outside the range of the statement.
218-
groupError.offset = (currentRange.end - currentRange.start);
196+
// Remove old CL errors.
197+
for (const invalidStatement of invalidStatements) {
198+
const existingError = currentErrors.findIndex(e => e.groupId === invalidStatement.groupId);
199+
if (existingError >= 0) {
200+
currentErrors.splice(existingError, 1);
201+
}
219202
}
220203

221-
const selectedWord = document.getWordRangeAtPosition(document.positionAt(baseIndex()))
222-
|| new Range(
223-
document.positionAt(baseIndex() - 1),
224-
document.positionAt(baseIndex())
225-
);
226-
227-
228-
const newDiag: SqlDiagnostic = {
229-
message: `${groupError.text} - ${groupError.sqlstate}`,
230-
code: groupError.sqlid,
231-
range: selectedWord,
232-
severity: diagnosticTypeMap[groupError.type],
233-
groupId: currentRange.groupId
234-
};
235-
236-
if (existingError >= 0) {
237-
currentErrors[existingError] = newDiag;
238-
} else {
239-
currentErrors.push(newDiag);
204+
for (let i = 0; i < validStatements.length; i++) {
205+
const currentRange = validStatements[i];
206+
const groupError = syntaxChecked[i];
207+
let existingError: number = currentErrors.findIndex(e => e.groupId === currentRange.groupId);
208+
209+
if (groupError.type === `none`) {
210+
if (existingError !== -1) {
211+
currentErrors.splice(existingError, 1);
212+
}
213+
214+
} else if (shouldShowError(groupError)) {
215+
let baseIndex = () => { return currentRange.start + groupError.offset };
216+
217+
if (baseIndex() > currentRange.end) {
218+
// This is a syntax error that is outside the range of the statement.
219+
groupError.offset = (currentRange.end - currentRange.start);
220+
}
221+
222+
const selectedWord = document.getWordRangeAtPosition(document.positionAt(baseIndex()))
223+
|| new Range(
224+
document.positionAt(baseIndex() - 1),
225+
document.positionAt(baseIndex())
226+
);
227+
228+
229+
const newDiag: SqlDiagnostic = {
230+
message: `${groupError.text} - ${groupError.sqlstate}`,
231+
code: groupError.sqlid,
232+
range: selectedWord,
233+
severity: diagnosticTypeMap[groupError.type],
234+
groupId: currentRange.groupId
235+
};
236+
237+
if (existingError >= 0) {
238+
currentErrors[existingError] = newDiag;
239+
} else {
240+
currentErrors.push(newDiag);
241+
}
242+
243+
}
240244
}
241245

246+
sqlDiagnosticCollection.set(document.uri, currentErrors);
242247
}
243248
}
244-
245-
sqlDiagnosticCollection.set(document.uri, currentErrors);
246249
}
247250
}
248251
}
249252
}
253+
} else {
254+
documentLargeError(basename);
250255
}
251256
}
252257

@@ -287,3 +292,7 @@ function getStatementRangeFromGroup(currentGroup: StatementGroup, groupId: numbe
287292

288293
return statementRange;
289294
}
295+
296+
function documentLargeError(basename: string) {
297+
window.showWarningMessage(`${basename}: the SQL syntax checker is disabled for this document because it is too large.`);
298+
}

0 commit comments

Comments
 (0)