14918df0c03d94d3bff7113dd6d39210578808b1
[sdk] / ide / src / designer / findCtx.ec
1 import "ide"
2
3 //extern Class thisClass;
4 extern Class insideClass;
5 extern Expression ctxInsideExp;
6 extern ClassFunction insideFunction;
7 extern ClassDef insideDef;
8 extern bool insideInstance;
9 static bool allocedDummyExp;
10
11 static Class currentClass;
12 static bool isAfterEqual;
13
14 static bool InsideIncl(Location loc, int line, int charPos)
15 {
16    return !loc.start.included && (loc.start.line < line || (loc.start.line == line && loc.start.charPos <= charPos)) &&
17           (loc.end.line > line || (loc.end.line == line && loc.end.charPos >= charPos));
18 }
19
20 static bool Inside(Location loc, int line, int charPos)
21 {
22    return !loc.start.included && (loc.start.line < line || (loc.start.line == line && loc.start.charPos < charPos)) &&
23           (loc.end.line > line || (loc.end.line == line && loc.end.charPos > charPos));
24 }
25
26 static bool InsideEndIncl(Location loc, int line, int charPos)
27 {
28    return !loc.start.included && (loc.start.line < line || (loc.start.line == line && loc.start.charPos < charPos)) &&
29           (loc.end.line > line || (loc.end.line == line && loc.end.charPos >= charPos));
30 }
31
32 static Identifier FindCtxSpecifier(Specifier spec, int line, int charPos)
33 {
34    Identifier idResult;
35    switch(spec.type)
36    {
37       case enumSpecifier:
38       case structSpecifier:
39       case unionSpecifier:
40       {
41          if(spec.definitions)
42          {
43             ClassDef def;
44             for(def = spec.definitions->first; def; def = def.next)
45             {
46                // TODO: Should use the FindCtxClassDef function here right?
47
48                //if(def.type == ClassDefDeclaration && def.decl && def.decl.type == DeclarationStruct)
49                //   ProcessDeclaration(def.decl);
50                switch(def.type)
51                {
52                   case declarationClassDef:
53                      if(InsideIncl(&def.decl.loc, line, charPos))
54                      {
55                         idResult = FindCtxDeclaration(def.decl, line, charPos);
56                         if(idResult)
57                            return idResult;
58                      }
59                      break;
60                   case defaultPropertiesClassDef:
61                   {
62                      MemberInit init;
63                      for(init = def.defProperties->first; init; init = init.next)
64                      {
65                         if(InsideIncl(&init.realLoc, line, charPos))
66                         {
67                            Class oldThisClass = GetThisClass();
68                            Context oldTopContext = GetTopContext();
69                            SetThisClass(currentClass);
70                            idResult = FindCtxMemberInit(init, line, charPos);
71                            if(idResult)
72                               return idResult;
73                            SetThisClass(oldThisClass);
74                         }
75                      }
76                      break;
77                   }
78                   case functionClassDef:
79                      if(InsideIncl(&def.function.loc, line, charPos))
80                      {
81                         idResult = FindCtxClassFunction(def.function, line, charPos);
82
83                         if(idResult)
84                            return idResult;
85                      }
86                      break;
87                   case propertyClassDef:
88                      if(def.propertyDef)
89                      {
90                         if(InsideIncl(&def.propertyDef.loc, line, charPos))
91                         {
92                            idResult = FindCtxProperty(def.propertyDef, line, charPos);
93                            if(idResult)
94                               return idResult;
95                         }
96                      }
97                      break;
98                   case propertyWatchClassDef:
99                      if(def.propertyWatch && def.propertyWatch.compound && InsideIncl(&def.propertyWatch.compound.loc, line, charPos))
100                      {
101                         Class oldThisClass = GetThisClass();
102                         Context oldTopContext = GetTopContext();
103                         SetThisClass(currentClass);
104                         idResult = FindCtxStatement(def.propertyWatch.compound, line, charPos);
105                         if(idResult) return idResult;
106                         SetThisClass(oldThisClass);
107                      }
108                      break;
109                }
110             }
111          }
112          break;
113       }
114    }
115    return null;
116 }
117
118 Identifier FindCtxIdentifier(Identifier id, int line, int charPos)
119 {
120    //if(id.loc.end.line == line && id.loc.end.charPos == charPos)
121    //if(InsideIncl(&id.loc.end.line == line && id.loc.end.charPos == charPos)
122
123    if(id.badID && InsideIncl(&id.badID.loc, line, charPos))
124       return FindCtxIdentifier(id.badID, line, charPos);
125
126    return id;
127    //return null;
128 }
129
130 Identifier FindCtxExpression(Expression exp, int line, int charPos)
131 {
132    Identifier idResult = null;
133    Expression oldExp = ctxInsideExp;
134
135    ctxInsideExp = exp;
136    switch(exp.type)
137    {
138       case newExp:
139          if(InsideIncl(&exp._new.size.loc, line, charPos))
140          {
141             idResult = FindCtxExpression(exp._new.size, line, charPos);
142             if(idResult) return idResult;
143          }
144          break;
145       case renewExp:
146          if(InsideIncl(&exp._renew.exp.loc, line, charPos))
147          {
148             idResult = FindCtxExpression(exp._renew.exp, line, charPos);
149             if(idResult) return idResult;
150          }
151          if(InsideIncl(&exp._renew.size.loc, line, charPos))
152          {
153             idResult = FindCtxExpression(exp._renew.size, line, charPos);
154             if(idResult) return idResult;
155          }
156          break;
157       case constantExp:
158          return (void *)-2;
159       case identifierExp:
160          idResult = FindCtxIdentifier(exp.identifier, line, charPos);
161          if(idResult) return idResult;
162          //return (void *)-1;
163          break;
164       case instanceExp:
165          if(InsideIncl(&exp.instance.loc, line, charPos))
166          {
167             idResult = FindCtxInstance(exp.instance, line, charPos);
168             if(idResult) return idResult;
169          }
170          break;
171       case stringExp:
172          return (void *)-2;
173          //break;
174       case opExp:
175          if(exp.op.exp1)
176          {
177             if(InsideIncl(&exp.op.exp1.loc, line, charPos))
178             {
179                idResult = FindCtxExpression(exp.op.exp1, line, charPos);
180                if(idResult) return idResult;
181             }
182          }
183          if(exp.op.exp2)
184          {
185             // Why was this done?
186             //if(InsideIncl(&exp.op.exp2.loc, line, charPos))
187             if(InsideEndIncl(&exp.op.exp2.loc, line, charPos))
188             {
189                idResult = FindCtxExpression(exp.op.exp2, line, charPos);
190                if(idResult) return idResult;
191             }
192             ctxInsideExp = exp.op.exp2;
193             //return (void *)-1;
194             return (void *)-2;
195          }
196          break;
197       case bracketsExp:
198       {
199          Expression expression;
200
201          for(expression = exp.list->first; expression; expression = expression.next)
202          {
203             if(InsideIncl(&expression.loc, line, charPos))
204             {
205                idResult = FindCtxExpression(expression, line, charPos);
206                if(idResult) return idResult;
207             }
208          }
209          break;
210       }
211       case indexExp:
212       {
213          Expression expression;
214          if(InsideIncl(&exp.index.exp.loc, line, charPos))
215          {
216             idResult = FindCtxExpression(exp.index.exp, line, charPos);
217             if(idResult) return idResult;
218          }
219
220          for(expression = exp.index.index->first; expression; expression = expression.next)
221          {
222             if(InsideIncl(&expression.loc, line, charPos))
223             {
224                idResult = FindCtxExpression(expression, line, charPos);
225                if(idResult) return idResult;
226             }
227          }
228          break;
229       }
230       case callExp:
231       {
232          int arg;
233          Type type = exp.call.exp.expType;
234
235          if(InsideIncl(&exp.call.exp.loc, line, charPos))
236          {
237             idResult = FindCtxExpression(exp.call.exp, line, charPos);
238             if(idResult) return idResult;
239          }
240
241          if(exp.call.argLoc.start.line > line || (line == exp.call.argLoc.start.line && exp.call.argLoc.start.charPos >= charPos))
242             arg = -1;
243          else
244             arg = 0;
245
246          if(exp.call.arguments)
247          {
248             Expression expression;
249
250             ctxInsideExp = null;
251
252             for(expression = exp.call.arguments->first; expression; expression = expression.next)
253             {
254                if(InsideIncl(&expression.loc, line, charPos) || (expression.loc.end.line > line || (line == expression.loc.end.line && expression.loc.end.charPos > charPos)))
255                {
256                   if(InsideIncl(&expression.loc, line, charPos))
257                      idResult = FindCtxExpression(expression, line, charPos);
258
259                   // Break
260                   break;
261                }
262                arg++;
263             }
264
265             if(type && type.kind == methodType && type.method)
266                type = type.method.dataType;
267
268             if(!ctxInsideExp && /*ctxInsideExp == exp && */type && type.kind == functionType)
269             {
270                int c;
271                Type param;
272
273                for(param = type.params.first, c = 0; c<arg && param; c++, param = param.next);
274
275                if(param && arg != -1)
276                {
277                   allocedDummyExp = true;
278                   ctxInsideExp = MkExpDummy();
279                   ctxInsideExp.destType = param;
280                   if(param) param.refCount++;
281                   return idResult ? idResult : (void *)-1;
282                }
283             }
284             if(idResult)
285                return idResult;
286          }
287          break;
288       }
289       case memberExp:
290          if(InsideIncl(&exp.member.exp.loc, line, charPos))
291          {
292             idResult = FindCtxExpression(exp.member.exp, line, charPos);
293             if(idResult) return idResult;
294          }
295          if(exp.addedThis)
296             return exp.member.member; //(void *)-1;
297
298          break;
299       case pointerExp:
300          if(InsideIncl(&exp.member.exp.loc, line, charPos))
301          {
302             idResult = FindCtxExpression(exp.member.exp, line, charPos);
303             if(idResult) return idResult;
304          }
305          break;
306       case typeSizeExp:
307          break;
308       case castExp:
309          if(InsideIncl(&exp.cast.exp.loc, line, charPos))
310          {
311             idResult = FindCtxExpression(exp.cast.exp, line, charPos);
312             if(idResult) return idResult;
313          }
314          break;
315       case conditionExp:
316          if(Inside(&exp.cond.cond.loc, line, charPos))
317          {
318             idResult = FindCtxExpression(exp.cond.cond, line, charPos);
319             if(idResult) return idResult;
320          }
321
322          {
323             Expression expression;
324             for(expression = exp.cond.exp->first; expression; expression = expression.next)
325             {
326                if(InsideIncl(&expression.loc, line, charPos))
327                {
328                   idResult = FindCtxExpression(expression, line, charPos);
329                   if(idResult) return idResult;
330                }
331             }
332          }
333          if(InsideIncl(&exp.cond.elseExp.loc, line, charPos))
334          {
335             idResult = FindCtxExpression(exp.cond.elseExp, line, charPos);
336             if(idResult) return idResult;
337          }
338          break;
339       case dummyExp:
340          return (void *)-2;
341    }
342
343    if(exp.destType && !exp.destType.truth) // && !exp.addedThis)
344       return (void *)-1;
345
346    ctxInsideExp = oldExp;
347    return null;
348 }
349
350 static Identifier FindCtxStatement(Statement stmt, int line, int charPos)
351 {
352    Identifier idResult;
353
354    switch(stmt.type)
355    {
356       case labeledStmt:
357          if(InsideIncl(&stmt.labeled.stmt.loc, line, charPos))
358             return FindCtxStatement(stmt.labeled.stmt, line, charPos);
359          break;
360       case caseStmt:
361          if(stmt.caseStmt.exp)
362          {
363             if(InsideIncl(&stmt.caseStmt.exp.loc, line, charPos))
364                return FindCtxExpression(stmt.caseStmt.exp, line, charPos);
365          }
366
367          if(stmt.caseStmt.stmt)
368          {
369             if(InsideIncl(&stmt.caseStmt.stmt.loc, line, charPos))
370                return FindCtxStatement(stmt.caseStmt.stmt, line, charPos);
371          }
372          break;
373       case badDeclarationStmt:
374       {
375          Declaration decl = stmt.decl;
376          if(InsideIncl(&decl.loc, line, charPos))
377          {
378             idResult = FindCtxDeclaration(decl, line, charPos);
379             if(idResult) return idResult;
380          }
381          break;
382       }
383       case compoundStmt:
384       {
385          if(!stmt.compound.isSwitch)
386             SetCurrentContext(stmt.compound.context);
387          if(stmt.compound.declarations)
388          {
389             Declaration decl;
390             for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
391             {
392                if(InsideIncl(&decl.loc, line, charPos))
393                {
394                   idResult = FindCtxDeclaration(decl, line, charPos);
395                   if(idResult) return idResult;
396                }
397             }
398          }
399          if(stmt.compound.statements)
400          {
401             Statement statement;
402             for(statement = stmt.compound.statements->first; statement; statement = statement.next)
403             {
404                if(InsideIncl(&statement.loc, line, charPos))
405                {
406                   idResult = FindCtxStatement(statement, line, charPos);
407                   if(idResult) return idResult;
408                }
409             }
410          }
411          return (void *)-1;
412          //curContext = stmt.compound.context.parent;
413          //break;
414       }
415       case expressionStmt:
416       {
417          if(stmt.expressions)
418          {
419             Expression exp;
420             for(exp = stmt.expressions->first; exp; exp = exp.next)
421             {
422                if(InsideIncl(&exp.loc, line, charPos))
423                {
424                   idResult = FindCtxExpression(exp, line, charPos);
425                   if(idResult) return idResult;
426                }
427             }
428          }
429          break;
430       }
431       case ifStmt:
432       {
433          Expression exp;
434          for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
435          {
436             if(InsideIncl(&exp.loc, line, charPos))
437             {
438                idResult = FindCtxExpression(exp, line, charPos);
439                if(idResult) return idResult;
440             }
441          }
442          if(stmt.ifStmt.stmt)
443          {
444             if(InsideIncl(&stmt.ifStmt.stmt.loc, line, charPos))
445             {
446                idResult = FindCtxStatement(stmt.ifStmt.stmt, line, charPos);
447                if(idResult) return idResult;
448             }
449          }
450          if(stmt.ifStmt.elseStmt)
451          {
452             if(InsideIncl(&stmt.ifStmt.elseStmt.loc, line, charPos))
453                return FindCtxStatement(stmt.ifStmt.elseStmt, line, charPos);
454          }
455          break;
456       }
457       case switchStmt:
458       {
459          Expression exp;
460          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
461          {
462             if(InsideIncl(&exp.loc, line, charPos))
463             {
464                idResult = FindCtxExpression(exp, line, charPos);
465                if(idResult) return idResult;
466             }
467          }
468          if(InsideIncl(&stmt.switchStmt.stmt.loc, line, charPos))
469             return FindCtxStatement(stmt.switchStmt.stmt, line, charPos);
470          break;
471       }
472       case whileStmt:
473       {
474          Expression exp;
475          if(stmt.whileStmt.exp)
476          {
477             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
478             {
479                if(InsideIncl(&exp.loc, line, charPos))
480                {
481                   idResult = FindCtxExpression(exp, line, charPos);
482                   if(idResult) return idResult;
483                }
484             }
485          }
486          if(stmt.whileStmt.stmt && InsideIncl(&stmt.whileStmt.stmt.loc, line, charPos))
487             return FindCtxStatement(stmt.whileStmt.stmt, line, charPos);
488          break;
489       }
490       case doWhileStmt:
491       {
492          if(InsideIncl(&stmt.doWhile.stmt.loc, line, charPos))
493          {
494             idResult = FindCtxStatement(stmt.doWhile.stmt, line, charPos);
495             if(idResult) return idResult;
496          }
497
498          if(stmt.doWhile.exp)
499          {
500             Expression exp;
501             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
502             {
503                if(InsideIncl(&exp.loc, line, charPos))
504                {
505                   idResult = FindCtxExpression(exp, line, charPos);
506                   if(idResult) return idResult;
507                }
508             }
509          }
510          break;
511       }
512       case forStmt:
513       {
514          Expression exp;
515
516          if(stmt.forStmt.init && InsideIncl(&stmt.forStmt.init.loc, line, charPos))
517          {
518             idResult = FindCtxStatement(stmt.forStmt.init, line, charPos);
519             if(idResult) return idResult;
520          }
521
522          if(stmt.forStmt.check && InsideIncl(&stmt.forStmt.check.loc, line, charPos))
523          {
524             idResult = FindCtxStatement(stmt.forStmt.check, line, charPos);
525             if(idResult) return idResult;
526          }
527
528          if(stmt.forStmt.increment)
529          {
530             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
531             {
532                if(InsideIncl(&exp.loc, line, charPos))
533                {
534                   idResult = FindCtxExpression(exp, line, charPos);
535                   if(idResult) return idResult;
536                }
537             }
538          }
539
540          if(stmt.forStmt.stmt)
541             return FindCtxStatement(stmt.forStmt.stmt, line, charPos);
542          break;
543       }
544       case gotoStmt:
545          break;
546       case continueStmt:
547          break;
548       case breakStmt:
549          break;
550       case returnStmt:
551          if(stmt.expressions)
552          {
553             Expression exp;
554
555             for(exp = stmt.expressions->first; exp; exp = exp.next)
556             {
557                if(InsideIncl(&exp.loc, line, charPos))
558                {
559                   idResult = FindCtxExpression(exp, line, charPos);
560                   if(idResult) return idResult;
561                }
562             }
563          }
564          break;
565       case fireWatchersStmt:
566       case stopWatchingStmt:
567       {
568          Identifier _watch;
569          if(stmt._watch.watcher && InsideIncl(&stmt._watch.watcher.loc, line, charPos))
570          {
571             idResult = FindCtxExpression(stmt._watch.watcher, line, charPos);
572             if(idResult) return idResult;
573          }
574          if(stmt._watch.object && InsideIncl(&stmt._watch.object.loc, line, charPos))
575          {
576             idResult = FindCtxExpression(stmt._watch.object, line, charPos);
577             if(idResult) return idResult;
578          }
579          if(stmt._watch.watches)
580          {
581             for(_watch = stmt._watch.watches->first; _watch; _watch = _watch.next)
582             {
583                if(InsideIncl(&_watch.loc, line, charPos))
584                {
585                   idResult = FindCtxIdentifier(_watch, line, charPos);
586                   if(idResult) return idResult;
587                }
588             }
589          }
590          break;
591       }
592       case watchStmt:
593       {
594          PropertyWatch _watch;
595          if(stmt._watch.watcher && InsideIncl(&stmt._watch.watcher.loc, line, charPos))
596          {
597             idResult = FindCtxExpression(stmt._watch.watcher, line, charPos);
598             if(idResult) return idResult;
599          }
600          if(stmt._watch.object && InsideIncl(&stmt._watch.object.loc, line, charPos))
601          {
602             idResult = FindCtxExpression(stmt._watch.object, line, charPos);
603             if(idResult) return idResult;
604          }
605          if(stmt._watch.watches)
606          {
607             for(_watch = stmt._watch.watches->first; _watch; _watch = _watch.next)
608             {
609                if(_watch.compound && InsideIncl(&_watch.compound.loc, line, charPos))
610                {
611                   idResult = FindCtxStatement(_watch.compound, line, charPos);
612                   if(idResult) return idResult;
613                }
614             }
615          }
616          break;
617       }
618    }
619    return null;
620 }
621
622 static Identifier FindCtxInitializer(Initializer initializer, int line, int charPos)
623 {
624    switch(initializer.type)
625    {
626       case listInitializer:
627       {
628          Initializer init;
629          Identifier idResult;
630
631          for(init = initializer.list->first; init; init = init.next)
632          {
633             if(InsideIncl(&init.loc, line, charPos))
634             {
635                idResult = FindCtxInitializer(init, line, charPos);
636                if(idResult) return idResult;
637             }
638          }
639          break;
640       }
641       case expInitializer:
642          if(InsideIncl(&initializer.exp.loc, line, charPos))
643             return FindCtxExpression(initializer.exp, line, charPos);
644
645          {
646             ctxInsideExp = initializer.exp;
647             return (void *)-1;
648          }
649          break;
650    }
651    return null;
652 }
653
654 static Identifier FindCtxInitDeclarator(InitDeclarator decl, int line, int charPos)
655 {
656    if(decl.initializer && InsideIncl(&decl.initializer.loc, line, charPos))
657       return FindCtxInitializer(decl.initializer, line, charPos);
658    return null;
659 }
660
661 static Identifier FindCtxDeclaration(Declaration decl, int line, int charPos)
662 {
663    Identifier idResult;
664
665    switch(decl.type)
666    {
667       case structDeclaration:
668       {
669          Specifier spec;
670          if(decl.specifiers)
671          {
672             for(spec = decl.specifiers->first; spec; spec = spec.next)
673             {
674                if(InsideIncl(&spec.loc, line, charPos))
675                {
676                   idResult = FindCtxSpecifier(spec, line, charPos);
677                   if(idResult) return idResult;
678                }
679             }
680          }
681          /*Declarator d;
682          if(decl.declarators && decl.declarators->first)
683          {
684             for(d = decl.declarators->first; d; d = d.next)
685             {
686                if(InsideIncl(&d.loc, line, charPos))
687                {
688                   if(d.type == DeclaratorStruct && d.declarator && d.declarator.type == DeclaratorIdentifier)
689                      return d.declarator.identifier;
690                }
691             }
692          }
693          */
694          break;
695       }
696       case initDeclaration:
697       {
698          // Need to loop through specifiers to look for :: completion
699          if(decl.specifiers)
700          {
701             Specifier s;
702
703             for(s = decl.specifiers->first; s; s = s.next)
704             {
705                if(InsideIncl(&s.loc, line, charPos))
706                {
707                   idResult = FindCtxSpecifier(s, line, charPos);
708                   if(idResult) return idResult;
709                }
710             }
711          }
712
713          if(decl.declarators && decl.declarators->first)
714          {
715             InitDeclarator d;
716             for(d = decl.declarators->first; d; d = d.next)
717             {
718                if(InsideIncl(&d.loc, line, charPos))
719                {
720                   idResult = FindCtxInitDeclarator(d, line, charPos);
721                   if(idResult) return idResult;
722                }
723             }
724          }
725          break;
726       }
727       case instDeclaration:
728          if(InsideIncl(&decl.inst.loc, line, charPos))
729             return FindCtxInstance(decl.inst, line, charPos);
730          break;
731    }
732    return null;
733 }
734
735 static Identifier FindCtxFunction(FunctionDefinition func, int line, int charPos)
736 {
737    if(func.body && Inside(&func.body.loc, line, charPos))
738    {
739       Identifier idResult;
740
741       Identifier id = GetDeclId(func.declarator);
742       Symbol symbol = func.declarator.symbol;
743       Type type = symbol.type;
744       Class oldThisClass = GetThisClass();
745       Context oldTopContext = GetTopContext();
746
747       idResult = FindCtxStatement(func.body, line, charPos);
748       if(idResult)
749          return idResult;
750
751       SetThisClass(oldThisClass);
752       SetTopContext(oldTopContext);
753    }
754    return null;
755 }
756
757 static Identifier FindCtxMemberInit(MemberInit init, int line, int charPos)
758 {
759    Identifier idResult;
760    if(init.initializer && InsideIncl(&init.initializer.loc, line, charPos))
761    {
762       idResult = FindCtxInitializer(init.initializer, line, charPos);
763       if(idResult)
764       {
765          if(init.identifiers && init.identifiers->first)
766             isAfterEqual = true;
767          return idResult;
768       }
769    }
770    if(init.identifiers && init.identifiers->first && InsideIncl(&((Identifier)init.identifiers->first).loc, line, charPos))
771    {
772       idResult = FindCtxIdentifier(init.identifiers->first, line, charPos);
773       if(idResult)
774          return (void *)-2; //idResult;
775    }
776    if(init.initializer && Inside(&init.initializer.loc, line, charPos))
777    {
778       if(init.identifiers && init.identifiers->first)
779          isAfterEqual = true;
780
781       if(init.initializer.type == expInitializer)
782       {
783          ctxInsideExp = init.initializer.exp;
784          return (void *)-1;
785       }
786    }
787    return null;
788 }
789
790 static Identifier FindCtxInstance(Instantiation inst, int line, int charPos)
791 {
792    Identifier idResult = null;
793    Class oldThisClass = GetThisClass();
794    Symbol sym = inst._class ? FindClass(inst._class.name) : null;
795    bool insideSomething = false;
796    bool insideBrackets;
797    Method method = null;
798
799    Class curClass = null;
800    DataMember curMember = null;
801    DataMember dataMember = null;
802    DataMember subMemberStack[256];
803    int subMemberStackPos = 0;
804
805    if(sym)
806       SetThisClass(sym.registered);
807
808    insideBrackets = !(inst.insideLoc.start.line > line || (line == inst.insideLoc.start.line && inst.insideLoc.start.charPos > charPos));
809    if(insideBrackets)
810    {
811       // Start with first member
812       eClass_FindNextMember(GetThisClass(), &curClass, &curMember, subMemberStack, &subMemberStackPos);
813       dataMember = curMember;
814    }
815
816    if(inst.members)
817    {
818       MembersInit init;
819       MemberInit memberInit;
820       for(init = inst.members->first; init; init = init.next)
821       {
822          if(init.loc.start.line > line || (line == init.loc.start.line && init.loc.start.charPos > charPos))
823             break;
824
825          if(init.type == dataMembersInit && init.dataMembers && insideBrackets && sym)
826          {
827             for(memberInit = init.dataMembers->first; memberInit; memberInit = memberInit.next)
828             {
829                isAfterEqual = false;
830
831                if(memberInit.identifiers && memberInit.identifiers->first)
832                {
833                   DataMember _subMemberStack[256];
834                   int _subMemberStackPos = 0;
835                   DataMember thisMember = eClass_FindDataMember(GetThisClass(), ((Identifier)memberInit.identifiers->first).string, GetPrivateModule(), _subMemberStack, &_subMemberStackPos);
836                   if(!thisMember)
837                   {
838                      // WARNING: Brackets needed until precomp fix
839                      thisMember = (DataMember)eClass_FindProperty(GetThisClass(), ((Identifier)memberInit.identifiers->first).string, GetPrivateModule());
840                   }
841                   if(thisMember)
842                   {
843                      method = null;
844                      dataMember = thisMember;
845                      if(thisMember.memberAccess == publicAccess)
846                      {
847                         curMember = thisMember;
848                         curClass = thisMember._class;
849                         memcpy(subMemberStack, _subMemberStack, sizeof(DataMember) * _subMemberStackPos);
850                         subMemberStackPos = _subMemberStackPos;
851                      }
852                   }
853                   else
854                      method = eClass_FindMethod(GetThisClass(), ((Identifier)memberInit.identifiers->first).string, GetPrivateModule());
855                }
856
857                if(!idResult && InsideIncl(&memberInit.realLoc, line, charPos))
858                   idResult = FindCtxMemberInit(memberInit, line, charPos);
859
860                if(InsideIncl(&memberInit.realLoc, line, charPos) || (memberInit.realLoc.end.line > line || (line == memberInit.realLoc.end.line && memberInit.realLoc.end.charPos > charPos)))
861                {
862                   if(memberInit.identifiers && memberInit.identifiers->first && InsideIncl(&memberInit.loc, line, charPos) && !dataMember)
863                      insideBrackets = false;
864                   break;
865                }
866                else if((!memberInit.identifiers || !memberInit.identifiers->first || dataMember) && (memberInit.next || !Inside(&init.loc, line, charPos)))
867                {
868                   method = null;
869                   eClass_FindNextMember(GetThisClass(), &curClass, &curMember, subMemberStack, &subMemberStackPos);
870                   dataMember = curMember;
871                }
872             }
873          }
874
875          if(InsideIncl(&init.loc, line, charPos))
876          {
877             if(Inside(&init.loc, line, charPos))
878                if(init.type == methodMembersInit)
879                   insideSomething = true;
880
881             if(init.type == methodMembersInit && Inside(&init.function.loc, line, charPos))
882             {
883                idResult = FindCtxClassFunction(init.function, line, charPos);
884                if(init.function == insideFunction)
885                   insideDef = (ClassDef)init; // Only using prev member of insideDef
886             }
887
888             if(Inside(&init.loc, line, charPos))
889                break;
890          }
891
892          if((init.loc.end.line > line || (line == init.loc.end.line && init.loc.end.charPos > charPos)))
893             break;
894       }
895    }
896    if((!idResult || idResult != (Identifier)-1) && sym && sym.registered && InsideIncl(&inst.insideLoc, line, charPos) && insideBrackets && !insideSomething)
897    {
898       if(dataMember && !method)
899       {
900          if(!dataMember.dataType)
901             dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
902          allocedDummyExp = true;
903          ctxInsideExp = MkExpDummy();
904          ctxInsideExp.destType = dataMember.dataType;
905          if(ctxInsideExp.destType) ctxInsideExp.destType.refCount++;
906       }
907    }
908
909    if((!idResult || idResult != (Identifier)-1) && sym && sym.registered && InsideIncl(&inst.insideLoc, line, charPos) && !insideSomething && insideBrackets)
910    {
911       if(method)
912       {
913          allocedDummyExp = true;
914          ctxInsideExp = MkExpDummy();
915          ctxInsideExp.destType = method.dataType;
916          if(ctxInsideExp.destType) ctxInsideExp.destType.refCount++;
917       }
918    }
919
920    if(sym && !insideSomething && InsideIncl(&inst.insideLoc, line, charPos))
921    {
922       if(!isAfterEqual && !insideClass && (!idResult || idResult == (void *)-2))
923          insideClass = sym.registered;
924
925       if(isAfterEqual && currentClass)
926          SetThisClass(currentClass);
927
928       return idResult ? idResult : (void *) -1;
929    }
930    if(idResult)
931       return idResult;
932
933    SetThisClass(oldThisClass);
934
935    return null;
936 }
937
938 static Identifier FindCtxClassFunction(ClassFunction func, int line, int charPos)
939 {
940    if(func.body && Inside(&func.body.loc, line, charPos))
941    {
942       Identifier idResult;
943
944       Identifier id = GetDeclId(func.declarator);
945       Symbol symbol = func.declarator ? func.declarator.symbol : null;
946       Type type = symbol ? symbol.type : null;
947       Class oldThisClass = GetThisClass();
948       Context oldTopContext = GetTopContext();
949       SetThisClass((type && type.thisClass) ? type.thisClass.registered : currentClass);
950
951       if(func.body)
952       {
953          idResult = FindCtxStatement(func.body, line, charPos);
954          if(idResult)
955             return idResult;
956       }
957
958       SetThisClass(oldThisClass);
959       SetTopContext(oldTopContext);
960    }
961    else if(!func.body && GetFuncDecl(func.declarator))
962    {
963       if(!GetThisClass())
964          SetThisClass(currentClass);
965       else
966       {
967          insideInstance = true;
968          // Is this insideClass ever used?
969          insideClass = GetThisClass(); //currentClass;
970       }
971       insideFunction = func;
972       return (void *)-1;
973    }
974    else if(!func.body && GetDeclId(func.declarator))
975    {
976       if(!GetThisClass())
977          SetThisClass(currentClass);
978       else
979       {
980          insideInstance = true;
981
982          // Has to be GetThisClass() to work...
983          insideClass = GetThisClass();//currentClass;
984       }
985       return (void *)-1;
986    }
987    else
988    {
989       // TESTING THIS FOR HANDLING: bool ^bool NotifyClicked
990       insideInstance = true;
991
992       // Has to be GetThisClass() to work...
993       insideClass = GetThisClass();//currentClass;
994    }
995    return null;
996 }
997
998 static Identifier FindCtxProperty(PropertyDef def, int line, int charPos)
999 {
1000    Identifier result;
1001    if(def.getStmt && Inside(&def.getStmt.loc, line, charPos))
1002    {
1003       Class oldThisClass = GetThisClass();
1004       Context oldTopContext = GetTopContext();
1005       SetThisClass(currentClass);
1006       result = FindCtxStatement(def.getStmt, line, charPos);
1007       if(result) return result;
1008       SetThisClass(oldThisClass);
1009    }
1010    if(def.setStmt && Inside(&def.setStmt.loc, line, charPos))
1011    {
1012       Class oldThisClass = GetThisClass();
1013       Context oldTopContext = GetTopContext();
1014       SetThisClass(currentClass);
1015       result = FindCtxStatement(def.setStmt, line, charPos);
1016       if(result) return result;
1017       SetThisClass(oldThisClass);
1018    }
1019    return null;
1020 }
1021
1022 static Identifier FindCtxClassDef(ClassDef def, int line, int charPos)
1023 {
1024    Identifier idResult;
1025    switch(def.type)
1026    {
1027       case declarationClassDef:
1028          if(InsideEndIncl(&def.decl.loc, line, charPos))
1029          {
1030             idResult = FindCtxDeclaration(def.decl, line, charPos);
1031             if(idResult)
1032                return idResult;
1033          }
1034          break;
1035       case defaultPropertiesClassDef:
1036       {
1037          MemberInit init;
1038          for(init = def.defProperties->first; init; init = init.next)
1039          {
1040             if(InsideIncl(&init.realLoc, line, charPos))
1041             {
1042                Class oldThisClass = GetThisClass();
1043                Context oldTopContext = GetTopContext();
1044                SetThisClass(currentClass);
1045                idResult = FindCtxMemberInit(init, line, charPos);
1046                if(idResult)
1047                   return idResult;
1048                SetThisClass(oldThisClass);
1049             }
1050          }
1051          break;
1052       }
1053       case functionClassDef:
1054          if(Inside(&def.function.loc, line, charPos))
1055          {
1056             idResult = FindCtxClassFunction(def.function, line, charPos);
1057             if(def.function == insideFunction)
1058                insideDef = def;
1059
1060             if(idResult)
1061                return idResult;
1062          }
1063          break;
1064       case propertyClassDef:
1065          if(def.propertyDef)
1066          {
1067             if(Inside(&def.propertyDef.loc, line, charPos))
1068             {
1069                idResult = FindCtxProperty(def.propertyDef, line, charPos);
1070                if(idResult)
1071                   return idResult;
1072             }
1073          }
1074          break;
1075       case propertyWatchClassDef:
1076          if(def.propertyWatch && def.propertyWatch.compound && Inside(&def.propertyWatch.compound.loc, line, charPos))
1077          {
1078             Class oldThisClass = GetThisClass();
1079             Context oldTopContext = GetTopContext();
1080             SetThisClass(currentClass);
1081             idResult = FindCtxStatement(def.propertyWatch.compound, line, charPos);
1082             if(idResult) return idResult;
1083             SetThisClass(oldThisClass);
1084          }
1085          break;
1086    }
1087    return null;
1088 }
1089
1090 static Identifier FindCtxClass(ClassDefinition _class, int line, int charPos)
1091 {
1092    Identifier idResult;
1093    bool insideSomething = false;
1094    if(_class.definitions)
1095    {
1096       ClassDef def;
1097       for(def = _class.definitions->first; def; def = def.next)
1098       {
1099          if(def.type == defaultPropertiesClassDef ? InsideIncl(&def.loc, line, charPos) : Inside(&def.loc, line, charPos) )
1100          {
1101             if(def.type != defaultPropertiesClassDef)
1102                insideSomething = true;
1103
1104             idResult = FindCtxClassDef(def, line, charPos);
1105             if(idResult)
1106                return idResult;
1107             else
1108                insideSomething = false;
1109          }
1110       }
1111    }
1112    if(!insideSomething && line > _class.blockStart.start.line || (line == _class.blockStart.start.line && charPos >= _class.blockStart.start.charPos) )
1113    {
1114       insideClass = _class.symbol.registered;
1115       return (void *)-1;
1116    }
1117    return null;
1118 }
1119
1120 Identifier FindCtxTree(OldList ast, int line, int charPos)
1121 {
1122    Identifier idResult;
1123    External external;
1124
1125    if(allocedDummyExp)
1126    {
1127       FreeExpression(ctxInsideExp);
1128       allocedDummyExp = false;
1129    }
1130
1131    insideClass = null;
1132    ctxInsideExp = null;
1133    SetThisClass(null);
1134    insideFunction = null;
1135    insideInstance = false;
1136    isAfterEqual = false;
1137
1138    if(ast != null)
1139    {
1140       for(external = ast.first; external; external = external.next)
1141       {
1142          switch(external.type)
1143          {
1144             case functionExternal:
1145                if(Inside(&external.loc, line, charPos))
1146                {
1147                   idResult = FindCtxFunction(external.function, line, charPos);
1148                   if(idResult)
1149                      return (idResult == (void *)-1 || idResult == (void *)-2) ? null : idResult;
1150                }
1151                break;
1152             case declarationExternal:
1153                if(InsideIncl(&external.loc, line, charPos))
1154                {
1155                   idResult = FindCtxDeclaration(external.declaration, line, charPos);
1156                   if(idResult)
1157                      return (idResult == (void *)-1 || idResult == (void *)-2) ? null : idResult;
1158                }
1159                break;
1160             case classExternal:
1161                if(Inside(&external._class.loc, line, charPos))
1162                {
1163                   currentClass = external._class.symbol.registered;
1164                   idResult = FindCtxClass(external._class, line, charPos);
1165                   currentClass = null;
1166                   if(idResult)
1167                      return (idResult == (void *)-1 || idResult == (void *)-2) ? null : idResult;
1168                }
1169                break;
1170          }
1171       }
1172    }
1173    return null;
1174 }
1175
1176 void FindCtx_Terminate()
1177 {
1178    if(allocedDummyExp)
1179    {
1180       FreeExpression(ctxInsideExp);
1181       allocedDummyExp = false;
1182    }
1183 }