774cd9a58bf10c3ab846d8d2c9f91a172569fa03
[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(Inside(&expression.loc, line, charPos))
257                      idResult = FindCtxExpression(expression, line, charPos);
258                   
259                   // Break
260                   break;
261                }
262                arg++;
263             }
264
265
266             if(!ctxInsideExp && /*ctxInsideExp == exp && */type && type.kind == functionType)
267             {
268                int c;
269                Type param;
270
271                for(param = type.params.first, c = 0; c<arg && param; c++, param = param.next);
272
273                if(param && arg != -1)
274                {
275                   allocedDummyExp = true;
276                   ctxInsideExp = MkExpDummy();
277                   ctxInsideExp.destType = param;
278                   if(param) param.refCount++;
279                   return idResult ? idResult : (void *)-1;
280                }
281             }
282             if(idResult) 
283                return idResult;
284          }
285          break;
286       }
287       case memberExp:
288          if(InsideIncl(&exp.member.exp.loc, line, charPos))
289          {
290             idResult = FindCtxExpression(exp.member.exp, line, charPos);
291             if(idResult) return idResult;
292          }
293          if(exp.addedThis)
294             return exp.member.member; //(void *)-1;
295
296          break;
297       case pointerExp:
298          if(InsideIncl(&exp.member.exp.loc, line, charPos))
299          {
300             idResult = FindCtxExpression(exp.member.exp, line, charPos);
301             if(idResult) return idResult;
302          }
303          break;
304       case typeSizeExp:
305          break;
306       case castExp:
307          if(InsideIncl(&exp.cast.exp.loc, line, charPos))
308          {
309             idResult = FindCtxExpression(exp.cast.exp, line, charPos);
310             if(idResult) return idResult;
311          }
312          break;
313       case conditionExp:
314          if(Inside(&exp.cond.cond.loc, line, charPos))
315          {
316             idResult = FindCtxExpression(exp.cond.cond, line, charPos);
317             if(idResult) return idResult;
318          }
319
320          {
321             Expression expression;
322             for(expression = exp.cond.exp->first; expression; expression = expression.next)
323             {
324                if(InsideIncl(&expression.loc, line, charPos))
325                {
326                   idResult = FindCtxExpression(expression, line, charPos);
327                   if(idResult) return idResult;
328                }
329             }
330          }
331          if(InsideIncl(&exp.cond.elseExp.loc, line, charPos))
332          {
333             idResult = FindCtxExpression(exp.cond.elseExp, line, charPos);
334             if(idResult) return idResult;
335          }
336          break;
337       case dummyExp:
338          return (void *)-2;
339    }
340    
341    if(exp.destType && !exp.destType.truth) // && !exp.addedThis)
342       return (void *)-1;
343    
344    ctxInsideExp = oldExp;
345    return null;
346 }
347
348 static Identifier FindCtxStatement(Statement stmt, int line, int charPos)
349 {
350    Identifier idResult;
351
352    switch(stmt.type)
353    {
354       case labeledStmt:
355          if(InsideIncl(&stmt.labeled.stmt.loc, line, charPos))
356             return FindCtxStatement(stmt.labeled.stmt, line, charPos);
357          break;
358       case caseStmt:
359          if(stmt.caseStmt.exp)
360          {
361             if(InsideIncl(&stmt.caseStmt.exp.loc, line, charPos))
362                return FindCtxExpression(stmt.caseStmt.exp, line, charPos);
363          }
364
365          if(stmt.caseStmt.stmt)
366          {
367             if(InsideIncl(&stmt.caseStmt.stmt.loc, line, charPos))
368                return FindCtxStatement(stmt.caseStmt.stmt, line, charPos);
369          }
370          break;
371       case badDeclarationStmt:
372       {
373          Declaration decl = stmt.decl;
374          if(InsideIncl(&decl.loc, line, charPos))
375          {
376             idResult = FindCtxDeclaration(decl, line, charPos);
377             if(idResult) return idResult;
378          }
379          break;
380       }
381       case compoundStmt:
382       {
383          if(!stmt.compound.isSwitch)
384             SetCurrentContext(stmt.compound.context);
385          if(stmt.compound.declarations)
386          {
387             Declaration decl;
388             for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
389             {
390                if(InsideIncl(&decl.loc, line, charPos))
391                {
392                   idResult = FindCtxDeclaration(decl, line, charPos);
393                   if(idResult) return idResult;
394                }
395             }
396          }
397          if(stmt.compound.statements)
398          {
399             Statement statement;
400             for(statement = stmt.compound.statements->first; statement; statement = statement.next)
401             {
402                if(InsideIncl(&statement.loc, line, charPos))
403                {
404                   idResult = FindCtxStatement(statement, line, charPos);
405                   if(idResult) return idResult;
406                }
407             }
408          }
409          return (void *)-1;
410          //curContext = stmt.compound.context.parent;
411          //break;
412       }
413       case expressionStmt:
414       {
415          if(stmt.expressions)
416          {
417             Expression exp;
418             for(exp = stmt.expressions->first; exp; exp = exp.next)
419             {
420                if(InsideIncl(&exp.loc, line, charPos))
421                {
422                   idResult = FindCtxExpression(exp, line, charPos);
423                   if(idResult) return idResult;
424                }
425             }
426          }
427          break;
428       }
429       case ifStmt:
430       {
431          Expression exp;
432          for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
433          {
434             if(InsideIncl(&exp.loc, line, charPos))
435             {
436                idResult = FindCtxExpression(exp, line, charPos);
437                if(idResult) return idResult;
438             }
439          }
440          if(stmt.ifStmt.stmt)
441          {
442             if(InsideIncl(&stmt.ifStmt.stmt.loc, line, charPos))
443             {
444                idResult = FindCtxStatement(stmt.ifStmt.stmt, line, charPos);
445                if(idResult) return idResult;
446             }
447          }
448          if(stmt.ifStmt.elseStmt)
449          {
450             if(InsideIncl(&stmt.ifStmt.elseStmt.loc, line, charPos))
451                return FindCtxStatement(stmt.ifStmt.elseStmt, line, charPos);
452          }
453          break;
454       }
455       case switchStmt:
456       {
457          Expression exp;
458          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
459          {
460             if(InsideIncl(&exp.loc, line, charPos))
461             {
462                idResult = FindCtxExpression(exp, line, charPos);
463                if(idResult) return idResult;
464             }
465          }
466          if(InsideIncl(&stmt.switchStmt.stmt.loc, line, charPos))
467             return FindCtxStatement(stmt.switchStmt.stmt, line, charPos);
468          break;
469       }
470       case whileStmt:
471       {
472          Expression exp;
473          if(stmt.whileStmt.exp)
474          {
475             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
476             {
477                if(InsideIncl(&exp.loc, line, charPos))
478                {
479                   idResult = FindCtxExpression(exp, line, charPos);
480                   if(idResult) return idResult;
481                }
482             }
483          }
484          if(stmt.whileStmt.stmt && InsideIncl(&stmt.whileStmt.stmt.loc, line, charPos))
485             return FindCtxStatement(stmt.whileStmt.stmt, line, charPos);
486          break;
487       }
488       case doWhileStmt:
489       {
490          if(InsideIncl(&stmt.doWhile.stmt.loc, line, charPos))
491          {
492             idResult = FindCtxStatement(stmt.doWhile.stmt, line, charPos);
493             if(idResult) return idResult;
494          }
495
496          if(stmt.doWhile.exp)
497          {
498             Expression exp;
499             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
500             {
501                if(InsideIncl(&exp.loc, line, charPos))
502                {
503                   idResult = FindCtxExpression(exp, line, charPos);
504                   if(idResult) return idResult;
505                }
506             }
507          }
508          break;
509       }
510       case forStmt:
511       {
512          Expression exp;
513
514          if(stmt.forStmt.init && InsideIncl(&stmt.forStmt.init.loc, line, charPos))
515          {
516             idResult = FindCtxStatement(stmt.forStmt.init, line, charPos);
517             if(idResult) return idResult;
518          }
519          
520          if(stmt.forStmt.check && InsideIncl(&stmt.forStmt.check.loc, line, charPos))
521          {
522             idResult = FindCtxStatement(stmt.forStmt.check, line, charPos);
523             if(idResult) return idResult;
524          }
525          
526          if(stmt.forStmt.increment)
527          {
528             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
529             {
530                if(InsideIncl(&exp.loc, line, charPos))
531                {
532                   idResult = FindCtxExpression(exp, line, charPos);
533                   if(idResult) return idResult;
534                }
535             }
536          }
537
538          if(stmt.forStmt.stmt)
539             return FindCtxStatement(stmt.forStmt.stmt, line, charPos);
540          break;
541       }
542       case gotoStmt:
543          break;
544       case continueStmt:
545          break;
546       case breakStmt:
547          break;
548       case returnStmt:
549          if(stmt.expressions)
550          {
551             Expression exp;
552             
553             for(exp = stmt.expressions->first; exp; exp = exp.next)
554             {
555                if(InsideIncl(&exp.loc, line, charPos))
556                {
557                   idResult = FindCtxExpression(exp, line, charPos);
558                   if(idResult) return idResult;
559                }
560             }
561          }
562          break;
563       case fireWatchersStmt:
564       case stopWatchingStmt:
565       {
566          Identifier _watch;
567          if(stmt._watch.watcher && InsideIncl(&stmt._watch.watcher.loc, line, charPos))
568          {
569             idResult = FindCtxExpression(stmt._watch.watcher, line, charPos);
570             if(idResult) return idResult;
571          }
572          if(stmt._watch.object && InsideIncl(&stmt._watch.object.loc, line, charPos))
573          {
574             idResult = FindCtxExpression(stmt._watch.object, line, charPos);
575             if(idResult) return idResult;
576          }
577          if(stmt._watch.watches)
578          {
579             for(_watch = stmt._watch.watches->first; _watch; _watch = _watch.next)
580             {
581                if(InsideIncl(&_watch.loc, line, charPos))
582                {
583                   idResult = FindCtxIdentifier(_watch, line, charPos);
584                   if(idResult) return idResult;
585                }
586             }
587          }
588          break;
589       }
590       case watchStmt:
591       {
592          PropertyWatch _watch;
593          if(stmt._watch.watcher && InsideIncl(&stmt._watch.watcher.loc, line, charPos))
594          {
595             idResult = FindCtxExpression(stmt._watch.watcher, line, charPos);
596             if(idResult) return idResult;
597          }
598          if(stmt._watch.object && InsideIncl(&stmt._watch.object.loc, line, charPos))
599          {
600             idResult = FindCtxExpression(stmt._watch.object, line, charPos);
601             if(idResult) return idResult;
602          }
603          if(stmt._watch.watches)
604          {
605             for(_watch = stmt._watch.watches->first; _watch; _watch = _watch.next)
606             {
607                if(_watch.compound && InsideIncl(&_watch.compound.loc, line, charPos))
608                {
609                   idResult = FindCtxStatement(_watch.compound, line, charPos);
610                   if(idResult) return idResult;
611                }
612             }
613          }
614          break;
615       }
616    }
617    return null;
618 }
619
620 static Identifier FindCtxInitializer(Initializer initializer, int line, int charPos)
621 {
622    switch(initializer.type)
623    {
624       case listInitializer:
625       {
626          Initializer init;
627          Identifier idResult;
628          
629          for(init = initializer.list->first; init; init = init.next)
630          {
631             if(InsideIncl(&init.loc, line, charPos))
632             {
633                idResult = FindCtxInitializer(init, line, charPos);
634                if(idResult) return idResult;
635             }
636          }
637          break;
638       }
639       case expInitializer:
640          if(InsideIncl(&initializer.exp.loc, line, charPos))
641             return FindCtxExpression(initializer.exp, line, charPos);
642
643          {
644             ctxInsideExp = initializer.exp;
645             return (void *)-1;
646          }
647          break;
648    }
649    return null;
650 }
651
652 static Identifier FindCtxInitDeclarator(InitDeclarator decl, int line, int charPos)
653 {
654    if(decl.initializer && InsideIncl(&decl.initializer.loc, line, charPos))
655       return FindCtxInitializer(decl.initializer, line, charPos);
656    return null;
657 }
658
659 static Identifier FindCtxDeclaration(Declaration decl, int line, int charPos)
660 {
661    Identifier idResult;
662    
663    switch(decl.type)
664    {
665       case structDeclaration:
666       {
667          Specifier spec;
668          if(decl.specifiers)
669          {
670             for(spec = decl.specifiers->first; spec; spec = spec.next)
671             {
672                if(InsideIncl(&spec.loc, line, charPos))
673                {
674                   idResult = FindCtxSpecifier(spec, line, charPos);
675                   if(idResult) return idResult;
676                }
677             }
678          }
679          /*Declarator d;
680          if(decl.declarators && decl.declarators->first)
681          {
682             for(d = decl.declarators->first; d; d = d.next)
683             {
684                if(InsideIncl(&d.loc, line, charPos))
685                {
686                   if(d.type == DeclaratorStruct && d.declarator && d.declarator.type == DeclaratorIdentifier)
687                      return d.declarator.identifier;
688                }
689             }   
690          }
691          */
692          break;
693       }
694       case initDeclaration:
695       {
696          // Need to loop through specifiers to look for :: completion
697          if(decl.specifiers)
698          {
699             Specifier s;
700
701             for(s = decl.specifiers->first; s; s = s.next)
702             {
703                if(InsideIncl(&s.loc, line, charPos))
704                {
705                   idResult = FindCtxSpecifier(s, line, charPos);
706                   if(idResult) return idResult;
707                }
708             }
709          }
710
711          if(decl.declarators && decl.declarators->first)
712          {
713             InitDeclarator d;
714             for(d = decl.declarators->first; d; d = d.next)
715             {
716                if(InsideIncl(&d.loc, line, charPos))
717                {
718                   idResult = FindCtxInitDeclarator(d, line, charPos);
719                   if(idResult) return idResult;
720                }
721             }   
722          }
723          break;
724       }
725       case instDeclaration:
726          if(InsideIncl(&decl.inst.loc, line, charPos))
727             return FindCtxInstance(decl.inst, line, charPos);
728          break;
729    }
730    return null;
731 }
732
733 static Identifier FindCtxFunction(FunctionDefinition func, int line, int charPos)
734 {
735    if(func.body && Inside(&func.body.loc, line, charPos))
736    {
737       Identifier idResult;
738       
739       Identifier id = GetDeclId(func.declarator);
740       Symbol symbol = func.declarator.symbol;
741       Type type = symbol.type;
742       Class oldThisClass = GetThisClass();
743       Context oldTopContext = GetTopContext();
744
745       idResult = FindCtxStatement(func.body, line, charPos);
746       if(idResult)
747          return idResult;
748
749       SetThisClass(oldThisClass);
750       SetTopContext(oldTopContext);
751    }
752    return null;
753 }
754
755 static Identifier FindCtxMemberInit(MemberInit init, int line, int charPos)
756 {
757    Identifier idResult;
758    if(init.initializer && InsideIncl(&init.initializer.loc, line, charPos))
759    {
760       idResult = FindCtxInitializer(init.initializer, line, charPos);
761       if(idResult)
762       {
763          if(init.identifiers && init.identifiers->first)
764             isAfterEqual = true;
765          return idResult;
766       }
767    }
768    if(init.identifiers && init.identifiers->first && InsideIncl(&((Identifier)init.identifiers->first).loc, line, charPos))
769    {
770       idResult = FindCtxIdentifier(init.identifiers->first, line, charPos);
771       if(idResult)
772          return (void *)-2; //idResult;
773    }
774    if(init.initializer && Inside(&init.initializer.loc, line, charPos))
775    {
776       if(init.identifiers && init.identifiers->first)
777          isAfterEqual = true;
778
779       if(init.initializer.type == expInitializer)
780       {
781          ctxInsideExp = init.initializer.exp;
782          return (void *)-1;
783       }
784    }
785    return null;
786 }
787
788 static Identifier FindCtxInstance(Instantiation inst, int line, int charPos)
789 {
790    Identifier idResult = null;
791    Class oldThisClass = GetThisClass();
792    Symbol sym = inst._class ? FindClass(inst._class.name) : null;
793    bool insideSomething = false;
794    bool insideBrackets;
795    Method method = null;
796
797    Class curClass = null;
798    DataMember curMember = null;
799    DataMember dataMember = null;
800    DataMember subMemberStack[256];
801    int subMemberStackPos = 0;
802
803    if(sym)
804       SetThisClass(sym.registered);
805
806    insideBrackets = !(inst.insideLoc.start.line > line || (line == inst.insideLoc.start.line && inst.insideLoc.start.charPos > charPos));
807    if(insideBrackets)
808    {
809       // Start with first member
810       eClass_FindNextMember(GetThisClass(), &curClass, &curMember, subMemberStack, &subMemberStackPos);
811       dataMember = curMember;
812    }
813
814    if(inst.members)
815    {
816       MembersInit init;
817       MemberInit memberInit;
818       for(init = inst.members->first; init; init = init.next)
819       {         
820          if(init.loc.start.line > line || (line == init.loc.start.line && init.loc.start.charPos > charPos))
821             break;
822
823          if(init.type == dataMembersInit && init.dataMembers && insideBrackets && sym)
824          {
825             for(memberInit = init.dataMembers->first; memberInit; memberInit = memberInit.next)
826             {
827                isAfterEqual = false;
828
829                if(memberInit.identifiers && memberInit.identifiers->first)
830                {
831                   DataMember _subMemberStack[256];
832                   int _subMemberStackPos = 0;
833                   DataMember thisMember = eClass_FindDataMember(GetThisClass(), ((Identifier)memberInit.identifiers->first).string, GetPrivateModule(), _subMemberStack, &_subMemberStackPos);
834                   if(!thisMember)
835                   {
836                      // WARNING: Brackets needed until precomp fix
837                      thisMember = (DataMember)eClass_FindProperty(GetThisClass(), ((Identifier)memberInit.identifiers->first).string, GetPrivateModule());
838                   }
839                   if(thisMember)
840                   {
841                      method = null;
842                      dataMember = thisMember;
843                      if(thisMember.memberAccess == publicAccess)
844                      {
845                         curMember = thisMember;
846                         curClass = thisMember._class;
847                         memcpy(subMemberStack, _subMemberStack, sizeof(DataMember) * _subMemberStackPos);
848                         subMemberStackPos = _subMemberStackPos;
849                      }
850                   }
851                   else
852                      method = eClass_FindMethod(GetThisClass(), ((Identifier)memberInit.identifiers->first).string, GetPrivateModule());
853                }
854
855                if(!idResult && InsideIncl(&memberInit.realLoc, line, charPos))
856                   idResult = FindCtxMemberInit(memberInit, line, charPos);
857
858                if(InsideIncl(&memberInit.realLoc, line, charPos) || (memberInit.realLoc.end.line > line || (line == memberInit.realLoc.end.line && memberInit.realLoc.end.charPos > charPos)))
859                {
860                   if(memberInit.identifiers && memberInit.identifiers->first && InsideIncl(&memberInit.loc, line, charPos) && !dataMember)
861                      insideBrackets = false;
862                   break;
863                }
864                else if((!memberInit.identifiers || !memberInit.identifiers->first || dataMember) && (memberInit.next || !Inside(&init.loc, line, charPos)))
865                {
866                   method = null;
867                   eClass_FindNextMember(GetThisClass(), &curClass, &curMember, subMemberStack, &subMemberStackPos);
868                   dataMember = curMember;
869                }
870             }
871          }
872
873          if(InsideIncl(&init.loc, line, charPos))
874          {
875             if(Inside(&init.loc, line, charPos))
876                if(init.type == methodMembersInit)
877                   insideSomething = true;
878
879             if(init.type == methodMembersInit && Inside(&init.function.loc, line, charPos))
880             {
881                idResult = FindCtxClassFunction(init.function, line, charPos);
882                if(init.function == insideFunction)
883                   insideDef = (ClassDef)init; // Only using prev member of insideDef
884             }
885
886             if(Inside(&init.loc, line, charPos))
887                break;
888          }
889
890          if((init.loc.end.line > line || (line == init.loc.end.line && init.loc.end.charPos > charPos)))
891             break;
892       }
893    }
894    if((!idResult || idResult != (Identifier)-1) && sym && sym.registered && InsideIncl(&inst.insideLoc, line, charPos) && insideBrackets && !insideSomething)
895    {
896       if(dataMember && !method)
897       {
898          if(!dataMember.dataType)
899             dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
900          allocedDummyExp = true;
901          ctxInsideExp = MkExpDummy();
902          ctxInsideExp.destType = dataMember.dataType;
903          if(ctxInsideExp.destType) ctxInsideExp.destType.refCount++;
904       }
905    }
906
907    if((!idResult || idResult != (Identifier)-1) && sym && sym.registered && InsideIncl(&inst.insideLoc, line, charPos) && !insideSomething && insideBrackets)
908    {
909       if(method)
910       {
911          allocedDummyExp = true;
912          ctxInsideExp = MkExpDummy();
913          ctxInsideExp.destType = method.dataType;
914          if(ctxInsideExp.destType) ctxInsideExp.destType.refCount++;
915       }
916    }
917
918    if(sym && !insideSomething && InsideIncl(&inst.insideLoc, line, charPos))
919    {
920       if(!isAfterEqual && !insideClass && (!idResult || idResult == (void *)-2))
921          insideClass = sym.registered;
922
923       if(isAfterEqual && currentClass)
924          SetThisClass(currentClass);
925
926       return idResult ? idResult : (void *) -1;
927    }
928    if(idResult)
929       return idResult;
930
931    SetThisClass(oldThisClass);
932
933    return null;
934 }
935
936 static Identifier FindCtxClassFunction(ClassFunction func, int line, int charPos)
937 {
938    if(func.body && Inside(&func.body.loc, line, charPos))
939    {
940       Identifier idResult;
941       
942       Identifier id = GetDeclId(func.declarator);
943       Symbol symbol = func.declarator ? func.declarator.symbol : null;
944       Type type = symbol ? symbol.type : null;
945       Class oldThisClass = GetThisClass();
946       Context oldTopContext = GetTopContext();
947       SetThisClass((type && type.thisClass) ? type.thisClass.registered : currentClass);
948
949       if(func.body)
950       {
951          idResult = FindCtxStatement(func.body, line, charPos);
952          if(idResult)
953             return idResult;
954       }
955
956       SetThisClass(oldThisClass);
957       SetTopContext(oldTopContext);
958    }
959    else if(!func.body && GetFuncDecl(func.declarator))
960    {
961       if(!GetThisClass())
962          SetThisClass(currentClass);
963       else
964       {
965          insideInstance = true;
966          // Is this insideClass ever used?
967          insideClass = GetThisClass(); //currentClass;
968       }
969       insideFunction = func;
970       return (void *)-1;
971    }
972    else if(!func.body && GetDeclId(func.declarator))
973    {
974       if(!GetThisClass())
975          SetThisClass(currentClass);
976       else
977       {
978          insideInstance = true;
979
980          // Has to be GetThisClass() to work...
981          insideClass = GetThisClass();//currentClass;
982       }
983       return (void *)-1;
984    }
985    else
986    {
987       // TESTING THIS FOR HANDLING: bool ^bool NotifyClicked
988       insideInstance = true;
989
990       // Has to be GetThisClass() to work...
991       insideClass = GetThisClass();//currentClass;
992    }
993    return null;
994 }
995
996 static Identifier FindCtxProperty(PropertyDef def, int line, int charPos)
997 {
998    Identifier result;
999    if(def.getStmt && Inside(&def.getStmt.loc, line, charPos))
1000    {
1001       Class oldThisClass = GetThisClass();
1002       Context oldTopContext = GetTopContext();
1003       SetThisClass(currentClass);
1004       result = FindCtxStatement(def.getStmt, line, charPos);
1005       if(result) return result;
1006       SetThisClass(oldThisClass);
1007    }
1008    if(def.setStmt && Inside(&def.setStmt.loc, line, charPos))
1009    {
1010       Class oldThisClass = GetThisClass();
1011       Context oldTopContext = GetTopContext();
1012       SetThisClass(currentClass);
1013       result = FindCtxStatement(def.setStmt, line, charPos);
1014       if(result) return result;
1015       SetThisClass(oldThisClass);
1016    }
1017    return null;
1018 }
1019
1020 static Identifier FindCtxClassDef(ClassDef def, int line, int charPos)
1021 {
1022    Identifier idResult;
1023    switch(def.type)
1024    {
1025       case declarationClassDef:
1026          if(InsideEndIncl(&def.decl.loc, line, charPos))
1027          {
1028             idResult = FindCtxDeclaration(def.decl, line, charPos);
1029             if(idResult)
1030                return idResult;
1031          }
1032          break;
1033       case defaultPropertiesClassDef:
1034       {
1035          MemberInit init;
1036          for(init = def.defProperties->first; init; init = init.next)
1037          {
1038             if(InsideIncl(&init.realLoc, line, charPos))
1039             {
1040                Class oldThisClass = GetThisClass();
1041                Context oldTopContext = GetTopContext();
1042                SetThisClass(currentClass);
1043                idResult = FindCtxMemberInit(init, line, charPos);
1044                if(idResult)
1045                   return idResult;
1046                SetThisClass(oldThisClass);
1047             }
1048          }
1049          break;
1050       }
1051       case functionClassDef:
1052          if(Inside(&def.function.loc, line, charPos))
1053          {
1054             idResult = FindCtxClassFunction(def.function, line, charPos);
1055             if(def.function == insideFunction)
1056                insideDef = def;
1057
1058             if(idResult)
1059                return idResult;
1060          }
1061          break;
1062       case propertyClassDef:
1063          if(def.propertyDef)
1064          {
1065             if(Inside(&def.propertyDef.loc, line, charPos))
1066             {
1067                idResult = FindCtxProperty(def.propertyDef, line, charPos);
1068                if(idResult)
1069                   return idResult;
1070             }
1071          }
1072          break;
1073       case propertyWatchClassDef:
1074          if(def.propertyWatch && def.propertyWatch.compound && Inside(&def.propertyWatch.compound.loc, line, charPos))
1075          {
1076             Class oldThisClass = GetThisClass();
1077             Context oldTopContext = GetTopContext();
1078             SetThisClass(currentClass);
1079             idResult = FindCtxStatement(def.propertyWatch.compound, line, charPos);
1080             if(idResult) return idResult;
1081             SetThisClass(oldThisClass);
1082          }
1083          break;
1084    }
1085    return null;
1086 }
1087
1088 static Identifier FindCtxClass(ClassDefinition _class, int line, int charPos)
1089 {
1090    Identifier idResult;
1091    bool insideSomething = false;
1092    if(_class.definitions)
1093    {
1094       ClassDef def;
1095       for(def = _class.definitions->first; def; def = def.next)
1096       {
1097          if(def.type == defaultPropertiesClassDef ? InsideIncl(&def.loc, line, charPos) : Inside(&def.loc, line, charPos) )
1098          {
1099             if(def.type != defaultPropertiesClassDef)
1100                insideSomething = true;
1101
1102             idResult = FindCtxClassDef(def, line, charPos);
1103             if(idResult)
1104                return idResult;
1105             else
1106                insideSomething = false;
1107          }
1108       }
1109    }
1110    if(!insideSomething && line > _class.blockStart.start.line || (line == _class.blockStart.start.line && charPos >= _class.blockStart.start.charPos) )
1111    {
1112       insideClass = _class.symbol.registered;
1113       return (void *)-1;
1114    }
1115    return null;
1116 }
1117
1118 Identifier FindCtxTree(OldList ast, int line, int charPos)
1119 {
1120    Identifier idResult;
1121    External external;
1122
1123    if(allocedDummyExp)
1124    {
1125       FreeExpression(ctxInsideExp);
1126       allocedDummyExp = false;
1127    }
1128
1129    insideClass = null;
1130    ctxInsideExp = null;
1131    SetThisClass(null);
1132    insideFunction = null;
1133    insideInstance = false;
1134    isAfterEqual = false;
1135
1136    if(ast != null)
1137    {
1138       for(external = ast.first; external; external = external.next)
1139       {
1140          switch(external.type)
1141          {
1142             case functionExternal: 
1143                if(Inside(&external.loc, line, charPos))
1144                {
1145                   idResult = FindCtxFunction(external.function, line, charPos);
1146                   if(idResult)
1147                      return (idResult == (void *)-1 || idResult == (void *)-2) ? null : idResult;
1148                }
1149                break;
1150             case declarationExternal: 
1151                if(InsideIncl(&external.loc, line, charPos))
1152                {
1153                   idResult = FindCtxDeclaration(external.declaration, line, charPos);
1154                   if(idResult)
1155                      return (idResult == (void *)-1 || idResult == (void *)-2) ? null : idResult;
1156                }
1157                break;
1158             case classExternal: 
1159                if(Inside(&external._class.loc, line, charPos))
1160                {
1161                   currentClass = external._class.symbol.registered;
1162                   idResult = FindCtxClass(external._class, line, charPos);
1163                   if(idResult)
1164                      return (idResult == (void *)-1 || idResult == (void *)-2) ? null : idResult;
1165                   currentClass = null;
1166                }
1167                break;
1168          }
1169       }
1170    }
1171    return null;
1172 }
1173
1174 void FindCtx_Terminate()
1175 {
1176    if(allocedDummyExp)
1177    {
1178       FreeExpression(ctxInsideExp);
1179       allocedDummyExp = false;
1180    }
1181 }