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,30 @@ 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 ();
8499 var position = symbol .getSelectionRange ().getStart ();
85100
86- var typesOfCurrentReference = calculateTypes (ast , position );
101+ var typesOfCurrentReference = calculateTypes (uri , ast , position );
87102
88103 var typesOfOtherReferences = referenceIndex .getReferencesTo (symbol ).stream ()
89104 .filter (referenceTo -> referenceTo .getOccurrenceType () == OccurrenceType .DEFINITION )
90- .map (referenceTo -> calculateTypes (ast , referenceTo .getSelectionRange ().getStart ()))
105+ .map (referenceTo -> calculateTypes (uri , ast , referenceTo .getSelectionRange ().getStart ()))
91106 .flatMap (Collection ::stream )
92107 .toList ();
93108
@@ -108,37 +123,43 @@ private List<Type> calculateTypes(URI uri, Reference reference) {
108123 var document = serverContext .getDocument (uri );
109124 var ast = document .getAst ();
110125 var position = reference .getSelectionRange ().getStart ();
111- return calculateTypes (ast , position );
126+ return calculateTypes (uri , ast , position );
112127 }
113128
114129 // no-op
115130 return Collections .emptyList ();
116131 }
117132
118- private List <Type > calculateTypes (BSLParser .FileContext ast , Position position ) {
133+ private List <Type > calculateTypes (URI uri , BSLParser .FileContext ast , Position position ) {
119134 return Trees .findTerminalNodeContainsPosition (ast , position )
120135 .map (TerminalNode ::getParent )
121136 .map (ruleNode -> Trees .getRootParent (ruleNode , BSLParser .RULE_assignment ))
122137 .map (BSLParser .AssignmentContext .class ::cast )
123138 .map (BSLParser .AssignmentContext ::expression )
124- .map (this :: calculateTypes )
139+ .map (expression -> calculateTypes ( uri , expression ) )
125140 .orElseGet (Collections ::emptyList );
126141 }
127142
128- private List <Type > calculateTypes (BSLParser .ExpressionContext expression ) {
143+ private List <Type > calculateTypes (URI uri , BSLParser .ExpressionContext expression ) {
129144
130145 // only simple cases for now. Use ExpressionTree in the future.
131146 if (!expression .operation ().isEmpty ()) {
132147 return Collections .emptyList ();
133148 }
134149
135150 // new-resolver
136- var typeName = typeName (expression );
151+ var typeName = newTypeName (expression );
137152 if (!typeName .isEmpty ()) {
138153 Type type = new Type (typeName );
139154 return List .of (type );
140155 }
141156
157+ // globalMethodCall resolver
158+ var typeNames = returnedValue (uri , expression );
159+ if (!typeNames .isEmpty ()) {
160+ return typeNames ;
161+ }
162+
142163 // const-value resolver
143164 var constValueContext = expression .member (0 ).constValue ();
144165 if (constValueContext == null ) {
@@ -168,14 +189,48 @@ private List<Type> calculateTypes(BSLParser.ExpressionContext expression) {
168189
169190 }
170191
171- private String typeName (BSLParser .ExpressionContext ctx ) {
192+ private String newTypeName (BSLParser .ExpressionContext expression ) {
172193 var typeName = "" ;
173- var newCtx = Trees .getNextNode (ctx , ctx , BSLParser .RULE_newExpression );
194+ var newCtx = Trees .getNextNode (expression , expression , BSLParser .RULE_newExpression );
174195 if (newCtx instanceof BSLParser .NewExpressionContext newExpression ) {
175196 typeName = Constructors .typeName (newExpression ).orElse ("" );
176197 }
177198 return typeName ;
178199 }
179200
201+ private List <Type > returnedValue (URI uri , BSLParser .ExpressionContext expression ) {
202+ var complexIdentifier = expression .member (0 ).complexIdentifier ();
203+
204+ if (complexIdentifier == null ) {
205+ return Collections .emptyList ();
206+ }
207+
208+ if (!complexIdentifier .modifier ().isEmpty ()) {
209+ return Collections .emptyList ();
210+ }
211+
212+ var globalMethodCall = complexIdentifier .globalMethodCall ();
213+
214+ if (globalMethodCall == null ) {
215+ return Collections .emptyList ();
216+ }
217+
218+ var calledMethod = referenceResolver .findReference (uri , Ranges .create (globalMethodCall .methodName ()).getStart ());
219+
220+ return calledMethod .filter (Reference ::isSourceDefinedSymbolReference )
221+ .flatMap (Reference ::getSourceDefinedSymbol )
222+ .filter (Describable .class ::isInstance )
223+ .map (Describable .class ::cast )
224+ .flatMap (Describable ::getDescription )
225+ .filter (MethodDescription .class ::isInstance )
226+ .map (MethodDescription .class ::cast )
227+ .map (MethodDescription ::getReturnedValue )
228+ .stream ()
229+ .flatMap (List ::stream )
230+ .map (TypeDescription ::getName )
231+ .map (Type ::new )
232+ .toList ();
233+
234+ }
180235
181236}
0 commit comments