11package io .protostuff .jetbrains .plugin .psi ;
22
3+ import static io .protostuff .jetbrains .plugin .psi .ProtoRootNode .ResolveMode .RESOLVE_ALL ;
4+ import static io .protostuff .jetbrains .plugin .psi .ProtoRootNode .ResolveMode .RESOLVE_FIRST ;
5+
36import com .intellij .lang .ASTNode ;
7+ import com .intellij .psi .PsiElement ;
48import com .intellij .psi .PsiReference ;
59import java .util .ArrayDeque ;
610import java .util .ArrayList ;
711import java .util .Arrays ;
812import java .util .Collection ;
13+ import java .util .Collections ;
914import java .util .Deque ;
1015import java .util .HashSet ;
1116import java .util .List ;
1217import java .util .Objects ;
18+ import java .util .Optional ;
1319import java .util .Queue ;
1420import java .util .Set ;
21+ import java .util .function .Function ;
1522import java .util .stream .Collectors ;
1623import org .antlr .jetbrains .adapter .psi .AntlrPsiNode ;
1724import org .jetbrains .annotations .NotNull ;
@@ -46,13 +53,11 @@ public String getPackageName() {
4653 * Resolve data type using given scope lookup list.
4754 */
4855 public DataType resolve (String typeName , Deque <String > scopeLookupList ) {
49- return resolve (typeName , scopeLookupList , true );
56+ Optional <DataType > result = resolveFirst (proto -> proto .resolveLocal (typeName , scopeLookupList ));
57+ return result .orElse (null );
5058 }
5159
52- /**
53- * Resolve data type using given scope lookup list.
54- */
55- public DataType resolve (String typeName , Deque <String > scopeLookupList , boolean resolveInImports ) {
60+ private DataType resolveLocal (String typeName , Deque <String > scopeLookupList ) {
5661 DataType result = null ;
5762 // A leading '.' (for example, .foo.bar.Baz) means to start from the outermost scope
5863 if (typeName .startsWith ("." )) {
@@ -67,25 +72,7 @@ public DataType resolve(String typeName, Deque<String> scopeLookupList, boolean
6772 }
6873 }
6974 }
70- if (result != null ) {
71- return result ;
72- }
73- if (!resolveInImports ) {
74- return null ;
75- }
76- List <ImportNode > importNodes = getImports ();
77- for (ImportNode importNode : importNodes ) {
78- ProtoRootNode targetProto = importNode .getTargetProto ();
79- if (targetProto != null ) {
80- boolean isPublic = importNode .isPublic ();
81- result = targetProto .resolve (typeName , scopeLookupList , isPublic );
82- if (result != null ) {
83- return result ;
84- }
85-
86- }
87- }
88- return null ;
75+ return result ;
8976 }
9077
9178 /**
@@ -186,8 +173,41 @@ public Collection<ExtendNode> getExtenstions(MessageNode target) {
186173 * Returns all extensions visible inside of this proto file.
187174 */
188175 public Collection <ExtendNode > getExtensions () {
189- List <ExtendNode > result = new ArrayList <>();
190- result .addAll (getLocalExtensions ());
176+ return resolveAll (ProtoRootNode ::getLocalExtensions );
177+ }
178+
179+ enum ResolveMode {
180+ RESOLVE_FIRST ,
181+ RESOLVE_ALL
182+ }
183+
184+ @ NotNull
185+ private <T extends PsiElement > Optional <T > resolveFirst (Function <ProtoRootNode , T > extractor ) {
186+ Collection <T > elements = resolveElementsImpl (RESOLVE_FIRST , proto -> {
187+ T result = extractor .apply (proto );
188+ if (result == null ) {
189+ return Collections .emptyList ();
190+ }
191+ return Collections .singletonList (result );
192+ });
193+ if (elements .isEmpty ()) {
194+ return Optional .empty ();
195+ }
196+ return Optional .of (elements .iterator ().next ());
197+ }
198+
199+ @ NotNull
200+ private <T extends PsiElement > Collection <T > resolveAll (Function <ProtoRootNode , Collection <T >> extractor ) {
201+ return resolveElementsImpl (RESOLVE_ALL , extractor );
202+ }
203+
204+ @ NotNull
205+ private <T extends PsiElement > Collection <T > resolveElementsImpl (ResolveMode mode , Function <ProtoRootNode , Collection <T >> extractor ) {
206+ List <T > result = new ArrayList <>();
207+ result .addAll (extractor .apply (this ));
208+ if (stopLookup (mode , result )) {
209+ return result ;
210+ }
191211 Queue <ImportNode > queue = new ArrayDeque <>();
192212 queue .addAll (getImports ());
193213 Set <ProtoRootNode > processedProtos = new HashSet <>();
@@ -201,13 +221,20 @@ public Collection<ExtendNode> getExtensions() {
201221 }
202222 processedProtos .add (targetProto );
203223 if (targetProto != null ) {
204- result .addAll (targetProto . getLocalExtensions ( ));
224+ result .addAll (extractor . apply ( targetProto ));
205225 queue .addAll (targetProto .getPublicImports ());
226+ if (stopLookup (mode , result )) {
227+ break ;
228+ }
206229 }
207230 }
208231 return result ;
209232 }
210233
234+ private <T extends PsiElement > boolean stopLookup (ResolveMode mode , List <T > result ) {
235+ return mode == ResolveMode .RESOLVE_FIRST && !result .isEmpty ();
236+ }
237+
211238 /**
212239 * Returns local extensions declared in this proto file.
213240 */
0 commit comments