@@ -203,7 +203,7 @@ async function Diagnostics(document: vscode.TextDocument) {
203203 const diagnostics : vscode . Diagnostic [ ] = [ ] ;
204204
205205 await Promise . allSettled ( [
206- tryCatch ( diagnosticsMismatchingRootScopeName ( diagnostics , rootNode , document ) , "Diagnostics error:" , "MismatchingPackageJSONInfo" ) ,
206+ tryCatch ( diagnosticsMismatchingPackageJSONInfo ( diagnostics , rootNode , document ) , "Diagnostics error:" , "MismatchingPackageJSONInfo" ) ,
207207 tryCatch ( diagnosticsTreeSitterJSONErrors ( diagnostics , rootNode ) , "Diagnostics error:" , "TreeSitterJSONErrors" ) ,
208208 tryCatch ( diagnosticsTreeSitterRegexErrors ( diagnostics , trees ) , "Diagnostics error:" , "TreeSitterRegexErrors" ) ,
209209 tryCatch ( diagnosticsRegularExpressionErrors ( diagnostics , trees ) , "Diagnostics error:" , "OnigurumaRegexErrors" ) ,
@@ -947,49 +947,99 @@ async function diagnosticsDeadTextMateCode(diagnostics: vscode.Diagnostic[], roo
947947 // vscode.window.showInformationMessage(`dead ${(performance.now() - start).toFixed(3)}ms\n${JSON.stringify(diagnostics, stringify)}`);
948948}
949949
950- async function diagnosticsMismatchingRootScopeName ( diagnostics : vscode . Diagnostic [ ] , rootNode : webTreeSitter . Node , document : vscode . TextDocument ) {
951- // vscode.window.showInformationMessage(JSON.stringify("diagnostics scopeName"));
950+ async function diagnosticsMismatchingPackageJSONInfo ( diagnostics : vscode . Diagnostic [ ] , rootNode : webTreeSitter . Node , document : vscode . TextDocument ) {
952951 // const start = performance.now();
953952
954- const scopeNameQuery = `;scm
955- (scopeName (value) @scopeName)
956- ` ;
957- const scopeNameCapture = queryNode ( rootNode , scopeNameQuery ) . pop ( ) ;
958- if ( ! scopeNameCapture ) {
959- return ;
960- }
961-
962953 const { packageJSON, packageUri } = await getPackageJSON ( document ) ;
963954 if ( ! packageJSON ) {
964955 return ;
965956 }
966- const grammars = packageJSON ? .contributes ?. grammars ;
957+ const grammars = packageJSON . contributes ?. grammars ;
967958 if ( ! Array . isArray ( grammars ) ) {
968959 return ;
969960 }
970961
971- const node = scopeNameCapture . node ;
972- const scopeName = node . text ;
962+ const query = `;scm
963+ (json (scopeName (value) @scopeName))
964+ (json (injectionSelector) @injectionSelector)
965+ ` ;
966+ const queryCaptures = queryNode ( rootNode , query ) ;
973967
968+ let injectToPresent = false ;
969+ let injectionSelectorPresent = false ;
974970 for ( const grammar of grammars ) {
975- const uri = vscode . Uri . joinPath ( packageUri , '..' , grammar . path ) ;
971+ const path = grammar . path ;
972+ if ( ! path ) {
973+ continue ;
974+ }
975+ const uri = vscode . Uri . joinPath ( packageUri , '..' , path ) ;
976976 if ( document . uri . path == uri . path ) {
977- if ( grammar . scopeName == scopeName ) {
978- continue ;
977+ for ( const queryCapture of queryCaptures ) {
978+ switch ( queryCapture . name ) {
979+ case 'injectionSelector' :
980+ injectionSelectorPresent = true ;
981+ break ;
982+ case 'scopeName' :
983+ const scopeName = queryCapture . node . text ;
984+ if ( grammar . scopeName == scopeName ) {
985+ break ;
986+ }
987+
988+ const range = toRange ( queryCapture ) ;
989+ const diagnostic : vscode . Diagnostic = {
990+ range : range ,
991+ message : `scopeName '${ scopeName } ' does not match scopeName '${ grammar . scopeName } ' inside '${ packageUri . path } '` ,
992+ severity : vscode . DiagnosticSeverity . Error ,
993+ source : 'TextMate' ,
994+ code : 'scopeName' ,
995+ } ;
996+ diagnostics . push ( diagnostic ) ;
997+ break ;
998+ }
979999 }
9801000
981- const range = toRange ( node ) ;
982- const diagnostic : vscode . Diagnostic = {
983- range : range ,
984- message : `scopeName '${ scopeName } ' does not match scopeName '${ grammar . scopeName } ' inside '${ packageUri . path } '` ,
985- severity : vscode . DiagnosticSeverity . Error ,
986- source : 'TextMate' ,
987- code : 'scopeName' ,
988- } ;
989- diagnostics . push ( diagnostic ) ;
1001+ if ( grammar . injectTo ?. length ) {
1002+ injectToPresent = true ;
1003+ if ( ! injectionSelectorPresent ) {
1004+ const rootObjectQuery = `;scm
1005+ (json . "{" @rootObject)
1006+ ` ;
1007+ const rootObjectCaptures = queryNode ( rootNode , rootObjectQuery ) ;
1008+ for ( const rootObjectCapture of rootObjectCaptures ) {
1009+ const range = toRange ( rootObjectCapture ) ;
1010+ const diagnostic : vscode . Diagnostic = {
1011+ range : range ,
1012+ message : `Missing property "injectionSelector".` ,
1013+ severity : vscode . DiagnosticSeverity . Warning ,
1014+ source : 'TextMate' ,
1015+ code : 'injectionSelector' ,
1016+ } ;
1017+ diagnostics . push ( diagnostic ) ;
1018+ }
1019+ }
1020+ }
1021+ }
1022+ }
1023+
1024+ if ( injectionSelectorPresent && ! injectToPresent ) {
1025+ for ( const queryCapture of queryCaptures ) {
1026+ switch ( queryCapture . name ) {
1027+ case 'injectionSelector' :
1028+ const range = toRange ( queryCapture ) ;
1029+ const diagnostic : vscode . Diagnostic = {
1030+ range : range ,
1031+ message : '"injectionSelector" requires "injectTo" to be present under "grammars" inside `package.json`.' ,
1032+ severity : vscode . DiagnosticSeverity . Hint ,
1033+ source : 'TextMate' ,
1034+ code : 'dead' ,
1035+ tags : [ vscode . DiagnosticTag . Unnecessary ] ,
1036+ } ;
1037+ diagnostics . push ( diagnostic ) ;
1038+ break ;
1039+ }
9901040 }
9911041 }
992- // vscode.window.showInformationMessage(`scopeName ${(performance.now() - start).toFixed(3)}ms`);
1042+ // vscode.window.showInformationMessage(`packageJSON ${(performance.now() - start).toFixed(3)}ms`);
9931043}
9941044
9951045async function diagnosticsLinguistCaptures ( diagnostics : vscode . Diagnostic [ ] , rootNode : webTreeSitter . Node ) {
0 commit comments