@@ -280,6 +280,25 @@ async function checkStandardId(
280280 ) ;
281281
282282 if ( ! standardAttr ) {
283+ const misplacedStandardAttr = findModuleLevelStandardAttribute (
284+ text ,
285+ bdlAst ,
286+ ) ;
287+ if ( misplacedStandardAttr ) {
288+ diagnostics . push ( {
289+ code : "bdl/misplaced-standard" ,
290+ span : {
291+ start : misplacedStandardAttr . start ,
292+ end : misplacedStandardAttr . end ,
293+ } ,
294+ message :
295+ `Outer 'standard' attributes do not set the BDL standard.\nDid you mean "${
296+ formatStandardAttributeSuggestion ( text , misplacedStandardAttr )
297+ } "?`,
298+ severity : "error" ,
299+ } ) ;
300+ return ;
301+ }
283302 diagnostics . push ( {
284303 code : "bdl/missing-standard" ,
285304 span : { start : 0 , end : 0 } ,
@@ -312,6 +331,29 @@ async function checkStandardId(
312331 return standardId ;
313332}
314333
334+ function findModuleLevelStandardAttribute (
335+ text : string ,
336+ bdlAst : ast . BdlAst ,
337+ ) : ast . Attribute | undefined {
338+ for ( const statement of bdlAst . statements ) {
339+ const standardAttr = statement . attributes . find (
340+ ( attr ) =>
341+ text [ attr . start ] === "@" && slice ( text , attr . name ) === "standard" ,
342+ ) ;
343+ if ( standardAttr ) return standardAttr ;
344+ }
345+ }
346+
347+ function formatStandardAttributeSuggestion (
348+ text : string ,
349+ standardAttr : ast . Attribute ,
350+ ) : string {
351+ const standardId = standardAttr . content
352+ ? getAttributeContent ( text , standardAttr ) . replace ( / \s + / g, " " ) . trim ( )
353+ : "" ;
354+ return standardId ? `# standard - ${ standardId } ` : "# standard - <standard>" ;
355+ }
356+
315357async function checkStandard (
316358 ctx : CheckContext ,
317359 standardId : string | undefined ,
@@ -383,6 +425,12 @@ function checkWrongAttributeNames(ctx: CheckContext): void {
383425 const diagnostics = result . diagnostics ;
384426 const attributesBySlot = groupAttributesBySlot ( bdlAst ) ;
385427 const validAttributeKeys = { } as Record < AttributeSlot , Set < string > > ;
428+ const hasModuleStandardAttr = bdlAst . attributes . some (
429+ ( attr ) => slice ( text , attr . name ) === "standard" ,
430+ ) ;
431+ const misplacedStandardAttr = hasModuleStandardAttr
432+ ? undefined
433+ : findModuleLevelStandardAttribute ( text , bdlAst ) ;
386434
387435 const attributeEntries = [
388436 ...Object . entries ( globalStandard . attributes || { } ) ,
@@ -397,6 +445,7 @@ function checkWrongAttributeNames(ctx: CheckContext): void {
397445 const validAttributeKeySet = validAttributeKeys [ slot as AttributeSlot ] ;
398446 for ( const attr of attrs as ast . Attribute [ ] ) {
399447 const key = slice ( text , attr . name ) ;
448+ if ( attr === misplacedStandardAttr ) continue ;
400449 if ( validAttributeKeySet ?. has ( key ) ) continue ;
401450 diagnostics . push ( {
402451 code : "bdl/unknown-attribute" ,
0 commit comments