@@ -12,6 +12,7 @@ import {ApiExtract} from "../../utils/ApiExtract.js";
12
12
import ControllerByIdInfo from "./ControllerByIdInfo.js" ;
13
13
import BindingLinter from "../binding/BindingLinter.js" ;
14
14
import { Tag as SaxTag } from "sax-wasm" ;
15
+ import EventHandlerResolver from "./lib/EventHandlerResolver.js" ;
15
16
const log = getLogger ( "linter:xmlTemplate:Parser" ) ;
16
17
17
18
export type Namespace = string ;
@@ -557,15 +558,51 @@ export default class Parser {
557
558
// Check whether prop is of type "property" (indicating that it can have a binding)
558
559
// Note that some aggregations are handled like properties (0..n + alt type). Therefore check
559
560
// whether this is a property first. Additional aggregation-specific checks are not needed in that case
560
- if ( this . #apiExtract. isProperty ( `${ namespace } .${ moduleName } ` , prop . name ) ) {
561
- this . #bindingLinter. lintPropertyBinding ( prop . value , this . #requireDeclarations, {
562
- line : prop . start . line + 1 , // Add one to align with IDEs
563
- column : prop . start . column + 1 ,
564
- } ) ;
565
- } else if ( this . #apiExtract. isAggregation ( `${ namespace } .${ moduleName } ` , prop . name ) ) {
566
- this . #bindingLinter. lintAggregationBinding ( prop . value , this . #requireDeclarations, {
567
- line : prop . start . line + 1 , // Add one to align with IDEs
568
- column : prop . start . column + 1 ,
561
+ const symbolName = `${ namespace } .${ moduleName } ` ;
562
+ const position = {
563
+ line : prop . start . line + 1 , // Add one to align with IDEs
564
+ column : prop . start . column + 1 ,
565
+ } ;
566
+ if ( this . #apiExtract. isProperty ( symbolName , prop . name ) ) {
567
+ this . #bindingLinter. lintPropertyBinding ( prop . value , this . #requireDeclarations, position ) ;
568
+ } else if ( this . #apiExtract. isAggregation ( symbolName , prop . name ) ) {
569
+ this . #bindingLinter. lintAggregationBinding ( prop . value , this . #requireDeclarations, position ) ;
570
+ } else if ( this . #apiExtract. isEvent ( symbolName , prop . name ) ) {
571
+ EventHandlerResolver . parse ( prop . value ) . forEach ( ( eventHandler ) => {
572
+ if ( eventHandler . startsWith ( "cmd:" ) ) {
573
+ // No global usage possible via command execution
574
+ return ;
575
+ }
576
+ let functionName ;
577
+ const openBracketIndex = eventHandler . indexOf ( "(" ) ;
578
+ if ( openBracketIndex !== - 1 ) {
579
+ functionName = eventHandler . slice ( 0 , openBracketIndex ) ;
580
+ } else {
581
+ functionName = eventHandler ;
582
+ }
583
+ const variableName = this . #bindingLinter. getGlobalReference (
584
+ functionName , this . #requireDeclarations
585
+ ) ;
586
+ if ( ! variableName ) {
587
+ return ;
588
+ }
589
+ if ( ! functionName . includes ( "." ) ) {
590
+ // If the event handler does not include a dot, it is most likely a reference to the
591
+ // controller which should be prefixed with a leading dot, but works in UI5 1.x runtime
592
+ // without also it.
593
+ // Note that this could also be a global function reference, but we can't distinguish
594
+ // that here.
595
+ this . #context. addLintingMessage (
596
+ this . #resourcePath, MESSAGE . NO_AMBIGUOUS_EVENT_HANDLER , {
597
+ eventHandler : functionName ,
598
+ } , position
599
+ ) ;
600
+ } else {
601
+ this . #context. addLintingMessage ( this . #resourcePath, MESSAGE . NO_GLOBALS , {
602
+ variableName,
603
+ namespace : functionName ,
604
+ } , position ) ;
605
+ }
569
606
} ) ;
570
607
}
571
608
}
0 commit comments