@@ -654,7 +654,7 @@ enum PropPath {
654
654
Static ( JsWord ) ,
655
655
MemberCall ( JsWord ) ,
656
656
Unknown ( Id ) ,
657
- Expr ,
657
+ Expr ( Option < Expr > ) ,
658
658
This ,
659
659
Super ,
660
660
Private ( Id ) ,
@@ -724,7 +724,7 @@ fn normalize_callee_expr(
724
724
| Lit :: Num ( _)
725
725
| Lit :: BigInt ( _)
726
726
| Lit :: Regex ( _)
727
- | Lit :: JSXText ( _) => self . path . push ( PropPath :: Expr ) ,
727
+ | Lit :: JSXText ( _) => self . path . push ( PropPath :: Expr ( None ) ) ,
728
728
}
729
729
}
730
730
@@ -746,7 +746,7 @@ fn normalize_callee_expr(
746
746
}
747
747
Expr :: Call ( CallExpr { callee, .. } ) => {
748
748
let Some ( expr) = callee. as_expr ( ) else {
749
- self . path . push ( PropPath :: Expr ) ;
749
+ self . path . push ( PropPath :: Expr ( Some ( n . clone ( ) ) ) ) ;
750
750
return ;
751
751
} ;
752
752
match & * * expr {
@@ -759,12 +759,12 @@ fn normalize_callee_expr(
759
759
self . path . push ( PropPath :: MemberCall ( ident. sym . clone ( ) ) ) ;
760
760
}
761
761
_ => {
762
- self . path . push ( PropPath :: Expr ) ;
762
+ self . path . push ( PropPath :: Expr ( Some ( n . clone ( ) ) ) ) ;
763
763
}
764
764
}
765
765
}
766
766
767
- _ => self . path . push ( PropPath :: Expr ) ,
767
+ _ => self . path . push ( PropPath :: Expr ( Some ( n . clone ( ) ) ) ) ,
768
768
}
769
769
}
770
770
}
@@ -1026,65 +1026,84 @@ impl FunctionAnalyzer<'_> {
1026
1026
}
1027
1027
}
1028
1028
1029
+ fn get_intrinsic (
1030
+ first_arg : Option < & Expr > ,
1031
+ is_as_app : bool ,
1032
+ last : & Atom ,
1033
+ ) -> Option < Intrinsic > {
1034
+ let first_arg = first_arg?;
1035
+
1036
+ let function_name = if * last == "requestJira" {
1037
+ // Resolve Jira API requests to either JSM/JS/Jira as all are bundled within requestJira()
1038
+ match first_arg {
1039
+ Expr :: TaggedTpl ( TaggedTpl { tpl, .. } ) => {
1040
+ tpl. quasis . first ( ) . map ( |elem| & elem. raw )
1041
+ }
1042
+ Expr :: Lit ( Lit :: Str ( str_lit) ) => Some ( & str_lit. value ) ,
1043
+ _ => None ,
1044
+ }
1045
+ . and_then ( |atom| resolve_jira_api_type ( atom. as_ref ( ) ) )
1046
+ . unwrap_or_else ( || {
1047
+ warn ! ( "Could not resolve Jira API type, falling back to any Jira request" ) ;
1048
+ IntrinsicName :: RequestJiraAny
1049
+ } )
1050
+ } else if * last == "requestBitbucket" {
1051
+ IntrinsicName :: RequestBitbucket
1052
+ } else {
1053
+ IntrinsicName :: RequestConfluence
1054
+ } ;
1055
+
1056
+ match classify_api_call ( first_arg) {
1057
+ ApiCallKind :: Unknown => {
1058
+ if is_as_app {
1059
+ Some ( Intrinsic :: ApiCall ( function_name) )
1060
+ } else {
1061
+ Some ( Intrinsic :: SafeCall ( function_name) )
1062
+ }
1063
+ }
1064
+ ApiCallKind :: CustomField => {
1065
+ if is_as_app {
1066
+ Some ( Intrinsic :: ApiCustomField )
1067
+ } else {
1068
+ Some ( Intrinsic :: SafeCall ( function_name) )
1069
+ }
1070
+ }
1071
+ ApiCallKind :: Fields => {
1072
+ if is_as_app {
1073
+ Some ( Intrinsic :: ApiCustomField )
1074
+ } else {
1075
+ Some ( Intrinsic :: UserFieldAccess )
1076
+ }
1077
+ }
1078
+ ApiCallKind :: Trivial => Some ( Intrinsic :: SafeCall ( function_name) ) ,
1079
+ ApiCallKind :: Authorize => Some ( Intrinsic :: Authorize ( function_name) ) ,
1080
+ }
1081
+ }
1082
+
1029
1083
match * callee {
1030
1084
[ PropPath :: Unknown ( ( ref name, ..) ) ] if * name == * "fetch" => Some ( Intrinsic :: Fetch ) ,
1085
+ [ PropPath :: Expr ( ref n@ Some ( ref expr) ) , PropPath :: Static ( ref last) ] => {
1086
+ if self . res . is_expr_imported_from ( expr, self . module ) . is_some_and (
1087
+ |imp| matches ! ( imp, ImportKind :: Named ( s) if * s == * "asApp" || * s == * "asUser" ) ) {
1088
+ let is_as_app = self . res . is_expr_imported_from ( expr, self . module ) . is_some_and (
1089
+ |imp| matches ! ( imp, ImportKind :: Named ( s) if * s == * "asApp" ) ) ;
1090
+ return get_intrinsic ( first_arg, is_as_app, last) ;
1091
+ }
1092
+ None
1093
+ }
1031
1094
[ PropPath :: Def ( def) , ref authn @ .., PropPath :: Static ( ref last) ]
1032
- if ( * last == * "requestJira"
1095
+ if ( ( * last == * "requestJira"
1033
1096
|| * last == * "requestConfluence"
1034
1097
|| * last == * "requestBitbucket" )
1035
1098
&& Some ( & ImportKind :: Default )
1036
- == self . res . is_imported_from ( def, "@forge/api" ) =>
1099
+ == self . res . is_imported_from ( def, "@forge/api" ) ) || self . res . is_imported_from ( def, "@forge/api" ) . is_some_and (
1100
+ |imp| matches ! ( imp, ImportKind :: Named ( s) if * s == * "asApp" || * s == * "asUser" ) ,
1101
+ ) =>
1037
1102
{
1038
- let first_arg = first_arg?;
1039
1103
let is_as_app = authn. first ( ) == Some ( & PropPath :: MemberCall ( "asApp" . into ( ) ) ) ;
1040
-
1041
- let function_name = if * last == "requestJira" {
1042
- // Resolve Jira API requests to either JSM/JS/Jira as all are bundled within requestJira()
1043
- match first_arg {
1044
- Expr :: TaggedTpl ( TaggedTpl { tpl, .. } ) => {
1045
- tpl. quasis . first ( ) . map ( |elem| & elem. raw )
1046
- }
1047
- Expr :: Lit ( Lit :: Str ( str_lit) ) => Some ( & str_lit. value ) ,
1048
- _ => None ,
1049
- }
1050
- . and_then ( |atom| resolve_jira_api_type ( atom. as_ref ( ) ) )
1051
- . unwrap_or_else ( || {
1052
- warn ! ( "Could not resolve Jira API type, falling back to any Jira request" ) ;
1053
- IntrinsicName :: RequestJiraAny
1054
- } )
1055
- } else if * last == "requestBitbucket" {
1056
- IntrinsicName :: RequestBitbucket
1057
- } else {
1058
- IntrinsicName :: RequestConfluence
1059
- } ;
1060
-
1061
- match classify_api_call ( first_arg) {
1062
- ApiCallKind :: Unknown => {
1063
- if is_as_app {
1064
- Some ( Intrinsic :: ApiCall ( function_name) )
1065
- } else {
1066
- Some ( Intrinsic :: SafeCall ( function_name) )
1067
- }
1068
- }
1069
- ApiCallKind :: CustomField => {
1070
- if is_as_app {
1071
- Some ( Intrinsic :: ApiCustomField )
1072
- } else {
1073
- Some ( Intrinsic :: SafeCall ( function_name) )
1074
- }
1075
- }
1076
- ApiCallKind :: Fields => {
1077
- if is_as_app {
1078
- Some ( Intrinsic :: ApiCustomField )
1079
- } else {
1080
- Some ( Intrinsic :: UserFieldAccess )
1081
- }
1082
- }
1083
- ApiCallKind :: Trivial => Some ( Intrinsic :: SafeCall ( function_name) ) ,
1084
- ApiCallKind :: Authorize => Some ( Intrinsic :: Authorize ( function_name) ) ,
1085
- }
1104
+ let is_as_app = authn. first ( ) == Some ( & PropPath :: MemberCall ( "asApp" . into ( ) ) ) ;
1105
+ get_intrinsic ( first_arg, is_as_app, last)
1086
1106
}
1087
-
1088
1107
[ PropPath :: Def ( def) , PropPath :: Static ( ref s) , ..] if is_storage_read ( s) => {
1089
1108
match self . res . is_imported_from ( def, "@forge/api" ) {
1090
1109
Some ( ImportKind :: Named ( name) ) if * name == * "storage" => {
@@ -3875,6 +3894,21 @@ impl Environment {
3875
3894
}
3876
3895
}
3877
3896
3897
+ pub fn is_expr_imported_from ( & self , n : & Expr , module : ModId ) -> Option < & ImportKind > {
3898
+ if let Expr :: Call ( CallExpr {
3899
+ callee : Callee :: Expr ( expr) ,
3900
+ ..
3901
+ } ) = n
3902
+ {
3903
+ if let Expr :: Ident ( id) = & * * expr {
3904
+ if let Some ( defid) = self . recent_sym ( id. sym . clone ( ) , module) {
3905
+ return self . is_imported_from ( defid, "@forge/api" ) ;
3906
+ }
3907
+ }
3908
+ }
3909
+ None
3910
+ }
3911
+
3878
3912
pub fn resolve_alias ( & self , def : DefId ) -> DefId {
3879
3913
match self . def_ref ( def) {
3880
3914
DefKind :: Arg
0 commit comments