1
1
package fr .adrienbrault .idea .symfony2plugin .config .yaml ;
2
2
3
+ import com .intellij .openapi .util .TextRange ;
4
+ import com .intellij .patterns .PatternCondition ;
3
5
import com .intellij .patterns .PlatformPatterns ;
4
6
import com .intellij .patterns .StandardPatterns ;
5
7
import com .intellij .psi .*;
6
8
import com .intellij .util .ProcessingContext ;
7
9
import fr .adrienbrault .idea .symfony2plugin .Symfony2ProjectComponent ;
8
10
import org .jetbrains .annotations .NotNull ;
9
- import org .jetbrains .yaml .psi .YAMLScalar ;
11
+ import org .jetbrains .yaml .psi .* ;
10
12
11
13
public class YamlReferenceContributor extends PsiReferenceContributor {
12
14
private static final String TAG_PHP_CONST = "!php/const" ;
@@ -26,7 +28,7 @@ public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar)
26
28
return PsiReference .EMPTY_ARRAY ;
27
29
}
28
30
29
- var scalar = (YAMLScalar )element ;
31
+ var scalar = (YAMLScalar ) element ;
30
32
if (scalar .getTextValue ().isEmpty ()) {
31
33
return PsiReference .EMPTY_ARRAY ;
32
34
}
@@ -37,5 +39,245 @@ public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar)
37
39
}
38
40
}
39
41
);
42
+
43
+ // services:
44
+ // app.service.foo:
45
+ // arguments:
46
+ // - '@app.service.bar<caret>'
47
+ registrar .registerReferenceProvider (
48
+ PlatformPatterns
49
+ .psiElement (YAMLScalar .class )
50
+ .withParent (
51
+ PlatformPatterns
52
+ .psiElement (YAMLSequenceItem .class )
53
+ .withParent (
54
+ PlatformPatterns
55
+ .psiElement (YAMLSequence .class )
56
+ .withParent (
57
+ PlatformPatterns .psiElement (YAMLKeyValue .class ).withName ("arguments" )
58
+ )
59
+ )
60
+ ),
61
+ new YAMLScalarServiceReferenceProvider ()
62
+ );
63
+
64
+ // services:
65
+ // app.service.foo:
66
+ // arguments:
67
+ // $bar: '@app.service.bar'
68
+
69
+ // services:
70
+ // app.service.foo:
71
+ // properties:
72
+ // bar: '@app.service.bar'
73
+
74
+ registrar .registerReferenceProvider (
75
+ PlatformPatterns
76
+ .psiElement (YAMLScalar .class )
77
+ .withParent (
78
+ PlatformPatterns
79
+ .psiElement (YAMLKeyValue .class )
80
+ .withParent (
81
+ PlatformPatterns
82
+ .psiElement (YAMLMapping .class )
83
+ .withParent (
84
+ PlatformPatterns
85
+ .psiElement (YAMLKeyValue .class )
86
+ .withName ("arguments" , "properties" )
87
+ )
88
+ )
89
+ ),
90
+ new YAMLScalarServiceReferenceProvider ()
91
+ );
92
+
93
+ // services:
94
+ // app.service.foo:
95
+ // alias: app.service.bar
96
+
97
+ // services:
98
+ // app.service.foo_decorator:
99
+ // decorates: app.service.foo
100
+
101
+ // services:
102
+ // app.service.foo:
103
+ // parent: app.service.foo_parent
104
+
105
+ registrar .registerReferenceProvider (
106
+ PlatformPatterns
107
+ .psiElement (YAMLScalar .class )
108
+ .withParent (
109
+ PlatformPatterns
110
+ .psiElement (YAMLKeyValue .class )
111
+ .withName ("alias" , "decorates" , "parent" )
112
+ ),
113
+ new YAMLScalarServiceReferenceProvider (false )
114
+ );
115
+
116
+ // services:
117
+ // app.service.foo:
118
+ // configurator: @app.service.foo_configurator
119
+
120
+ // services:
121
+ // app.service.foo:
122
+ // factory: @app.service.foo_factory
123
+
124
+ registrar .registerReferenceProvider (
125
+ PlatformPatterns
126
+ .psiElement (YAMLScalar .class )
127
+ .withParent (
128
+ PlatformPatterns
129
+ .psiElement (YAMLKeyValue .class )
130
+ .withName ("configurator" , "factory" )
131
+ ),
132
+ new YAMLScalarServiceReferenceProvider ()
133
+ );
134
+
135
+ // services:
136
+ // app.service.foo:
137
+ // factory: ['@app.service.foo_factory', 'create']
138
+
139
+ // services:
140
+ // app.service.foo:
141
+ // configurator: ['@app.service.foo_configurator', 'configure']
142
+
143
+ registrar .registerReferenceProvider (
144
+ PlatformPatterns
145
+ .psiElement (YAMLScalar .class )
146
+ .withParent (
147
+ PlatformPatterns
148
+ .psiElement (YAMLSequenceItem .class )
149
+ .with (new PatternCondition <>("is first sequence item" ) {
150
+ @ Override
151
+ public boolean accepts (@ NotNull YAMLSequenceItem element , ProcessingContext context ) {
152
+ return element .getItemIndex () == 0 ;
153
+ }
154
+ })
155
+ .withParent (
156
+ PlatformPatterns
157
+ .psiElement (YAMLSequence .class )
158
+ .withParent (
159
+ PlatformPatterns .psiElement (YAMLKeyValue .class ).withName ("factory" , "configurator" )
160
+ )
161
+ )
162
+ ),
163
+ new YAMLScalarServiceReferenceProvider ()
164
+ );
165
+
166
+ // services:
167
+ // app.service.foo: '@app.service.bar'
168
+ registrar .registerReferenceProvider (
169
+ PlatformPatterns
170
+ .psiElement (YAMLScalar .class )
171
+ .withParent (
172
+ PlatformPatterns
173
+ .psiElement (YAMLKeyValue .class )
174
+ .withParent (
175
+ PlatformPatterns
176
+ .psiElement (YAMLMapping .class )
177
+ .withParent (
178
+ PlatformPatterns
179
+ .psiElement (YAMLKeyValue .class )
180
+ .withName ("services" )
181
+ )
182
+ )
183
+ ),
184
+ new YAMLScalarServiceReferenceProvider ()
185
+ );
186
+
187
+ // services:
188
+ // app.service.foo:
189
+ // calls:
190
+ // - setBar: [ '@app.service.bar' ]
191
+ registrar .registerReferenceProvider (
192
+ PlatformPatterns
193
+ .psiElement (YAMLScalar .class )
194
+ .withParent (
195
+ PlatformPatterns
196
+ .psiElement (YAMLSequenceItem .class )
197
+ .withParent (
198
+ PlatformPatterns
199
+ .psiElement (YAMLSequence .class )
200
+ .withParent (
201
+ PlatformPatterns
202
+ .psiElement (YAMLKeyValue .class )
203
+ .withParent (
204
+ PlatformPatterns
205
+ .psiElement (YAMLMapping .class )
206
+ .withParent (
207
+ PlatformPatterns
208
+ .psiElement (YAMLSequenceItem .class )
209
+ .withParent (
210
+ PlatformPatterns
211
+ .psiElement (YAMLSequence .class )
212
+ .withParent (
213
+ PlatformPatterns
214
+ .psiElement (YAMLKeyValue .class )
215
+ .withName ("calls" )
216
+ )
217
+ )
218
+ )
219
+ )
220
+
221
+ )
222
+ )
223
+ ),
224
+ new YAMLScalarServiceReferenceProvider ()
225
+ );
226
+ }
227
+
228
+ private static class YAMLScalarServiceReferenceProvider extends PsiReferenceProvider {
229
+
230
+ private static final String PREFIX = "@" ;
231
+ private static final String ESCAPED_PREFIX = "@@" ;
232
+
233
+ /**
234
+ * Flag indicating whenever YAMLScalar value start with `@` prefix
235
+ */
236
+ private boolean isPrefixed = true ;
237
+
238
+ public YAMLScalarServiceReferenceProvider () {
239
+ }
240
+
241
+ public YAMLScalarServiceReferenceProvider (boolean isPrefixed ) {
242
+ this .isPrefixed = isPrefixed ;
243
+ }
244
+
245
+ @ Override
246
+ public PsiReference @ NotNull [] getReferencesByElement (@ NotNull PsiElement element , @ NotNull ProcessingContext context ) {
247
+ if (!Symfony2ProjectComponent .isEnabled (element )) {
248
+ return PsiReference .EMPTY_ARRAY ;
249
+ }
250
+
251
+ if (element instanceof YAMLScalar ) {
252
+ var serviceName = ((YAMLScalar ) element ).getTextValue ();
253
+ if (serviceName .isEmpty ()) {
254
+ return PsiReference .EMPTY_ARRAY ;
255
+ }
256
+
257
+ if (!isPrefixed ) {
258
+ return new PsiReference []{
259
+ new ServiceYamlReference (element , serviceName )
260
+ };
261
+ }
262
+
263
+ if (isValidServiceNameWithPrefix (serviceName )) {
264
+ var range = TextRange .from (serviceName .indexOf (PREFIX ) + 1 , serviceName .length () - 1 );
265
+ if (element instanceof YAMLQuotedText ) {
266
+ // Skip quotes
267
+ range = range .shiftRight (1 );
268
+ }
269
+
270
+ return new PsiReference []{
271
+ new ServiceYamlReference (element , range , serviceName .substring (1 ))
272
+ };
273
+ }
274
+ }
275
+
276
+ return PsiReference .EMPTY_ARRAY ;
277
+ }
278
+
279
+ private boolean isValidServiceNameWithPrefix (@ NotNull String serviceName ) {
280
+ return serviceName .length () > 1 && serviceName .startsWith (PREFIX ) && !serviceName .startsWith (ESCAPED_PREFIX );
281
+ }
40
282
}
41
283
}
0 commit comments