34
34
import ocaml .lang .processing .parser .psi .OCamlElement ;
35
35
import ocaml .lang .processing .parser .psi .OCamlPsiUtil ;
36
36
import ocaml .lang .processing .parser .psi .element .*;
37
+ import ocaml .util .OCamlCollectionsUtil ;
37
38
import ocaml .util .OCamlFileUtil ;
38
39
import ocaml .util .OCamlStringUtil ;
39
40
import org .jetbrains .annotations .NotNull ;
40
41
import org .jetbrains .annotations .Nullable ;
41
42
43
+ import java .util .ArrayList ;
44
+ import java .util .Collections ;
42
45
import java .util .List ;
43
46
44
47
import static com .intellij .psi .search .GlobalSearchScope .getScopeRestrictedByFileTypes ;
51
54
public class OCamlResolvingUtil {
52
55
@ NotNull public static final String PERVASIVES = "Pervasives" ;
53
56
54
- @ Nullable
55
- public static OCamlStructuredElement findActualDefinitionOfStructuredElement (@ NotNull final OCamlReference reference ) {
57
+ @ NotNull
58
+ public static List < OCamlStructuredElement > findActualDefinitionsOfStructuredElementReference (@ NotNull final OCamlReference reference ) {
56
59
final OCamlResolvedReference resolvedReference = reference .resolve ();
57
- if (resolvedReference == null || !(resolvedReference instanceof OCamlStructuredBinding )) return null ;
58
- final OCamlStructuredElement expression = ((OCamlStructuredBinding ) resolvedReference ).getExpression ();
59
- return expression == null ? null : expression .findActualDefinition ();
60
+ if (resolvedReference == null || !(resolvedReference instanceof OCamlStructuredBinding )) return Collections .emptyList ();
61
+ final OCamlStructuredBinding binding = (OCamlStructuredBinding ) resolvedReference ;
62
+ return OCamlCollectionsUtil .createNotNullValuesList (binding .getExpression (), binding .getTypeExpression ());
63
+ }
64
+
65
+ @ NotNull
66
+ public static List <OCamlStructuredElement > collectActualDefinitionsOfStructuredElements (final OCamlStructuredElement ... elements ) {
67
+ final List <OCamlStructuredElement > result = new ArrayList <OCamlStructuredElement >();
68
+ for (final OCamlStructuredElement element : elements ) {
69
+ if (element != null ) {
70
+ result .addAll (element .findActualDefinitions ());
71
+ }
72
+ }
73
+ return result ;
60
74
}
61
75
62
76
@ NotNull
@@ -102,9 +116,9 @@ else if (builder.getContext().getSourceElement() instanceof OCamlModuleName) {
102
116
moduleName = builder .getContext ().getSourceElement ().getName ();
103
117
}
104
118
if (moduleName != null ) {
105
- final OCamlElement targetFile = findFileModule (sourceFile , moduleName );
106
- if (targetFile != null ) {
107
- processSibling (targetFile , builder );
119
+ final OCamlElement targetModule = findFileModule (sourceFile , moduleName );
120
+ if (targetModule != null ) {
121
+ processSibling (targetModule , builder );
108
122
}
109
123
}
110
124
}
@@ -121,16 +135,16 @@ private static boolean processSibling(@NotNull final OCamlElement sibling, @NotN
121
135
}
122
136
123
137
private static boolean tryProcessPervasives (@ NotNull final ResolvingBuilder builder , @ NotNull final PsiFile sourceFile ) {
124
- final OCamlElement pervasivesFile = findFileModule (sourceFile , PERVASIVES );
125
- return pervasivesFile != null && processSibling (pervasivesFile , builder );
138
+ final OCamlElement pervasivesModule = findFileModule (sourceFile , PERVASIVES );
139
+ return pervasivesModule != null && processSibling (pervasivesModule , builder );
126
140
}
127
141
128
142
@ Nullable
129
143
private static OCamlElement findFileModule (@ NotNull final PsiFile sourceFile , @ NotNull final String moduleName ) {
130
144
if (OCamlFileUtil .isImplementationFile (sourceFile )) {
131
- final OCamlElement targetFile = findFileModuleDefinition (sourceFile , moduleName );
132
- if (targetFile != null ) {
133
- return targetFile ;
145
+ final OCamlElement targetModule = findFileModuleDefinition (sourceFile , moduleName );
146
+ if (targetModule != null ) {
147
+ return targetModule ;
134
148
}
135
149
}
136
150
@@ -140,50 +154,58 @@ private static OCamlElement findFileModule(@NotNull final PsiFile sourceFile, @N
140
154
@ Nullable
141
155
public static OCamlModuleDefinitionBinding findFileModuleDefinition (@ NotNull final PsiFile sourceFile ,
142
156
@ NotNull final String moduleName ) {
143
- return doFindFile (sourceFile , moduleName , MLFileType .INSTANCE , OCamlModuleDefinitionBinding .class );
157
+ return doFindFileModule (sourceFile , moduleName , MLFileType .INSTANCE , OCamlModuleDefinitionBinding .class );
144
158
}
145
159
146
160
@ Nullable
147
161
public static OCamlModuleSpecificationBinding findFileModuleSpecification (@ NotNull final PsiFile sourceFile ,
148
162
@ NotNull final String moduleName ) {
149
- return doFindFile (sourceFile , moduleName , MLIFileType .INSTANCE , OCamlModuleSpecificationBinding .class );
163
+ return doFindFileModule (sourceFile , moduleName , MLIFileType .INSTANCE , OCamlModuleSpecificationBinding .class );
150
164
}
151
165
152
166
@ SuppressWarnings ({"unchecked" })
153
167
@ Nullable
154
- private static <T extends OCamlElement > T doFindFile (@ NotNull final PsiFile sourceFile ,
155
- @ NotNull final String moduleName ,
156
- @ NotNull final FileType fileType ,
157
- @ NotNull final Class <T > type ) {
168
+ private static <T extends OCamlStructuredBinding > T doFindFileModule (@ NotNull final PsiFile sourceFile ,
169
+ @ NotNull final String moduleName ,
170
+ @ NotNull final FileType fileType ,
171
+ @ NotNull final Class <T > type ) {
158
172
final Project project = sourceFile .getProject ();
159
173
160
174
final Module module = ModuleUtil .findModuleForPsiElement (sourceFile );
161
175
if (module == null ) return null ;
162
176
163
177
final String fileName = OCamlFileUtil .getFileName (moduleName , fileType );
164
178
final GlobalSearchScope scope = getScopeRestrictedByFileTypes (moduleWithDependenciesAndLibrariesScope (module ), fileType );
165
- final T file = findFileByName (project , scope , type , fileName );
166
- return file == null ? findFileByName (project , scope , type , OCamlStringUtil .changeFirstLetterCase (fileName )) : file ;
179
+ final T file = findFileModuleByFileName (project , scope , type , fileName );
180
+ return file == null ? findFileModuleByFileName (project , scope , type , OCamlStringUtil .changeFirstLetterCase (fileName )) : file ;
167
181
}
168
182
169
183
@ Nullable
170
- private static <T extends OCamlElement > T findFileByName (@ NotNull final Project project ,
171
- @ NotNull final GlobalSearchScope scope ,
172
- @ NotNull final Class <T > type ,
173
- @ NotNull final String fileName ) {
184
+ private static <T extends OCamlStructuredBinding > T findFileModuleByFileName (@ NotNull final Project project ,
185
+ @ NotNull final GlobalSearchScope scope ,
186
+ @ NotNull final Class <T > type ,
187
+ @ NotNull final String fileName ) {
174
188
final PsiFile [] files = ApplicationManager .getApplication ().runReadAction (new Computable <PsiFile []>() {
175
189
public PsiFile [] compute () {
176
190
return FilenameIndex .getFilesByName (project , fileName , scope );
177
191
}
178
192
});
179
193
180
194
for (final PsiFile file : files ) {
181
- if (type .isInstance (file )) {
182
- //noinspection unchecked
183
- return (T ) file ;
195
+ if (file instanceof OCamlFile ) {
196
+ final T moduleBinding = ((OCamlFile ) file ).getModuleBinding (type );
197
+ if (moduleBinding != null ) {
198
+ return moduleBinding ;
199
+ }
184
200
}
185
201
}
186
202
187
203
return null ;
188
204
}
205
+
206
+ private static void addIfNotNull (@ NotNull final List <OCamlStructuredElement > list , @ Nullable final OCamlStructuredElement item ) {
207
+ if (item != null ) {
208
+ list .add (item );
209
+ }
210
+ }
189
211
}
0 commit comments