Simplify linter error counting by using line events

This commit is contained in:
Raymond Hill 2023-04-04 09:24:18 -04:00
parent 9b5ed5ca86
commit 09265ef57c
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
2 changed files with 78 additions and 67 deletions

View File

@ -79,9 +79,6 @@ CodeMirror.defineMode('ubo-static-filtering', function() {
const raw = astParser.getNodeString(currentWalkerNode); const raw = astParser.getNodeString(currentWalkerNode);
const not = raw.startsWith('!'); const not = raw.startsWith('!');
const token = not ? raw.slice(1) : raw; const token = not ? raw.slice(1) : raw;
if ( preparseDirectiveTokens.has(token) === false ) {
return 'error strong';
}
return not === preparseDirectiveTokens.get(token) return not === preparseDirectiveTokens.get(token)
? 'negative strong' ? 'negative strong'
: 'positive strong'; : 'positive strong';
@ -671,38 +668,9 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => {
nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'),
}); });
let errorCount = 0;
let markedsetStart = 0;
let markedsetTimer;
const processMarkedsetAsync = doc => {
if ( markedsetTimer !== undefined ) { return; }
markedsetTimer = self.requestIdleCallback(deadline => {
markedsetTimer = undefined;
processMarkedset(doc, deadline);
});
};
const processMarkedset = (doc, deadline) => {
const lineCount = doc.lineCount();
doc.eachLine(markedsetStart, lineCount, lineHandle => {
const line = markedsetStart++;
const markers = lineHandle.gutterMarkers || null;
if ( markers && markers['CodeMirror-lintgutter'] ) {
errorCount += 1;
}
if ( (line & 0x0F) === 0 && deadline.timeRemaining() === 0 ) {
processMarkedsetAsync(doc);
return true;
}
if ( markedsetStart === lineCount ) {
CodeMirror.signal(doc.getEditor(), 'linterDone', { errorCount });
}
});
};
const changeset = []; const changeset = [];
let changesetTimer; let changesetTimer;
let errorCount = 0;
const addChange = (doc, change) => { const addChange = (doc, change) => {
changeset.push(change); changeset.push(change);
@ -711,10 +679,6 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => {
const processChangesetAsync = doc => { const processChangesetAsync = doc => {
if ( changesetTimer !== undefined ) { return; } if ( changesetTimer !== undefined ) { return; }
if ( markedsetTimer ) {
self.cancelIdleCallback(markedsetTimer);
markedsetTimer = undefined;
}
changesetTimer = self.requestIdleCallback(deadline => { changesetTimer = self.requestIdleCallback(deadline => {
changesetTimer = undefined; changesetTimer = undefined;
processChangeset(doc, deadline); processChangeset(doc, deadline);
@ -722,28 +686,27 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => {
}; };
const extractError = ( ) => { const extractError = ( ) => {
if ( astParser.isComment() ) { return; }
if ( astParser.isFilter() === false ) { return; }
if ( astParser.hasError() === false ) { return; } if ( astParser.hasError() === false ) { return; }
let error = 'Invalid filter'; const error = 'Invalid filter';
switch ( astParser.astError ) {
case sfp.AST_ERROR_REGEX:
return `${error}: Bad regular expression`;
case sfp.AST_ERROR_PATTERN:
return `${error}: Bad pattern`;
case sfp.AST_ERROR_DOMAIN_NAME:
return `${error}: Bad domain name`;
case sfp.AST_ERROR_OPTION_DUPLICATE:
return `${error}: Duplicate filter option`;
case sfp.AST_ERROR_OPTION_UNKNOWN:
return `${error}: Unsupported filter option`;
case sfp.AST_ERROR_IF_TOKEN_UNKNOWN:
return `${error}: Unknown preparsing token`;
default:
break;
}
if ( astParser.isCosmeticFilter() && astParser.result.error ) { if ( astParser.isCosmeticFilter() && astParser.result.error ) {
return `${error}: ${astParser.result.error}`; return `${error}: ${astParser.result.error}`;
} }
if ( astParser.astError === sfp.AST_ERROR_REGEX ) {
return `${error}: Bad regular expression`;
}
if ( astParser.astError === sfp.AST_ERROR_PATTERN ) {
return `${error}: Bad pattern`;
}
if ( astParser.astError === sfp.AST_ERROR_DOMAIN_NAME ) {
return `${error}: Bad domain name`;
}
if ( astParser.astError === sfp.AST_ERROR_OPTION_DUPLICATE ) {
return `${error}: Duplicate filter option`;
}
if ( astParser.astError === sfp.AST_ERROR_OPTION_UNKNOWN ) {
return `${error}: Unsupported filter option`;
}
return error; return error;
}; };
@ -764,12 +727,23 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => {
const makeMarker = (doc, lineHandle, marker, error) => { const makeMarker = (doc, lineHandle, marker, error) => {
if ( marker === undefined ) { if ( marker === undefined ) {
marker = markerTemplate.cloneNode(true); marker = addMarker(doc, lineHandle);
doc.setGutterMarker(lineHandle, 'CodeMirror-lintgutter', marker);
} }
marker.children[0].textContent = error; marker.children[0].textContent = error;
}; };
const addMarker = (doc, lineHandle) => {
const marker = markerTemplate.cloneNode(true);
doc.setGutterMarker(lineHandle, 'CodeMirror-lintgutter', marker);
lineHandle.on('delete', deleteMarker);
errorCount += 1;
return marker;
};
const deleteMarker = ( ) => {
errorCount -= 1;
};
const processChange = (doc, deadline, change) => { const processChange = (doc, deadline, change) => {
let { from, to } = change; let { from, to } = change;
doc.eachLine(from, to, lineHandle => { doc.eachLine(from, to, lineHandle => {
@ -804,9 +778,7 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => {
if ( changeset.length !== 0 ) { if ( changeset.length !== 0 ) {
return processChangesetAsync(doc); return processChangesetAsync(doc);
} }
errorCount = 0; CodeMirror.signal(doc.getEditor(), 'linterDone', { errorCount });
markedsetStart = 0;
processMarkedsetAsync(doc);
}; };
CodeMirror.defineInitHook(cm => { CodeMirror.defineInitHook(cm => {

View File

@ -76,6 +76,7 @@ export const AST_TYPE_EXTENDED_COSMETIC = iota++;
export const AST_TYPE_EXTENDED_SCRIPTLET = iota++; export const AST_TYPE_EXTENDED_SCRIPTLET = iota++;
export const AST_TYPE_EXTENDED_HTML = iota++; export const AST_TYPE_EXTENDED_HTML = iota++;
export const AST_TYPE_EXTENDED_RESPONSEHEADER = iota++; export const AST_TYPE_EXTENDED_RESPONSEHEADER = iota++;
export const AST_TYPE_COMMENT_PREPARSER = iota++;
iota = 0; iota = 0;
export const AST_FLAG_UNSUPPORTED = 1 << iota++; export const AST_FLAG_UNSUPPORTED = 1 << iota++;
@ -97,6 +98,7 @@ export const AST_ERROR_PATTERN = 1 << iota++;
export const AST_ERROR_DOMAIN_NAME = 1 << iota++; export const AST_ERROR_DOMAIN_NAME = 1 << iota++;
export const AST_ERROR_OPTION_DUPLICATE = 1 << iota++; export const AST_ERROR_OPTION_DUPLICATE = 1 << iota++;
export const AST_ERROR_OPTION_UNKNOWN = 1 << iota++; export const AST_ERROR_OPTION_UNKNOWN = 1 << iota++;
export const AST_ERROR_IF_TOKEN_UNKNOWN = 1 << iota++;
iota = 0; iota = 0;
const NODE_RIGHT_INDEX = iota++; const NODE_RIGHT_INDEX = iota++;
@ -553,6 +555,34 @@ export const removableHTTPHeaders = new Set([
'set-cookie', 'set-cookie',
]); ]);
export const preparserIfTokens = new Set([
'ext_ublock',
'ext_ubol',
'ext_devbuild',
'env_chromium',
'env_edge',
'env_firefox',
'env_legacy',
'env_mobile',
'env_mv3',
'env_safari',
'cap_html_filtering',
'cap_user_stylesheet',
'false',
'ext_abp',
'adguard',
'adguard_app_android',
'adguard_app_ios',
'adguard_app_mac',
'adguard_app_windows',
'adguard_ext_android_cb',
'adguard_ext_chromium',
'adguard_ext_edge',
'adguard_ext_firefox',
'adguard_ext_opera',
'adguard_ext_safari',
]);
/******************************************************************************/ /******************************************************************************/
const exCharCodeAt = (s, i) => { const exCharCodeAt = (s, i) => {
@ -1049,6 +1079,7 @@ export class AstFilterParser {
parseComment(parent) { parseComment(parent) {
const parentStr = this.getNodeString(parent); const parentStr = this.getNodeString(parent);
if ( this.rePreparseDirectiveAny.test(parentStr) ) { if ( this.rePreparseDirectiveAny.test(parentStr) ) {
this.astTypeFlavor = AST_TYPE_COMMENT_PREPARSER;
return this.parsePreparseDirective(parent, parentStr); return this.parsePreparseDirective(parent, parentStr);
} }
if ( this.reURL.test(parentStr) === false ) { return 0; } if ( this.reURL.test(parentStr) === false ) { return 0; }
@ -1078,14 +1109,22 @@ export class AstFilterParser {
directiveEnd directiveEnd
); );
if ( directiveEnd !== parentEnd ) { if ( directiveEnd !== parentEnd ) {
const next = this.allocTypedNode( const type = s.startsWith('!#if ')
s .startsWith('!#if ')
? NODE_TYPE_PREPARSE_DIRECTIVE_IF_VALUE ? NODE_TYPE_PREPARSE_DIRECTIVE_IF_VALUE
: NODE_TYPE_PREPARSE_DIRECTIVE_VALUE, : NODE_TYPE_PREPARSE_DIRECTIVE_VALUE;
directiveEnd, const next = this.allocTypedNode(type, directiveEnd, parentEnd);
parentEnd
);
this.linkRight(head, next); this.linkRight(head, next);
if ( type === NODE_TYPE_PREPARSE_DIRECTIVE_IF_VALUE ) {
const rawToken = this.getNodeString(next).trim();
const token = rawToken.charCodeAt(0) === 0x21 /* ! */
? rawToken.slice(1)
: rawToken;
if ( preparserIfTokens.has(token) === false ) {
this.addNodeFlags(next, NODE_FLAG_ERROR);
this.addFlags(AST_FLAG_HAS_ERROR);
this.astError = AST_ERROR_IF_TOKEN_UNKNOWN;
}
}
} }
return head; return head;
} }