2424import  com .github ._1c_syntax .bsl .languageserver .context .ServerContext ;
2525import  com .github ._1c_syntax .bsl .languageserver .context .symbol .Describable ;
2626import  com .github ._1c_syntax .bsl .languageserver .context .symbol .SourceDefinedSymbol ;
27+ import  com .github ._1c_syntax .bsl .languageserver .context .symbol .description .MethodDescription ;
28+ import  com .github ._1c_syntax .bsl .languageserver .context .symbol .description .TypeDescription ;
2729import  com .github ._1c_syntax .bsl .languageserver .context .symbol .variable .VariableDescription ;
2830import  com .github ._1c_syntax .bsl .languageserver .references .ReferenceIndex ;
2931import  com .github ._1c_syntax .bsl .languageserver .references .ReferenceResolver ;
3032import  com .github ._1c_syntax .bsl .languageserver .references .model .OccurrenceType ;
3133import  com .github ._1c_syntax .bsl .languageserver .references .model .Reference ;
34+ import  com .github ._1c_syntax .bsl .languageserver .utils .Ranges ;
3235import  com .github ._1c_syntax .bsl .languageserver .utils .Trees ;
3336import  com .github ._1c_syntax .bsl .languageserver .utils .bsl .Constructors ;
3437import  com .github ._1c_syntax .bsl .parser .BSLParser ;
4144import  java .util .Collection ;
4245import  java .util .Collections ;
4346import  java .util .List ;
47+ import  java .util .regex .MatchResult ;
48+ import  java .util .regex .Pattern ;
4449import  java .util .stream .Stream ;
4550
4651@ Component 
@@ -74,20 +79,34 @@ private List<Type> calculateTypes(SourceDefinedSymbol symbol) {
7479      if  (maybeDescription .isPresent ()) {
7580        var  description  = maybeDescription .get ();
7681        if  (description  instanceof  VariableDescription  variableDescription ) {
77-           // TODO: extract types from type description and return. 
82+           // TODO: use new type information from new bsp-parser 
83+           var  purposeDescription  = variableDescription .getPurposeDescription ();
84+           var  typeName  = Pattern .compile ("^(\\ S+)" ).matcher (purposeDescription ).results ()
85+             .findFirst ()
86+             .map (MatchResult ::group )
87+             .orElse ("" );
88+ 
89+           if  (!typeName .isEmpty ()) {
90+             return  List .of (new  Type (typeName ));
91+           }
7892        }
7993      }
8094    }
8195
8296    // reference-based type resolver 
97+     var  uri  = symbol .getOwner ().getUri ();
8398    var  ast  = symbol .getOwner ().getAst ();
99+     if  (ast  == null ) {
100+       return  Collections .emptyList ();
101+     }
102+ 
84103    var  position  = symbol .getSelectionRange ().getStart ();
85104
86-     var  typesOfCurrentReference  = calculateTypes (ast , position );
105+     var  typesOfCurrentReference  = calculateTypes (uri ,  ast , position );
87106
88107    var  typesOfOtherReferences  = referenceIndex .getReferencesTo (symbol ).stream ()
89108      .filter (referenceTo  -> referenceTo .getOccurrenceType () == OccurrenceType .DEFINITION )
90-       .map (referenceTo  -> calculateTypes (ast , referenceTo .getSelectionRange ().getStart ()))
109+       .map (referenceTo  -> calculateTypes (uri ,  ast , referenceTo .getSelectionRange ().getStart ()))
91110      .flatMap (Collection ::stream )
92111      .toList ();
93112
@@ -107,38 +126,47 @@ private List<Type> calculateTypes(URI uri, Reference reference) {
107126    if  (reference .getOccurrenceType () == OccurrenceType .DEFINITION ) {
108127      var  document  = serverContext .getDocument (uri );
109128      var  ast  = document .getAst ();
129+       if  (ast  == null ) {
130+         return  Collections .emptyList ();
131+       }
110132      var  position  = reference .getSelectionRange ().getStart ();
111-       return  calculateTypes (ast , position );
133+       return  calculateTypes (uri ,  ast , position );
112134    }
113135
114136    // no-op 
115137    return  Collections .emptyList ();
116138  }
117139
118-   private  List <Type > calculateTypes (BSLParser .FileContext  ast , Position  position ) {
140+   private  List <Type > calculateTypes (URI   uri ,  BSLParser .FileContext  ast , Position  position ) {
119141    return  Trees .findTerminalNodeContainsPosition (ast , position )
120142      .map (TerminalNode ::getParent )
121143      .map (ruleNode  -> Trees .getRootParent (ruleNode , BSLParser .RULE_assignment ))
122144      .map (BSLParser .AssignmentContext .class ::cast )
123145      .map (BSLParser .AssignmentContext ::expression )
124-       .map (this :: calculateTypes )
146+       .map (expression  ->  calculateTypes ( uri ,  expression ) )
125147      .orElseGet (Collections ::emptyList );
126148  }
127149
128-   private  List <Type > calculateTypes (BSLParser .ExpressionContext  expression ) {
150+   private  List <Type > calculateTypes (URI   uri ,  BSLParser .ExpressionContext  expression ) {
129151
130152    // only simple cases for now. Use ExpressionTree in the future. 
131153    if  (!expression .operation ().isEmpty ()) {
132154      return  Collections .emptyList ();
133155    }
134156
135157    // new-resolver 
136-     var  typeName  = typeName (expression );
158+     var  typeName  = newTypeName (expression );
137159    if  (!typeName .isEmpty ()) {
138160      Type  type  = new  Type (typeName );
139161      return  List .of (type );
140162    }
141163
164+     // globalMethodCall resolver 
165+     var  typeNames  = returnedValue (uri , expression );
166+     if  (!typeNames .isEmpty ()) {
167+       return  typeNames ;
168+     }
169+ 
142170    // const-value resolver 
143171    var  constValueContext  = expression .member (0 ).constValue ();
144172    if  (constValueContext  == null ) {
@@ -168,14 +196,48 @@ private List<Type> calculateTypes(BSLParser.ExpressionContext expression) {
168196
169197  }
170198
171-   private  String  typeName (BSLParser .ExpressionContext  ctx ) {
199+   private  String  newTypeName (BSLParser .ExpressionContext  expression ) {
172200    var  typeName  = "" ;
173-     var  newCtx  = Trees .getNextNode (ctx ,  ctx , BSLParser .RULE_newExpression );
201+     var  newCtx  = Trees .getNextNode (expression ,  expression , BSLParser .RULE_newExpression );
174202    if  (newCtx  instanceof  BSLParser .NewExpressionContext  newExpression ) {
175203      typeName  = Constructors .typeName (newExpression ).orElse ("" );
176204    }
177205    return  typeName ;
178206  }
179207
208+   private  List <Type > returnedValue (URI  uri , BSLParser .ExpressionContext  expression ) {
209+     var  complexIdentifier  = expression .member (0 ).complexIdentifier ();
210+ 
211+     if  (complexIdentifier  == null ) {
212+       return  Collections .emptyList ();
213+     }
214+ 
215+     if  (!complexIdentifier .modifier ().isEmpty ()) {
216+       return  Collections .emptyList ();
217+     }
218+ 
219+     var  globalMethodCall  = complexIdentifier .globalMethodCall ();
220+ 
221+     if  (globalMethodCall  == null ) {
222+       return  Collections .emptyList ();
223+     }
224+ 
225+     var  calledMethod  = referenceResolver .findReference (uri , Ranges .create (globalMethodCall .methodName ()).getStart ());
226+ 
227+     return  calledMethod .filter (Reference ::isSourceDefinedSymbolReference )
228+       .flatMap (Reference ::getSourceDefinedSymbol )
229+       .filter (Describable .class ::isInstance )
230+       .map (Describable .class ::cast )
231+       .flatMap (Describable ::getDescription )
232+       .filter (MethodDescription .class ::isInstance )
233+       .map (MethodDescription .class ::cast )
234+       .map (MethodDescription ::getReturnedValue )
235+       .stream ()
236+       .flatMap (List ::stream )
237+       .map (TypeDescription ::getName )
238+       .map (Type ::new )
239+       .toList ();
240+ 
241+   }
180242
181243}
0 commit comments