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