Pārlūkot izejas kodu

Show comptime emits as embedded sourceviews

Brian Fiete 3 gadi atpakaļ
vecāks
revīzija
4d1e14a1c3
65 mainītis faili ar 3229 papildinājumiem un 616 dzēšanām
  1. 22 13
      BeefLibs/Beefy2D/src/theme/dark/DarkComboBox.bf
  2. 41 5
      BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf
  3. 2 2
      BeefLibs/Beefy2D/src/theme/dark/DarkScrollbar.bf
  4. 10 8
      BeefLibs/Beefy2D/src/widgets/EditWidget.bf
  5. 10 2
      BeefLibs/Beefy2D/src/widgets/ScrollableWidget.bf
  6. 14 3
      BeefLibs/Beefy2D/src/widgets/Scrollbar.bf
  7. 23 0
      BeefLibs/Beefy2D/src/widgets/Widget.bf
  8. 4 0
      BeefySysLib/BeefySysLib.vcxproj
  9. 15 0
      BeefySysLib/BeefySysLib.vcxproj.filters
  10. 4 0
      BeefySysLib/BeefySysLib_static.vcxproj
  11. 15 0
      BeefySysLib/BeefySysLib_static.vcxproj.filters
  12. 4 2
      BeefySysLib/Common.cpp
  13. 110 0
      BeefySysLib/util/ZipFile.cpp
  14. 30 0
      BeefySysLib/util/ZipFile.h
  15. 11 0
      IDE/src/BuildContext.bf
  16. 43 8
      IDE/src/Compiler/BfCompiler.bf
  17. 67 23
      IDE/src/Compiler/BfParser.bf
  18. 17 0
      IDE/src/Compiler/BfResolvePassData.bf
  19. 29 1
      IDE/src/Debugger/DebugManager.bf
  20. 199 59
      IDE/src/IDEApp.bf
  21. 42 0
      IDE/src/IDEUtils.bf
  22. 1 0
      IDE/src/TestManager.bf
  23. 7 0
      IDE/src/Workspace.bf
  24. 2 1
      IDE/src/ui/ErrorsPanel.bf
  25. 5 1
      IDE/src/ui/OutputWidget.bf
  26. 0 4
      IDE/src/ui/QuickFind.bf
  27. 43 13
      IDE/src/ui/RenameSymbolDialog.bf
  28. 651 30
      IDE/src/ui/SourceEditWidgetContent.bf
  29. 488 118
      IDE/src/ui/SourceViewPanel.bf
  30. 2 0
      IDE/src/ui/StatusBar.bf
  31. 81 5
      IDEHelper/COFF.cpp
  32. 4 0
      IDEHelper/COFF.h
  33. 39 25
      IDEHelper/Compiler/BfAutoComplete.cpp
  34. 1 0
      IDEHelper/Compiler/BfAutoComplete.h
  35. 499 118
      IDEHelper/Compiler/BfCompiler.cpp
  36. 4 0
      IDEHelper/Compiler/BfCompiler.h
  37. 20 12
      IDEHelper/Compiler/BfContext.cpp
  38. 2 0
      IDEHelper/Compiler/BfContext.h
  39. 20 9
      IDEHelper/Compiler/BfDefBuilder.cpp
  40. 10 6
      IDEHelper/Compiler/BfExprEvaluator.cpp
  41. 45 32
      IDEHelper/Compiler/BfModule.cpp
  42. 3 2
      IDEHelper/Compiler/BfModule.h
  43. 212 72
      IDEHelper/Compiler/BfModuleTypeUtils.cpp
  44. 58 3
      IDEHelper/Compiler/BfParser.cpp
  45. 11 1
      IDEHelper/Compiler/BfParser.h
  46. 55 2
      IDEHelper/Compiler/BfReducer.cpp
  47. 34 2
      IDEHelper/Compiler/BfResolvePass.cpp
  48. 27 3
      IDEHelper/Compiler/BfResolvePass.h
  49. 2 7
      IDEHelper/Compiler/BfResolvedTypeUtils.h
  50. 44 2
      IDEHelper/Compiler/BfSystem.cpp
  51. 6 5
      IDEHelper/Compiler/BfSystem.h
  52. 21 0
      IDEHelper/Compiler/BfUtil.cpp
  53. 2 0
      IDEHelper/Compiler/BfUtil.h
  54. 6 1
      IDEHelper/Compiler/CeDebugger.cpp
  55. 1 0
      IDEHelper/Compiler/CeDebugger.h
  56. 31 0
      IDEHelper/Compiler/CeMachine.h
  57. 4 0
      IDEHelper/DbgModule.cpp
  58. 2 0
      IDEHelper/DbgModule.h
  59. 13 0
      IDEHelper/DebugManager.cpp
  60. 10 4
      IDEHelper/DebugTarget.cpp
  61. 5 7
      IDEHelper/DebugTarget.h
  62. 2 1
      IDEHelper/Debugger.h
  63. 1 1
      IDEHelper/MiniDumpDebugger.cpp
  64. 41 2
      IDEHelper/WinDebugger.cpp
  65. 2 1
      IDEHelper/WinDebugger.h

+ 22 - 13
BeefLibs/Beefy2D/src/theme/dark/DarkComboBox.bf

@@ -59,7 +59,7 @@ namespace Beefy.theme.dark
         public uint32 mBkgColor;
         public uint32 mBkgColor;
         public DarkEditWidget mEditWidget;
         public DarkEditWidget mEditWidget;
 		bool mAllowReverseDropdown; // Allow popdown to "popup" if there isn't enough space
 		bool mAllowReverseDropdown; // Allow popdown to "popup" if there isn't enough space
-		public Widget mPrevFocusWidget;
+		public SafeWidgetRef mPrevFocusWidget ~ delete _;
 		public bool mFocusDropdown = true;
 		public bool mFocusDropdown = true;
 		
 		
 		virtual public StringView Label 
 		virtual public StringView Label 
@@ -170,12 +170,16 @@ namespace Beefy.theme.dark
 
 
         public virtual void MenuClosed()
         public virtual void MenuClosed()
         {
         {
-			if (mPrevFocusWidget != null)
-			{
-				mPrevFocusWidget.SetFocus();
-			}
+			mPrevFocusWidget?.Value?.SetFocus();
         }
         }
 
 
+		protected override void RemovedFromWindow()
+		{
+			base.RemovedFromWindow();
+
+			mCurMenuWidget?.mMenu.mOnMenuClosed.Dispose();
+		}
+
         void HandleClose(Menu menu, Menu selectedItem)
         void HandleClose(Menu menu, Menu selectedItem)
         {
         {
             mCurMenuWidget = null;
             mCurMenuWidget = null;
@@ -186,7 +190,8 @@ namespace Beefy.theme.dark
 
 
         public virtual MenuWidget ShowDropdown()
         public virtual MenuWidget ShowDropdown()
         {
         {
-			mPrevFocusWidget = mWidgetWindow.mFocusWidget;
+			if ((mPrevFocusWidget == null) && (mWidgetWindow.mFocusWidget != null))
+				mPrevFocusWidget = new .(mWidgetWindow.mFocusWidget);
 
 
             float popupXOfs = GS!(5);
             float popupXOfs = GS!(5);
             float popupYOfs = GS!(-2);
             float popupYOfs = GS!(-2);
@@ -302,6 +307,16 @@ namespace Beefy.theme.dark
 			return true;
 			return true;
 		}	
 		}	
 
 
+		public void SelectFromLabel()
+		{
+			var label = Label;
+			for (let itemWidget in mCurMenuWidget.mItemWidgets)
+			{
+				if (itemWidget.mMenuItem.mLabel == label)
+					mCurMenuWidget.SetSelection(@itemWidget.Index);
+			}
+		}
+
 		void EditKeyDownHandler(KeyDownEvent evt)
 		void EditKeyDownHandler(KeyDownEvent evt)
 		{
 		{
 			if (!WantsKeyHandling())
 			if (!WantsKeyHandling())
@@ -318,13 +333,7 @@ namespace Beefy.theme.dark
 			if ((evt.mKeyCode == .Down) && (mCurMenuWidget == null))
 			if ((evt.mKeyCode == .Down) && (mCurMenuWidget == null))
 			{
 			{
 				ShowDropdown();
 				ShowDropdown();
-
-				var label = Label;
-				for (let itemWidget in mCurMenuWidget.mItemWidgets)
-				{
-					if (itemWidget.mMenuItem.mLabel == label)
-						mCurMenuWidget.SetSelection(@itemWidget.Index);
-				}
+				SelectFromLabel();
 			}
 			}
 
 
 			if ((evt.mKeyCode == .Escape) && (mCurMenuWidget != null) && (mEditWidget != null))
 			if ((evt.mKeyCode == .Escape) && (mCurMenuWidget != null) && (mEditWidget != null))

+ 41 - 5
BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf

@@ -21,6 +21,7 @@ namespace Beefy.theme.dark
 			}
 			}
 
 
 			public Kind mKind;
 			public Kind mKind;
+			public int32 mLine = -1;
 
 
 			public ~this()
 			public ~this()
 			{
 			{
@@ -61,7 +62,8 @@ namespace Beefy.theme.dark
 		public uint32 mViewWhiteSpaceColor;
 		public uint32 mViewWhiteSpaceColor;
 		public bool mScrollToStartOnLostFocus;
 		public bool mScrollToStartOnLostFocus;
 		public bool mHiliteCurrentLine;
 		public bool mHiliteCurrentLine;
-		public Dictionary<int, Embed> mEmbeds = new .() ~ DeleteDictionaryAndValues!(_);
+		public Dictionary<int32, Embed> mEmbeds = new .() ~ DeleteDictionaryAndValues!(_);
+		public Range? mLineRange;
 
 
 		protected static uint32[] sDefaultColors = new uint32[] ( Color.White ) ~ delete _;
 		protected static uint32[] sDefaultColors = new uint32[] ( Color.White ) ~ delete _;
 
 
@@ -498,7 +500,7 @@ namespace Beefy.theme.dark
 				((embed.mKind == .HideLine) && (!hideLine)))
 				((embed.mKind == .HideLine) && (!hideLine)))
 				selStartX += GS!(4);
 				selStartX += GS!(4);
 
 
-			Rect rect = .(selStartX, mLineCoords[lineIdx] - GS!(2), embed.GetWidth(hideLine), mFont.GetLineSpacing() + GS!(4));
+			Rect rect = .(selStartX, mLineCoords[lineIdx] - GS!(1), embed.GetWidth(hideLine), mFont.GetLineSpacing() + GS!(3));
 			if (rect.mY < 0)
 			if (rect.mY < 0)
 				rect.mY = 0;
 				rect.mY = 0;
 			return rect;
 			return rect;
@@ -508,7 +510,6 @@ namespace Beefy.theme.dark
         {            
         {            
             base.Draw(g);
             base.Draw(g);
 
 
-			
 #unwarn
 #unwarn
             int lineCount = GetLineCount();
             int lineCount = GetLineCount();
             float lineSpacing = mFont.GetLineSpacing();
             float lineSpacing = mFont.GetLineSpacing();
@@ -588,6 +589,12 @@ namespace Beefy.theme.dark
 			    drewCursor = true;
 			    drewCursor = true;
 			}
 			}
 
 
+			if (mLineRange != null)
+			{
+				firstLine = Math.Max(firstLine, mLineRange.Value.Start);
+				lastLine = Math.Min(lastLine, mLineRange.Value.End - 1);
+			}
+
 			String sectionText = scope String(256);
 			String sectionText = scope String(256);
             for (int lineIdx = firstLine; lineIdx <= lastLine; lineIdx++)
             for (int lineIdx = firstLine; lineIdx <= lastLine; lineIdx++)
             {
             {
@@ -604,7 +611,7 @@ namespace Beefy.theme.dark
 					continue;
 					continue;
 
 
 				DarkEditWidgetContent.Embed embed = null;
 				DarkEditWidgetContent.Embed embed = null;
-				if (mEmbeds.GetValue(lineIdx) case .Ok(out embed))
+				if (mEmbeds.GetValue((.)lineIdx) case .Ok(out embed))
 				{
 				{
 					if ((embed.mKind == .HideLine) &&
 					if ((embed.mKind == .HideLine) &&
 						((!IsInCollapseGroup(lineIdx, CursorLine)) || (!mEditWidget.mHasFocus)))
 						((!IsInCollapseGroup(lineIdx, CursorLine)) || (!mEditWidget.mHasFocus)))
@@ -813,6 +820,20 @@ namespace Beefy.theme.dark
 			return line;
 			return line;
 		}
 		}
 
 
+		public override void PhysCursorMoved(CursorMoveKind moveKind)
+		{
+			base.PhysCursorMoved(moveKind);
+
+			if (mLineRange != null)
+			{
+				var lineAndColumn = CursorLineAndColumn;
+				if (lineAndColumn.mLine < mLineRange.Value.Start)
+					CursorLineAndColumn = .(mLineRange.Value.Start, lineAndColumn.mColumn);
+				else if (lineAndColumn.mLine >= mLineRange.Value.End)
+					CursorLineAndColumn = .(mLineRange.Value.End - 1, lineAndColumn.mColumn);
+			}
+		}
+
         public override bool GetLineCharAtCoord(float x, float y, out int line, out int lineChar, out float overflowX)
         public override bool GetLineCharAtCoord(float x, float y, out int line, out int lineChar, out float overflowX)
         {
         {
 			line = GetLineAt(y);
 			line = GetLineAt(y);
@@ -1145,7 +1166,7 @@ namespace Beefy.theme.dark
 			
 			
 			bool isOverEmbed = false;
 			bool isOverEmbed = false;
 
 
-			if (mEmbeds.GetValue(line) case .Ok(let embed))
+			if (mEmbeds.GetValue((.)line) case .Ok(let embed))
 			{
 			{
 				Rect embedRect = GetEmbedRect(line, embed);
 				Rect embedRect = GetEmbedRect(line, embed);
 				if (embedRect.Contains(x, y))
 				if (embedRect.Contains(x, y))
@@ -1223,6 +1244,21 @@ namespace Beefy.theme.dark
                 mVertScrollbar.mScrollIncrement = scrollIncrement;
                 mVertScrollbar.mScrollIncrement = scrollIncrement;
         }
         }
 
 
+		public override void UpdateScrollbarData()
+		{
+			base.UpdateScrollbarData();
+
+			var ewc = mEditWidgetContent as DarkEditWidgetContent;
+			if (ewc.mLineRange != null)
+			{
+				ewc.GetTextData();
+				mVertScrollbar.mContentStart = ewc.mLineCoords[Math.Min(ewc.mLineRange.Value.Start, ewc.mLineCoords.Count - 1)];
+				mVertScrollbar.mContentSize = ewc.mLineCoords[Math.Min(ewc.mLineRange.Value.End, ewc.mLineCoords.Count - 1)] - mVertScrollbar.mContentStart;
+				ScrollPositionChanged();
+				mVertScrollbar.UpdateData();
+			}
+		}
+
         public override void Draw(Graphics g)
         public override void Draw(Graphics g)
         {
         {
             base.Draw(g);
             base.Draw(g);

+ 2 - 2
BeefLibs/Beefy2D/src/theme/dark/DarkScrollbar.bf

@@ -125,14 +125,14 @@ namespace Beefy.theme.dark
                 float trackSize = sizeLeft - mThumb.mWidth;
                 float trackSize = sizeLeft - mThumb.mWidth;
                 float trackPct = (x - btnMargin) / trackSize;
                 float trackPct = (x - btnMargin) / trackSize;
                 double contentPos = (mContentSize - mPageSize) * trackPct;
                 double contentPos = (mContentSize - mPageSize) * trackPct;
-                return contentPos;
+                return contentPos + mContentStart;
             }
             }
             else
             else
             {
             {
                 float trackSize = sizeLeft - mThumb.mHeight;
                 float trackSize = sizeLeft - mThumb.mHeight;
                 float trackPct = (y - btnMargin) / trackSize;
                 float trackPct = (y - btnMargin) / trackSize;
                 double contentPos = (mContentSize - mPageSize) * trackPct;
                 double contentPos = (mContentSize - mPageSize) * trackPct;
-                return contentPos;
+                return contentPos + mContentStart;
             }
             }
         }
         }
 
 

+ 10 - 8
BeefLibs/Beefy2D/src/widgets/EditWidget.bf

@@ -2868,11 +2868,11 @@ namespace Beefy.widgets
                 ExtractString(lineStart, lineEnd - lineStart, outStr); // Full line
                 ExtractString(lineStart, lineEnd - lineStart, outStr); // Full line
         }
         }
 
 
-        public int GetTextIdx(int line, int charIdx)
+        public int GetTextIdx(int line, int lineChar)
         {
         {
             GetTextData();
             GetTextData();
             int useLine = Math.Min(line, mData.mLineStarts.Count - 1);
             int useLine = Math.Min(line, mData.mLineStarts.Count - 1);
-            return mData.mLineStarts[useLine] + charIdx;
+            return mData.mLineStarts[useLine] + lineChar;
         }
         }
 
 
         public int GetCharIdIdx(int32 findCharId)
         public int GetCharIdIdx(int32 findCharId)
@@ -3139,13 +3139,15 @@ namespace Beefy.widgets
 
 
             float lineHeight = GetLineHeight(line);
             float lineHeight = GetLineHeight(line);
 
 
+			double yOfs = (mEditWidget.mVertScrollbar?.mContentStart).GetValueOrDefault();
+
             if (mIsMultiline)
             if (mIsMultiline)
             {
             {
-                if (aY < mEditWidget.mVertPos.mDest + mTextInsets.mTop)
+                if (aY < mEditWidget.mVertPos.mDest + mTextInsets.mTop + yOfs)
                 {
                 {
                     if (scrollView)
                     if (scrollView)
                     {
                     {
-                        float scrollPos = aY - mTextInsets.mTop;
+                        double scrollPos = aY - mTextInsets.mTop - yOfs;
                         if (centerView)
                         if (centerView)
                         {                            
                         {                            
                             scrollPos -= mEditWidget.mScrollContentContainer.mHeight * 0.50f;
                             scrollPos -= mEditWidget.mScrollContentContainer.mHeight * 0.50f;
@@ -3158,7 +3160,7 @@ namespace Beefy.widgets
                         int aLine;
                         int aLine;
                         int aCharIdx;
                         int aCharIdx;
                         float overflowX;
                         float overflowX;
-                        GetLineCharAtCoord(aX, (float)mEditWidget.mVertPos.mDest + mTextInsets.mTop, out aLine, out aCharIdx, out overflowX);
+                        GetLineCharAtCoord(aX, (float)(mEditWidget.mVertPos.mDest + mTextInsets.mTop + yOfs), out aLine, out aCharIdx, out overflowX);
 
 
                         float newX;
                         float newX;
                         float newY;
                         float newY;
@@ -3169,11 +3171,11 @@ namespace Beefy.widgets
                         MoveCursorTo(aLine, aCharIdx);
                         MoveCursorTo(aLine, aCharIdx);
                     }
                     }
                 }
                 }
-                else if (aY + lineHeight + mShowLineBottomPadding > mEditWidget.mVertPos.mDest + mEditWidget.mScrollContentContainer.mHeight)
+                else if (aY + lineHeight + mShowLineBottomPadding > mEditWidget.mVertPos.mDest + mEditWidget.mScrollContentContainer.mHeight + yOfs)
                 {
                 {
                     if (scrollView)
                     if (scrollView)
                     {
                     {
-                        float scrollPos = aY + lineHeight + mShowLineBottomPadding - mEditWidget.mScrollContentContainer.mHeight;
+                        double scrollPos = aY + lineHeight + mShowLineBottomPadding - mEditWidget.mScrollContentContainer.mHeight - yOfs;
                         if (centerView)
                         if (centerView)
                         {
                         {
                             // Show slightly more content on bottom
                             // Show slightly more content on bottom
@@ -3183,7 +3185,7 @@ namespace Beefy.widgets
                         mEditWidget.VertScrollTo(scrollPos);
                         mEditWidget.VertScrollTo(scrollPos);
                     }
                     }
                     else
                     else
-                        MoveCursorToCoord(aX, (float)mEditWidget.mVertPos.mDest + mEditWidget.mScrollContentContainer.mHeight - lineHeight);
+                        MoveCursorToCoord(aX, (float)(mEditWidget.mVertPos.mDest + mEditWidget.mScrollContentContainer.mHeight - lineHeight + yOfs));
                 }
                 }
             }
             }
 
 

+ 10 - 2
BeefLibs/Beefy2D/src/widgets/ScrollableWidget.bf

@@ -121,7 +121,11 @@ namespace Beefy.widgets
 
 
         public bool VertScrollTo(double vertPos, bool immediate = false)
         public bool VertScrollTo(double vertPos, bool immediate = false)
         {
         {
-            double aVertPos = Math.Max(0, Math.Min(vertPos, mScrollContent.mHeight - mScrollContentContainer.mHeight));
+			float contentHeight = mScrollContent.mHeight;
+			if (mVertScrollbar != null)
+				contentHeight = (float)mVertScrollbar.mContentSize;
+
+            double aVertPos = Math.Max(0, Math.Min(vertPos, contentHeight - mScrollContentContainer.mHeight));
             if (aVertPos == mVertPos.mDest)
             if (aVertPos == mVertPos.mDest)
                 return false;
                 return false;
 
 
@@ -200,6 +204,7 @@ namespace Beefy.widgets
                 mHorzScrollbar.UpdateData();
                 mHorzScrollbar.UpdateData();
 				MarkDirty();
 				MarkDirty();
             }
             }
+
             if ((mVertScrollbar != null) && (mVertScrollbar.mContentPos != mVertPos.v))
             if ((mVertScrollbar != null) && (mVertScrollbar.mContentPos != mVertPos.v))
             {
             {
                 mVertScrollbar.mContentPos = mVertPos.v;
                 mVertScrollbar.mContentPos = mVertPos.v;
@@ -208,7 +213,9 @@ namespace Beefy.widgets
             }
             }
             if (mScrollContent != null)
             if (mScrollContent != null)
             {
             {
-                mScrollContent.Resize((int32)(-mHorzPos.v), (int32)(-mVertPos.v),
+                mScrollContent.Resize(
+					(int32)(-mHorzPos.v - (mHorzScrollbar?.mContentStart).GetValueOrDefault()),
+					(int32)(-mVertPos.v - (mVertScrollbar?.mContentStart).GetValueOrDefault()),
                     mScrollContent.mWidth, mScrollContent.mHeight);
                     mScrollContent.mWidth, mScrollContent.mHeight);
             }
             }
 
 
@@ -253,6 +260,7 @@ namespace Beefy.widgets
         public override void MouseWheel(float x, float y, float deltaX, float deltaY)
         public override void MouseWheel(float x, float y, float deltaX, float deltaY)
         {
         {
             base.MouseWheel(x, y, deltaX, deltaY);
             base.MouseWheel(x, y, deltaX, deltaY);
+
 			if (deltaY != 0)
 			if (deltaY != 0)
 			{
 			{
 	            if (mVertScrollbar != null)
 	            if (mVertScrollbar != null)

+ 14 - 3
BeefLibs/Beefy2D/src/widgets/Scrollbar.bf

@@ -100,6 +100,7 @@ namespace Beefy.widgets
             Vert
             Vert
         }
         }
 
 
+		public double mContentStart;
         public double mContentSize;
         public double mContentSize;
         public double mPageSize;
         public double mPageSize;
         public double mContentPos;        
         public double mContentPos;        
@@ -120,6 +121,7 @@ namespace Beefy.widgets
         public float mScrollIncrement;
         public float mScrollIncrement;
         public bool mAlignItems;
         public bool mAlignItems;
 		public bool mDoAutoClamp = true;
 		public bool mDoAutoClamp = true;
+		public bool mAllowMouseWheel = true;
 
 
         public Event<ScrollEventHandler> mOnScrollEvent ~ _.Dispose();
         public Event<ScrollEventHandler> mOnScrollEvent ~ _.Dispose();
 
 
@@ -147,6 +149,9 @@ namespace Beefy.widgets
 
 
         public virtual void ScrollTo(double pos)
         public virtual void ScrollTo(double pos)
         {
         {
+			var pos;
+			pos -= mContentStart;
+
 			MarkDirty();
 			MarkDirty();
             double oldPos = mContentPos;
             double oldPos = mContentPos;
 
 
@@ -161,8 +166,8 @@ namespace Beefy.widgets
             if ((mOnScrollEvent.HasListeners) && (oldPos != mContentPos))
             if ((mOnScrollEvent.HasListeners) && (oldPos != mContentPos))
             {
             {
                 ScrollEvent scrollEvent = scope ScrollEvent();
                 ScrollEvent scrollEvent = scope ScrollEvent();
-                scrollEvent.mOldPos = oldPos;
-                scrollEvent.mNewPos = mContentPos;
+                scrollEvent.mOldPos = oldPos + mContentStart;
+                scrollEvent.mNewPos = mContentPos + mContentStart;
                 mOnScrollEvent(scrollEvent);
                 mOnScrollEvent(scrollEvent);
             }
             }
         }
         }
@@ -176,7 +181,7 @@ namespace Beefy.widgets
 
 
         public virtual void Scroll(double amt)
         public virtual void Scroll(double amt)
         {
         {
-            ScrollTo(mContentPos + amt);            
+            ScrollTo(mContentPos + amt + mContentStart);
         }
         }
 
 
         public virtual double GetContentPosAt(float x, float y)
         public virtual double GetContentPosAt(float x, float y)
@@ -226,6 +231,12 @@ namespace Beefy.widgets
 
 
         public override void MouseWheel(float x, float y, float deltaX, float deltaY)
         public override void MouseWheel(float x, float y, float deltaX, float deltaY)
         {
         {
+			if (!mAllowMouseWheel)
+			{
+				base.MouseWheel(x, y, deltaX, deltaY);
+				return;
+			}
+
 			float delta = (mOrientation == .Horz) ? deltaX : deltaY;
 			float delta = (mOrientation == .Horz) ? deltaX : deltaY;
             Scroll(GetScrollIncrement() * -delta);
             Scroll(GetScrollIncrement() * -delta);
         }
         }

+ 23 - 0
BeefLibs/Beefy2D/src/widgets/Widget.bf

@@ -834,4 +834,27 @@ namespace Beefy.widgets
 			return true;
 			return true;
 		}
 		}
     }
     }
+
+	class SafeWidgetRef
+	{
+		Widget mWidget;
+
+		public this(Widget widget)
+		{
+			mWidget = widget;
+			mWidget.mOnDeleted.Add(new => OnDelete);
+		}
+
+		public ~this()
+		{
+			mWidget?.mOnDeleted.Remove(scope => OnDelete, true);
+		}
+
+		public Widget Value => mWidget;
+
+		void OnDelete(Widget widget)
+		{
+			mWidget = null;
+		}
+	}
 }
 }

+ 4 - 0
BeefySysLib/BeefySysLib.vcxproj

@@ -1624,6 +1624,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'">TurnOffAllWarnings</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'">TurnOffAllWarnings</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">TurnOffAllWarnings</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">TurnOffAllWarnings</WarningLevel>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="third_party\miniz\miniz.c" />
     <ClCompile Include="third_party\png\png.c">
     <ClCompile Include="third_party\png\png.c">
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">Level1</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">Level1</WarningLevel>
@@ -1950,6 +1951,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
     <ClCompile Include="util\UTF8.cpp" />
     <ClCompile Include="util\UTF8.cpp" />
     <ClCompile Include="util\Vector.cpp" />
     <ClCompile Include="util\Vector.cpp" />
     <ClCompile Include="util\WorkThread.cpp" />
     <ClCompile Include="util\WorkThread.cpp" />
+    <ClCompile Include="util\ZipFile.cpp" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="BFApp.h" />
     <ClInclude Include="BFApp.h" />
@@ -2133,6 +2135,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
     <ClInclude Include="third_party\jpeg\transupp.h" />
     <ClInclude Include="third_party\jpeg\transupp.h" />
     <ClInclude Include="third_party\libffi\i686-pc-cygwin\include\ffi.h" />
     <ClInclude Include="third_party\libffi\i686-pc-cygwin\include\ffi.h" />
     <ClInclude Include="third_party\libffi\i686-pc-cygwin\include\ffitarget.h" />
     <ClInclude Include="third_party\libffi\i686-pc-cygwin\include\ffitarget.h" />
+    <ClInclude Include="third_party\miniz\miniz.h" />
     <ClInclude Include="third_party\png\png.h" />
     <ClInclude Include="third_party\png\png.h" />
     <ClInclude Include="third_party\png\pngasmrd.h" />
     <ClInclude Include="third_party\png\pngasmrd.h" />
     <ClInclude Include="third_party\png\pngconf.h" />
     <ClInclude Include="third_party\png\pngconf.h" />
@@ -2190,6 +2193,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
     <ClInclude Include="util\UTF8.h" />
     <ClInclude Include="util\UTF8.h" />
     <ClInclude Include="util\Vector.h" />
     <ClInclude Include="util\Vector.h" />
     <ClInclude Include="util\WorkThread.h" />
     <ClInclude Include="util\WorkThread.h" />
+    <ClInclude Include="util\ZipFile.h" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win64.asm">
     <CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win64.asm">

+ 15 - 0
BeefySysLib/BeefySysLib.vcxproj.filters

@@ -75,6 +75,9 @@
     <Filter Include="src\third_party\stb">
     <Filter Include="src\third_party\stb">
       <UniqueIdentifier>{b85b0989-3047-46e9-93d7-5bc352fb0df7}</UniqueIdentifier>
       <UniqueIdentifier>{b85b0989-3047-46e9-93d7-5bc352fb0df7}</UniqueIdentifier>
     </Filter>
     </Filter>
+    <Filter Include="src\third_party\miniz">
+      <UniqueIdentifier>{a159b9ee-1a71-44f5-a412-1e01e20b70c7}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="platform\win\DXRenderDevice.cpp">
     <ClCompile Include="platform\win\DXRenderDevice.cpp">
@@ -722,6 +725,12 @@
     <ClCompile Include="util\Compress.cpp">
     <ClCompile Include="util\Compress.cpp">
       <Filter>src\util</Filter>
       <Filter>src\util</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="third_party\miniz\miniz.c">
+      <Filter>src\third_party\miniz</Filter>
+    </ClCompile>
+    <ClCompile Include="util\ZipFile.cpp">
+      <Filter>src\util</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="Common.h">
     <ClInclude Include="Common.h">
@@ -1108,6 +1117,12 @@
     <ClInclude Include="util\BitSet.h">
     <ClInclude Include="util\BitSet.h">
       <Filter>src\util</Filter>
       <Filter>src\util</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="third_party\miniz\miniz.h">
+      <Filter>src\third_party\miniz</Filter>
+    </ClInclude>
+    <ClInclude Include="util\ZipFile.h">
+      <Filter>src\util</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">
     <CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">

+ 4 - 0
BeefySysLib/BeefySysLib_static.vcxproj

@@ -677,6 +677,7 @@
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Level1</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Level1</WarningLevel>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="third_party\miniz\miniz.c" />
     <ClCompile Include="third_party\png\png.c">
     <ClCompile Include="third_party\png\png.c">
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Level1</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
       <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level1</WarningLevel>
@@ -883,6 +884,7 @@
     <ClCompile Include="util\UTF8.cpp" />
     <ClCompile Include="util\UTF8.cpp" />
     <ClCompile Include="util\Vector.cpp" />
     <ClCompile Include="util\Vector.cpp" />
     <ClCompile Include="util\WorkThread.cpp" />
     <ClCompile Include="util\WorkThread.cpp" />
+    <ClCompile Include="util\ZipFile.cpp" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="BFApp.h" />
     <ClInclude Include="BFApp.h" />
@@ -1007,6 +1009,7 @@
     <ClInclude Include="third_party\jpeg\transupp.h" />
     <ClInclude Include="third_party\jpeg\transupp.h" />
     <ClInclude Include="third_party\libffi\i686-pc-cygwin\include\ffi.h" />
     <ClInclude Include="third_party\libffi\i686-pc-cygwin\include\ffi.h" />
     <ClInclude Include="third_party\libffi\i686-pc-cygwin\include\ffitarget.h" />
     <ClInclude Include="third_party\libffi\i686-pc-cygwin\include\ffitarget.h" />
+    <ClInclude Include="third_party\miniz\miniz.h" />
     <ClInclude Include="third_party\png\png.h" />
     <ClInclude Include="third_party\png\png.h" />
     <ClInclude Include="third_party\png\pngasmrd.h" />
     <ClInclude Include="third_party\png\pngasmrd.h" />
     <ClInclude Include="third_party\png\pngconf.h" />
     <ClInclude Include="third_party\png\pngconf.h" />
@@ -1049,6 +1052,7 @@
     <ClInclude Include="util\UTF8.h" />
     <ClInclude Include="util\UTF8.h" />
     <ClInclude Include="util\Vector.h" />
     <ClInclude Include="util\Vector.h" />
     <ClInclude Include="util\WorkThread.h" />
     <ClInclude Include="util\WorkThread.h" />
+    <ClInclude Include="util\ZipFile.h" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win64.asm">
     <CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win64.asm">

+ 15 - 0
BeefySysLib/BeefySysLib_static.vcxproj.filters

@@ -66,6 +66,9 @@
     <Filter Include="src\third_party\utf8proc">
     <Filter Include="src\third_party\utf8proc">
       <UniqueIdentifier>{1309f90f-4745-4623-ab21-5d7b1450103c}</UniqueIdentifier>
       <UniqueIdentifier>{1309f90f-4745-4623-ab21-5d7b1450103c}</UniqueIdentifier>
     </Filter>
     </Filter>
+    <Filter Include="src\third_party\miniz">
+      <UniqueIdentifier>{d32cb9b0-e79b-49fe-82e2-33302be0baf6}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="platform\win\DXRenderDevice.cpp">
     <ClCompile Include="platform\win\DXRenderDevice.cpp">
@@ -575,6 +578,12 @@
     <ClCompile Include="util\Compress.cpp">
     <ClCompile Include="util\Compress.cpp">
       <Filter>src\util</Filter>
       <Filter>src\util</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="util\ZipFile.cpp">
+      <Filter>src\util</Filter>
+    </ClCompile>
+    <ClCompile Include="third_party\miniz\miniz.c">
+      <Filter>src\third_party\miniz</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="Common.h">
     <ClInclude Include="Common.h">
@@ -883,6 +892,12 @@
     <ClInclude Include="util\Compress.h">
     <ClInclude Include="util\Compress.h">
       <Filter>src\util</Filter>
       <Filter>src\util</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="util\ZipFile.h">
+      <Filter>src\util</Filter>
+    </ClInclude>
+    <ClInclude Include="third_party\miniz\miniz.h">
+      <Filter>src\third_party\miniz</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">
     <CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">

+ 4 - 2
BeefySysLib/Common.cpp

@@ -1152,6 +1152,9 @@ String Beefy::FixPath(const StringImpl& pathIn)
 
 
 String Beefy::FixPathAndCase(const StringImpl& pathIn)
 String Beefy::FixPathAndCase(const StringImpl& pathIn)
 {
 {
+	if ((!pathIn.IsEmpty()) && (pathIn[0] == '$'))
+		return pathIn;
+
 	String path = FixPath(pathIn);
 	String path = FixPath(pathIn);
 #ifdef _WIN32
 #ifdef _WIN32
 	for (int i = 0; i < (int)path.length(); ++i)
 	for (int i = 0; i < (int)path.length(); ++i)
@@ -1180,8 +1183,7 @@ String Beefy::RemoveTrailingSlash(const StringImpl& str)
 
 
 bool Beefy::FileNameEquals(const StringImpl& filePathA, const StringImpl& filePathB)
 bool Beefy::FileNameEquals(const StringImpl& filePathA, const StringImpl& filePathB)
 {
 {
-#ifdef _WIN32
-	//return _stricmp(filePathA.c_str(), filePathB.c_str()) == 0;
+#ifdef _WIN32	
 	if (filePathA.length() != filePathB.length())
 	if (filePathA.length() != filePathB.length())
 		return false;
 		return false;
 	
 	

+ 110 - 0
BeefySysLib/util/ZipFile.cpp

@@ -0,0 +1,110 @@
+#include "ZipFile.h"
+
+extern "C"
+{
+#include "miniz/miniz.h"
+}
+
+USING_NS_BF;
+
+class ZipFile::Data
+{
+public:
+	bool mIsWriter;
+	mz_zip_archive mZip;
+};
+
+ZipFile::ZipFile()
+{
+	mData = NULL;
+}
+
+ZipFile::~ZipFile()
+{
+	if (mData != NULL)
+		Close();
+}
+
+bool ZipFile::Open(const StringImpl& filePath)
+{
+	if (mData != NULL)
+		Close();
+
+	mData = new ZipFile::Data();
+	memset(mData, 0, sizeof(ZipFile::Data));	
+	if (!mz_zip_reader_init_file(&mData->mZip, filePath.c_str(), 0))
+		return false;
+
+	return true;
+}
+
+bool ZipFile::Create(const StringImpl& filePath)
+{
+	if (mData != NULL)
+		Close();
+
+	mData = new ZipFile::Data();	
+	memset(mData, 0, sizeof(ZipFile::Data));	
+	if (!mz_zip_writer_init_file(&mData->mZip, filePath.c_str(), 0))	
+	{
+		delete mData;
+		mData = NULL;
+		return false;
+	}
+
+	mData->mIsWriter = true;
+	return true;
+}
+
+bool ZipFile::Close()
+{
+	if (mData == NULL)
+		return false;
+	
+	if (mData->mIsWriter)
+	{
+		if (!mz_zip_writer_finalize_archive(&mData->mZip))
+			return false;
+		if (!mz_zip_writer_end(&mData->mZip))
+			return false;
+	}
+	else
+	{
+		if (!mz_zip_reader_end(&mData->mZip))
+			return false;
+	}
+
+	return true;
+}
+
+bool ZipFile::IsOpen()
+{
+	return mData != NULL;
+}
+
+bool ZipFile::Add(const StringImpl& fileName, Span<uint8> data)
+{
+	if (mData == NULL)
+		return false;
+
+	if (!mz_zip_writer_add_mem(&mData->mZip, fileName.c_str(), data.mVals, data.mSize, MZ_NO_COMPRESSION))
+		return false;
+
+	return true;
+}
+
+
+bool ZipFile::Get(const StringImpl& fileName, Array<uint8>& data)
+{
+	if (mData == NULL)
+		return false;
+
+	int idx = mz_zip_reader_locate_file(&mData->mZip, fileName.c_str(), NULL, 0);
+	if (idx < 0)
+		return false;
+
+	size_t size = 0;
+	void* ptr = mz_zip_reader_extract_to_heap(&mData->mZip, idx, &size, 0);
+	data.Insert(data.mSize, (uint8*)ptr, (intptr)size);
+	return true;
+}

+ 30 - 0
BeefySysLib/util/ZipFile.h

@@ -0,0 +1,30 @@
+#pragma once
+
+#include "../Common.h"
+#include "../Span.h"
+
+NS_BF_BEGIN
+
+
+class ZipFile
+{
+public:
+	class Data;
+
+public:
+	Data* mData;
+
+public:
+	ZipFile();
+	~ZipFile();
+
+	bool Open(const StringImpl& filePath);
+	bool Create(const StringImpl& filePath);
+	bool Close();
+	bool IsOpen();
+	bool Add(const StringImpl& fileName, Span<uint8> data);
+	bool Get(const StringImpl& fileName, Array<uint8>& data);
+};
+
+
+NS_BF_END

+ 11 - 0
IDE/src/BuildContext.bf

@@ -1205,10 +1205,21 @@ namespace IDE
 						linkLine.Append(" /ignore:4099");
 						linkLine.Append(" /ignore:4099");
 					}
 					}
 
 
+					int targetDotPos = targetPath.LastIndexOf('.');
+					if (targetDotPos != -1)
+					{
+						var writeEmitCmd = new IDEApp.WriteEmitCmd();
+						writeEmitCmd.mPath = new .(targetPath, 0, targetDotPos);
+						writeEmitCmd.mPath.Append("__emit.zip");
+						writeEmitCmd.mProjectName = new .(project.mProjectName);
+						gApp.mExecutionQueue.Add(writeEmitCmd);
+					}
+
 			        var runCmd = gApp.QueueRun(linkerPath, linkLine, gApp.mInstallDir, .UTF16WithBom);
 			        var runCmd = gApp.QueueRun(linkerPath, linkLine, gApp.mInstallDir, .UTF16WithBom);
 					runCmd.mReference = new .(project.mProjectName);
 					runCmd.mReference = new .(project.mProjectName);
 					runCmd.mEnvVars = new .() { (new String("VSLANG"), new String("1033")) };
 					runCmd.mEnvVars = new .() { (new String("VSLANG"), new String("1033")) };
 			        runCmd.mOnlyIfNotFailed = true;
 			        runCmd.mOnlyIfNotFailed = true;
+
 			        var tagetCompletedCmd = new IDEApp.TargetCompletedCmd(project);
 			        var tagetCompletedCmd = new IDEApp.TargetCompletedCmd(project);
 			        tagetCompletedCmd.mOnlyIfNotFailed = true;
 			        tagetCompletedCmd.mOnlyIfNotFailed = true;
 			        gApp.mExecutionQueue.Add(tagetCompletedCmd);
 			        gApp.mExecutionQueue.Add(tagetCompletedCmd);

+ 43 - 8
IDE/src/Compiler/BfCompiler.bf

@@ -58,10 +58,10 @@ namespace IDE.Compiler
 		static extern bool BfCompiler_VerifyTypeName(void* bfCompiler, char8* typeName, int32 cursorPos);
 		static extern bool BfCompiler_VerifyTypeName(void* bfCompiler, char8* typeName, int32 cursorPos);
 
 
         [CallingConvention(.Stdcall), CLink]
         [CallingConvention(.Stdcall), CLink]
-        static extern bool BfCompiler_ClassifySource(void* bfCompiler, void* bfPassInstance, void* bfParser, void* bfResolvePassData, void* char8Data);
+        static extern bool BfCompiler_ClassifySource(void* bfCompiler, void* bfPassInstance, void* bfResolvePassData);
 
 
 		[CallingConvention(.Stdcall), CLink]
 		[CallingConvention(.Stdcall), CLink]
-		static extern char8* BfCompiler_GetCollapseRegions(void* bfCompiler, void* bfParser);
+		static extern char8* BfCompiler_GetCollapseRegions(void* bfCompiler, void* bfParser, void* bfResolvePassData, char8* explicitEmitTypeNames);
 
 
         [CallingConvention(.Stdcall), CLink]
         [CallingConvention(.Stdcall), CLink]
         static extern char8* BfCompiler_GetAutocompleteInfo(void* bfCompiler);
         static extern char8* BfCompiler_GetAutocompleteInfo(void* bfCompiler);
@@ -135,6 +135,12 @@ namespace IDE.Compiler
 		[CallingConvention(.Stdcall), CLink]
 		[CallingConvention(.Stdcall), CLink]
 		static extern char8* BfCompiler_GetTypeInfo(void* bfCompiler, char8* typeName);
 		static extern char8* BfCompiler_GetTypeInfo(void* bfCompiler, char8* typeName);
 
 
+		[CallingConvention(.Stdcall), CLink]
+		static extern char8* BfCompiler_GetGenericTypeInstances(void* bfCompiler, char8* typeName);
+
+		[CallingConvention(.Stdcall), CLink]
+		static extern int32 BfCompiler_GetTypeId(void* bfCompiler, char8* typeName);
+
         [CallingConvention(.Stdcall), CLink]
         [CallingConvention(.Stdcall), CLink]
         static extern void BfCompiler_SetOptions(void* bfCompiler,
         static extern void BfCompiler_SetOptions(void* bfCompiler,
             void* hotProject, int32 hotIdx, char8* targetTriple, char8* targetCPU, int32 toolsetType, int32 simdSetting, int32 allocStackCount, int32 maxWorkerThreads,
             void* hotProject, int32 hotIdx, char8* targetTriple, char8* targetCPU, int32 toolsetType, int32 simdSetting, int32 allocStackCount, int32 maxWorkerThreads,
@@ -149,6 +155,12 @@ namespace IDE.Compiler
 		[CallingConvention(.Stdcall), CLink]
 		[CallingConvention(.Stdcall), CLink]
 		static extern int32 BfCompiler_GetEmitSourceVersion(void* bfCompiler, char8* fileName);
 		static extern int32 BfCompiler_GetEmitSourceVersion(void* bfCompiler, char8* fileName);
 
 
+		[CallingConvention(.Stdcall), CLink]
+		static extern char8* BfCompiler_GetEmitLocation(void* bfCompiler, char8* typeName, int32 line, out int32 embedLine, out int32 embedLineChar);
+
+		[CallingConvention(.Stdcall), CLink]
+		static extern void BfCompiler_WriteEmitData(void* bfCompiler, char8* filePath, void* bfProject);
+		
 		public enum HotTypeFlags
 		public enum HotTypeFlags
 		{
 		{
 			None		= 0,
 			None		= 0,
@@ -260,18 +272,17 @@ namespace IDE.Compiler
 			BfCompiler_ClearResults(mNativeBfCompiler);
 			BfCompiler_ClearResults(mNativeBfCompiler);
 		}
 		}
 
 
-        public bool ClassifySource(BfPassInstance bfPassInstance, BfParser parser, BfResolvePassData resolvePassData, EditWidgetContent.CharData[] char8Data)
+        public bool ClassifySource(BfPassInstance bfPassInstance, BfResolvePassData resolvePassData)
         {
         {
             void* nativeResolvePassData = null;
             void* nativeResolvePassData = null;
             if (resolvePassData != null)
             if (resolvePassData != null)
                 nativeResolvePassData = resolvePassData.mNativeResolvePassData;
                 nativeResolvePassData = resolvePassData.mNativeResolvePassData;
-            EditWidgetContent.CharData* char8DataPtr = (char8Data != null) ? char8Data.CArray() : null;
-            return BfCompiler_ClassifySource(mNativeBfCompiler, bfPassInstance.mNativeBfPassInstance, (parser != null) ? parser.mNativeBfParser : null, nativeResolvePassData, char8DataPtr);                
+            return BfCompiler_ClassifySource(mNativeBfCompiler, bfPassInstance.mNativeBfPassInstance, nativeResolvePassData);
         }
         }
 
 
-		public void GetCollapseRegions(BfParser parser, String outData)
+		public void GetCollapseRegions(BfParser parser, BfResolvePassData resolvePassData, String explicitEmitTypeNames, String outData)
 		{
 		{
-			outData.Append(BfCompiler_GetCollapseRegions(mNativeBfCompiler, (parser != null) ? parser.mNativeBfParser : null));
+			outData.Append(BfCompiler_GetCollapseRegions(mNativeBfCompiler, (parser != null) ? parser.mNativeBfParser : null, resolvePassData.mNativeResolvePassData, explicitEmitTypeNames));
 		}
 		}
 
 
 		public bool VerifyTypeName(String typeName, int cursorPos)
 		public bool VerifyTypeName(String typeName, int cursorPos)
@@ -344,6 +355,15 @@ namespace IDE.Compiler
 			return BfCompiler_GetEmitSourceVersion(mNativeBfCompiler, fileName.ToScopeCStr!());
 			return BfCompiler_GetEmitSourceVersion(mNativeBfCompiler, fileName.ToScopeCStr!());
 		}
 		}
 
 
+		public void GetEmitLocation(StringView typeName, int line, String outFilePath, out int embedLine, out int embedLineChar)
+		{
+			int32 embedLine32;
+			int32 embedLineChar32;
+			outFilePath.Append(BfCompiler_GetEmitLocation(mNativeBfCompiler, typeName.ToScopeCStr!(), (.)line, out embedLine32, out embedLineChar32));
+			embedLine = embedLine32;
+			embedLineChar = embedLineChar32;
+		}
+
         public void QueueSetPassInstance(BfPassInstance passInstance)
         public void QueueSetPassInstance(BfPassInstance passInstance)
         {
         {
             SetPassInstanceCommand command = new SetPassInstanceCommand();
             SetPassInstanceCommand command = new SetPassInstanceCommand();
@@ -588,7 +608,7 @@ namespace IDE.Compiler
 
 
                     var resolvePassData = BfResolvePassData.Create(ResolveType.Classify);
                     var resolvePassData = BfResolvePassData.Create(ResolveType.Classify);
                     // If we get canceled then try again after waiting a couple updates
                     // If we get canceled then try again after waiting a couple updates
-                    if (!ClassifySource(passInstance, null, resolvePassData, null))
+                    if (!ClassifySource(passInstance, resolvePassData))
                         QueueDeferredResolveAll();
                         QueueDeferredResolveAll();
 					UpdateRebuildFileWatches();
 					UpdateRebuildFileWatches();
 
 
@@ -808,11 +828,21 @@ namespace IDE.Compiler
 			outStr.Append(BfCompiler_GetTypeDefInfo(mNativeBfCompiler, typeDefName));
 			outStr.Append(BfCompiler_GetTypeDefInfo(mNativeBfCompiler, typeDefName));
 		}
 		}
 
 
+		public void GetGenericTypeInstances(String typeName, String outStr)
+		{
+			outStr.Append(BfCompiler_GetGenericTypeInstances(mNativeBfCompiler, typeName));
+		}
+
 		public void GetTypeInfo(String typeDefName, String outStr)
 		public void GetTypeInfo(String typeDefName, String outStr)
 		{
 		{
 			outStr.Append(BfCompiler_GetTypeInfo(mNativeBfCompiler, typeDefName));
 			outStr.Append(BfCompiler_GetTypeInfo(mNativeBfCompiler, typeDefName));
 		}
 		}
 
 
+		public int GetTypeId(String typeName)
+		{
+			return BfCompiler_GetTypeId(mNativeBfCompiler, typeName);
+		}
+
 		public void ClearBuildCache()
 		public void ClearBuildCache()
 		{
 		{
 			BfCompiler_ClearBuildCache(mNativeBfCompiler);
 			BfCompiler_ClearBuildCache(mNativeBfCompiler);
@@ -943,5 +973,10 @@ namespace IDE.Compiler
 			dirChangedCommand.mDir.Set(str);
 			dirChangedCommand.mDir.Set(str);
 			QueueCommand(dirChangedCommand);
 			QueueCommand(dirChangedCommand);
 		}
 		}
+
+		public void WriteEmitData(String filePath, BfProject bfProject)
+		{
+			BfCompiler_WriteEmitData(mNativeBfCompiler, filePath, bfProject.mNativeBfProject);
+		}
     }
     }
 }
 }

+ 67 - 23
IDE/src/Compiler/BfParser.bf

@@ -29,29 +29,50 @@ namespace IDE.Compiler
 
 
     public enum ResolveType
     public enum ResolveType
     {
     {
-        None,
-        Classify,
-        ClassifyFullRefresh,
-        Autocomplete,
-        Autocomplete_HighPri,
-        GoToDefinition,
-        GetSymbolInfo,        
-        RenameSymbol,
-        ShowFileSymbolReferences,
-        GetNavigationData,
-		GetCurrentLocation,
-		GetFixits,
-		GetTypeDefList,
-		GetTypeDefInto,
-		GetResultString
+        case None,
+	        Classify,
+	        ClassifyFullRefresh,
+	        Autocomplete,
+	        Autocomplete_HighPri,
+	        GoToDefinition,
+	        GetSymbolInfo,        
+	        RenameSymbol,
+	        ShowFileSymbolReferences,
+	        GetNavigationData,
+			GetCurrentLocation,
+			GetFixits,
+			GetTypeDefList,
+			GetTypeDefInto,
+			GetResultString;
+
+		public bool IsClassify => (this == .Classify) || (this == .ClassifyFullRefresh);
     }
     }
 
 
+	public enum SourceEmbedKind
+	{
+		None,
+		Type,
+		Method
+	}
+
     public class ResolveParams
     public class ResolveParams
     {
     {
+		public class Embed
+		{
+			public String mTypeName ~ delete _;
+			public int32 mRevision = -1;
+			public int32 mCursorIdx = -1;
+			public EditWidgetContent.CharData[] mCharData ~ delete _;
+		}
+
 		public ResolveType mResolveType;
 		public ResolveType mResolveType;
 		public int32 mOverrideCursorPos = -1;
 		public int32 mOverrideCursorPos = -1;
 		public bool mInDeferredList;
 		public bool mInDeferredList;
 
 
+		public EditWidgetContent.CharData[] mCharData ~ delete _;
+		public IdSpan mCharIdSpan ~ _.Dispose();
+		public BfParser mParser;
+
         public int32 mLocalId = -1;
         public int32 mLocalId = -1;
         public String mReplaceStr ~ delete _;
         public String mReplaceStr ~ delete _;
         public String mTypeDef ~ delete _;
         public String mTypeDef ~ delete _;
@@ -71,9 +92,7 @@ namespace IDE.Compiler
 		public WaitEvent mWaitEvent ~ delete _;
 		public WaitEvent mWaitEvent ~ delete _;
 
 
 		public BfPassInstance mPassInstance ~ delete _;
 		public BfPassInstance mPassInstance ~ delete _;
-		public EditWidgetContent.CharData[] mCharData ~ delete _;
-		public IdSpan mCharIdSpan ~ _.Dispose();
-		public BfParser mParser;
+		public List<Embed> mEmitEmbeds = new .() ~ DeleteContainerAndItems!(_);
 		public String mDocumentationName ~ delete _;
 		public String mDocumentationName ~ delete _;
 		public bool mCancelled;
 		public bool mCancelled;
 		public int32 mTextVersion = -1;
 		public int32 mTextVersion = -1;
@@ -108,13 +127,16 @@ namespace IDE.Compiler
         static extern void BfParser_SetNextRevision(void* bfParser, void* nextParser);
         static extern void BfParser_SetNextRevision(void* bfParser, void* nextParser);
 
 
         [CallingConvention(.Stdcall), CLink]
         [CallingConvention(.Stdcall), CLink]
-        static extern bool BfParser_SetCursorIdx(void* bfParser, int32 cursorIdx);
+        static extern void BfParser_SetCursorIdx(void* bfParser, int32 cursorIdx);
 
 
         [CallingConvention(.Stdcall), CLink]
         [CallingConvention(.Stdcall), CLink]
-        static extern bool BfParser_SetAutocomplete(void* bfParser, int32 cursorIdx);
+        static extern void BfParser_SetAutocomplete(void* bfParser, int32 cursorIdx);
+
+		[CallingConvention(.Stdcall), CLink]
+		static extern void BfParser_SetEmbedKind(void* bfParser, SourceEmbedKind embedKind);
 
 
         [CallingConvention(.Stdcall), CLink]
         [CallingConvention(.Stdcall), CLink]
-        static extern bool BfParser_SetIsClassifying(void* bfParser);
+        static extern void BfParser_SetIsClassifying(void* bfParser);
 
 
         [CallingConvention(.Stdcall), CLink]
         [CallingConvention(.Stdcall), CLink]
         static extern bool BfParser_Parse(void* bfParser, void* bfPassInstance, bool compatMode);
         static extern bool BfParser_Parse(void* bfParser, void* bfPassInstance, bool compatMode);
@@ -140,6 +162,12 @@ namespace IDE.Compiler
         [CallingConvention(.Stdcall), CLink]
         [CallingConvention(.Stdcall), CLink]
         static extern void BfParser_ClassifySource(void* bfParser, void* elementTypeArray, bool preserveFlags);
         static extern void BfParser_ClassifySource(void* bfParser, void* elementTypeArray, bool preserveFlags);
 
 
+		[CallingConvention(.Stdcall), CLink]
+        static extern void BfParser_CreateClassifier(void* bfParser, void* passInstance, void* resolvePassData, void* elementTypeArray);
+
+		[CallingConvention(.Stdcall), CLink]
+		static extern void BfParser_FinishClassifier(void* bfParser, void* resolvePassData);
+
         [CallingConvention(.Stdcall), CLink]
         [CallingConvention(.Stdcall), CLink]
         static extern void BfParser_GenerateAutoCompletionFrom(void* bfParser, int32 srcPosition);
         static extern void BfParser_GenerateAutoCompletionFrom(void* bfParser, int32 srcPosition);
 
 
@@ -168,11 +196,11 @@ namespace IDE.Compiler
 			mNativeBfParser = null;
 			mNativeBfParser = null;
 		}
 		}
 
 
-        public void SetSource(String data, String fileName)
+        public void SetSource(StringView data, String fileName)
         {
         {
             Debug.Assert(!mIsUsed);
             Debug.Assert(!mIsUsed);
             mIsUsed = true;
             mIsUsed = true;
-            BfParser_SetSource(mNativeBfParser, data, (int32)data.Length, fileName);
+            BfParser_SetSource(mNativeBfParser, data.Ptr, (int32)data.Length, fileName);
         }
         }
 
 
         public void SetCharIdData(ref IdSpan char8IdData)
         public void SetCharIdData(ref IdSpan char8IdData)
@@ -192,6 +220,11 @@ namespace IDE.Compiler
             BfParser_SetAutocomplete(mNativeBfParser, (int32)cursorIdx);
             BfParser_SetAutocomplete(mNativeBfParser, (int32)cursorIdx);
         }
         }
 
 
+		public void SetEmbedKind(SourceEmbedKind embedKind)
+		{
+			BfParser_SetEmbedKind(mNativeBfParser, embedKind);
+		}
+
         public void SetIsClassifying()
         public void SetIsClassifying()
         {
         {
             BfParser_SetIsClassifying(mNativeBfParser);
             BfParser_SetIsClassifying(mNativeBfParser);
@@ -247,6 +280,17 @@ namespace IDE.Compiler
             BfParser_ClassifySource(mNativeBfParser, char8DataPtr, preserveFlags);
             BfParser_ClassifySource(mNativeBfParser, char8DataPtr, preserveFlags);
         }
         }
 
 
+		public void CreateClassifier(BfPassInstance passInstance, BfResolvePassData bfResolvePassData, EditWidgetContent.CharData[] charDataArr)
+		{
+			EditWidgetContent.CharData* charDataPtr = charDataArr.CArray();
+			BfParser_CreateClassifier(mNativeBfParser, passInstance.mNativeBfPassInstance, bfResolvePassData.mNativeResolvePassData, charDataPtr);
+		}
+
+		public void FinishClassifier(BfResolvePassData bfResolvePassData)
+		{
+			BfParser_FinishClassifier(mNativeBfParser, bfResolvePassData.mNativeResolvePassData);
+		}
+
         public void SetNextRevision(BfParser nextRevision)
         public void SetNextRevision(BfParser nextRevision)
         {
         {
             BfParser_SetNextRevision(mNativeBfParser, nextRevision.mNativeBfParser);
             BfParser_SetNextRevision(mNativeBfParser, nextRevision.mNativeBfParser);

+ 17 - 0
IDE/src/Compiler/BfResolvePassData.bf

@@ -2,6 +2,7 @@ using System;
 using System.Collections;
 using System.Collections;
 using System.Text;
 using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using Beefy.widgets;
 
 
 namespace IDE.Compiler
 namespace IDE.Compiler
 {
 {
@@ -37,6 +38,12 @@ namespace IDE.Compiler
 		[CallingConvention(.Stdcall), CLink]
 		[CallingConvention(.Stdcall), CLink]
 		static extern void BfResolvePassData_SetDocumentationRequest(void* bfResolvePassData, char8* entryName);
 		static extern void BfResolvePassData_SetDocumentationRequest(void* bfResolvePassData, char8* entryName);
 
 
+		[CallingConvention(.Stdcall), CLink]
+		static extern void BfResolvePassData_AddEmitEmbed(void* bfResolvePassData, char8* typeName, int32 cursorIdx);
+
+		[CallingConvention(.Stdcall), CLink]
+		static extern void* BfResolvePassData_GetEmitEmbedData(void* bfResolvePassData, char8* typeName, out int32 srcLength, out int32 revision);
+
         //
         //
 
 
         //[CallingConvention(.Stdcall), CLink]
         //[CallingConvention(.Stdcall), CLink]
@@ -100,5 +107,15 @@ namespace IDE.Compiler
             resolvePassData.mNativeResolvePassData = BfParser.[Friend]BfParser_CreateResolvePassData(null, (int32)resolveType, doFuzzyAutoComplete);
             resolvePassData.mNativeResolvePassData = BfParser.[Friend]BfParser_CreateResolvePassData(null, (int32)resolveType, doFuzzyAutoComplete);
             return resolvePassData;
             return resolvePassData;
         }
         }
+
+		public void AddEmitEmbed(char8* typeName, int32 cursorIdx)
+		{
+			BfResolvePassData_AddEmitEmbed(mNativeResolvePassData, typeName, cursorIdx);
+		}
+
+		public EditWidgetContent.CharData* GetEmitEmbedData(char8* typeName, out int32 srcLength, out int32 revision)
+		{
+			return (.)BfResolvePassData_GetEmitEmbedData(mNativeResolvePassData, typeName, out srcLength, out revision);
+		}
     }
     }
 }
 }

+ 29 - 1
IDE/src/Debugger/DebugManager.bf

@@ -372,6 +372,9 @@ namespace IDE.Debugger
 		[CallingConvention(.Stdcall),CLink]
 		[CallingConvention(.Stdcall),CLink]
 		static extern int Debugger_GetDbgAllocHeapSize();
 		static extern int Debugger_GetDbgAllocHeapSize();
 
 
+		[CallingConvention(.Stdcall), CLink]
+		static extern char8* Debugger_GetEmitSource(char8* fileName);
+
 		public String mRunningPath ~ delete _;
 		public String mRunningPath ~ delete _;
 		public bool mIsRunning;
 		public bool mIsRunning;
 		public bool mIsRunningCompiled;
 		public bool mIsRunningCompiled;
@@ -382,8 +385,9 @@ namespace IDE.Debugger
 		public int32 mActiveCallStackIdx;
 		public int32 mActiveCallStackIdx;
 		public Event<Action> mBreakpointsChangedDelegate ~ _.Dispose();
 		public Event<Action> mBreakpointsChangedDelegate ~ _.Dispose();
 		public Breakpoint mRunToCursorBreakpoint;
 		public Breakpoint mRunToCursorBreakpoint;
+		public int32 mDebugIdx;
 
 
-		bool IsRunning
+		public bool IsRunning
 		{
 		{
 			get
 			get
 			{
 			{
@@ -391,6 +395,14 @@ namespace IDE.Debugger
 			}
 			}
 		}
 		}
 
 
+		public bool IsRunningUncompiled
+		{
+			get
+			{
+				return mIsRunning && !mIsRunningCompiled;
+			}
+		}
+
 		public this()
 		public this()
 		{
 		{
 			Debugger_Create();
 			Debugger_Create();
@@ -975,7 +987,14 @@ namespace IDE.Debugger
 			stackSize = stackSizeOut;
 			stackSize = stackSizeOut;
 
 
 			if (outFile != null)
 			if (outFile != null)
+			{
 				outFile.Append(fileStrPtr);
 				outFile.Append(fileStrPtr);
+				if ((outFile.StartsWith("$Emit")) && (mIsRunningCompiled))
+				{
+					int dollarPos = outFile.IndexOf('$', 1);
+					outFile.Remove(5, dollarPos - 5);
+				}
+			}
 			if (outStackFrameInfo != null)
 			if (outStackFrameInfo != null)
 				outStackFrameInfo.Append(locationStr);
 				outStackFrameInfo.Append(locationStr);
 		}
 		}
@@ -1224,5 +1243,14 @@ namespace IDE.Debugger
 		{
 		{
 			return Debugger_GetDbgAllocHeapSize();
 			return Debugger_GetDbgAllocHeapSize();
 		}
 		}
+
+		public bool GetEmitSource(StringView fileName, String outText)
+		{
+			char8* str = Debugger_GetEmitSource(fileName.ToScopeCStr!());
+			if (str == null)
+				return false;
+			outText.Append(str);
+			return true;
+		}
 	}
 	}
 }
 }

+ 199 - 59
IDE/src/IDEApp.bf

@@ -380,6 +380,12 @@ namespace IDE
             public bool mOnlyIfNotFailed;
             public bool mOnlyIfNotFailed;
         }
         }
 
 
+		public class WriteEmitCmd : ExecutionCmd
+		{
+			public String mProjectName ~ delete _;
+			public String mPath ~ delete _;
+		}
+
         public class BuildCompletedCmd : ExecutionCmd
         public class BuildCompletedCmd : ExecutionCmd
         {
         {
             public Stopwatch mStopwatch ~ delete _;
             public Stopwatch mStopwatch ~ delete _;
@@ -524,6 +530,18 @@ namespace IDE
         private int32 mStepCount;
         private int32 mStepCount;
         private int32 mNoDebugMessagesTick;
         private int32 mNoDebugMessagesTick;
 
 
+		public class DeferredShowSource
+		{
+			public String mFilePath ~ delete _;
+			public int32 mShowHotIdx;
+			public int32 mRefHotIdx;
+			public int32 mLine;
+			public int32 mColumn;
+			public LocatorType mHilitePosition;
+			public bool mShowTemp;
+		}
+		public DeferredShowSource mDeferredShowSource ~ delete _;
+
         public bool IsCompiling
         public bool IsCompiling
         {
         {
             get
             get
@@ -1335,7 +1353,7 @@ namespace IDE
             return false;
             return false;
         }
         }
 
 
-        public SourceViewPanel GetActiveSourceViewPanel(bool includeLastActive = false)
+        public SourceViewPanel GetActiveSourceViewPanel(bool includeLastActive = false, bool includeEmbeds = false)
         {
         {
 			if (mRunningTestScript)
 			if (mRunningTestScript)
 				return mLastActiveSourceViewPanel;
 				return mLastActiveSourceViewPanel;
@@ -1343,10 +1361,12 @@ namespace IDE
             var activePanel = GetActiveDocumentPanel();
             var activePanel = GetActiveDocumentPanel();
             var sourceViewPanel = activePanel as SourceViewPanel;
             var sourceViewPanel = activePanel as SourceViewPanel;
 			if (sourceViewPanel != null)
 			if (sourceViewPanel != null)
-				return sourceViewPanel.GetActivePanel();
+				sourceViewPanel = sourceViewPanel.GetActivePanel();
 			if ((mLastActiveSourceViewPanel != null) && (includeLastActive))
 			if ((mLastActiveSourceViewPanel != null) && (includeLastActive))
-				return mLastActiveSourceViewPanel.GetActivePanel();
-			return null;
+				sourceViewPanel = mLastActiveSourceViewPanel.GetActivePanel();
+			if ((sourceViewPanel != null) && (includeEmbeds))
+				sourceViewPanel = sourceViewPanel.GetFocusedEmbeddedView();
+			return sourceViewPanel;
         }
         }
 
 
         public TextPanel GetActiveTextPanel()
         public TextPanel GetActiveTextPanel()
@@ -1461,21 +1481,20 @@ namespace IDE
 				}
 				}
 			}
 			}
 
 
-			BfCompiler compiler = null;
-
-			if (fileName.Contains("$EmitR$"))
-				compiler = mBfResolveCompiler;
-			else if (fileName.Contains("$Emit$"))
-				compiler = mBfBuildCompiler;
-
-			if (compiler != null)
+			if (fileName.StartsWith("$Emit$"))
 			{
 			{
-				if (compiler.GetEmitSource(fileName, outBuffer))
-				{
-					if (onPreFilter != null)
-						onPreFilter();
+				BfCompiler compiler = mBfResolveCompiler;
+				if (!compiler.IsPerformingBackgroundOperation())
+					compiler.GetEmitSource(fileName, outBuffer);
+				
+				if (onPreFilter != null)
+					onPreFilter();
+				return .Ok;
+			}
+			else if (fileName.StartsWith("$Emit"))
+			{
+				if (mDebugger.GetEmitSource(fileName, outBuffer))
 					return .Ok;
 					return .Ok;
-				}
 			}
 			}
 
 
 			return Utils.LoadTextFile(fileName, outBuffer, autoRetry, onPreFilter);
 			return Utils.LoadTextFile(fileName, outBuffer, autoRetry, onPreFilter);
@@ -4152,7 +4171,7 @@ namespace IDE
 
 
         public void GoToDefinition(bool force)
         public void GoToDefinition(bool force)
         {
         {
-            var sourceViewPanel = GetActiveSourceViewPanel();
+            var sourceViewPanel = GetActiveSourceViewPanel(false, true);
             if (sourceViewPanel != null)
             if (sourceViewPanel != null)
             {
             {
 				if (!force)
 				if (!force)
@@ -4188,7 +4207,7 @@ namespace IDE
                 }
                 }
                 else
                 else
 #endif
 #endif
-                {                    
+                /*{                    
                     ResolveParams resolveParams = scope ResolveParams();
                     ResolveParams resolveParams = scope ResolveParams();
                     sourceViewPanel.Classify(ResolveType.GoToDefinition, resolveParams);
                     sourceViewPanel.Classify(ResolveType.GoToDefinition, resolveParams);
                     if (resolveParams.mOutFileName != null)
                     if (resolveParams.mOutFileName != null)
@@ -4204,7 +4223,7 @@ namespace IDE
 				{
 				{
 	                Fail("Unable to locate definition");
 	                Fail("Unable to locate definition");
 				}
 				}
-				else
+				else*/
 				{
 				{
 					sourceViewPanel.ShowSymbolReferenceHelper(.GoToDefinition);
 					sourceViewPanel.ShowSymbolReferenceHelper(.GoToDefinition);
 				}
 				}
@@ -4629,6 +4648,7 @@ namespace IDE
 
 
 			if (var sourceViewPanel = documentPanel as SourceViewPanel)
 			if (var sourceViewPanel = documentPanel as SourceViewPanel)
 			{
 			{
+				sourceViewPanel = sourceViewPanel.GetFocusedEmbeddedView();
 			    sourceViewPanel.ToggleBreakpointAtCursor(setKind, setFlags, bindToThread ? gApp.mDebugger.GetActiveThread() : -1);
 			    sourceViewPanel.ToggleBreakpointAtCursor(setKind, setFlags, bindToThread ? gApp.mDebugger.GetActiveThread() : -1);
 			}
 			}
 			else if (var disassemblyPanel = documentPanel as DisassemblyPanel)
 			else if (var disassemblyPanel = documentPanel as DisassemblyPanel)
@@ -6483,9 +6503,10 @@ namespace IDE
 
 
         public (SourceViewPanel panel, TabbedView.TabButton tabButton) ShowSourceFile(String filePath, ProjectSource projectSource = null, SourceShowType showType = SourceShowType.ShowExisting, bool setFocus = true)
         public (SourceViewPanel panel, TabbedView.TabButton tabButton) ShowSourceFile(String filePath, ProjectSource projectSource = null, SourceShowType showType = SourceShowType.ShowExisting, bool setFocus = true)
         {
         {
+			DeleteAndNullify!(mDeferredShowSource);
+
 			//TODO: PUT BACK!
 			//TODO: PUT BACK!
 			//return null;
 			//return null;
-
 #unwarn
 #unwarn
 			String useFilePath = filePath;
 			String useFilePath = filePath;
 			var useProjectSource = projectSource;
 			var useProjectSource = projectSource;
@@ -6604,6 +6625,8 @@ namespace IDE
             else
             else
                 success = sourceViewPanel.Show(useFilePath, !mInitialized);
                 success = sourceViewPanel.Show(useFilePath, !mInitialized);
 			sourceViewPanel.mEmitRevision = emitRevision;
 			sourceViewPanel.mEmitRevision = emitRevision;
+			if (emitRevision != -1)
+				sourceViewPanel.mEditWidget.mEditWidgetContent.mIsReadOnly = true;
 
 
             if (!success)
             if (!success)
             {
             {
@@ -7051,9 +7074,76 @@ namespace IDE
 
 
         public SourceViewPanel ShowSourceFileLocation(String filePath, int showHotIdx, int refHotIdx, int line, int column, LocatorType hilitePosition, bool showTemp = false)
         public SourceViewPanel ShowSourceFileLocation(String filePath, int showHotIdx, int refHotIdx, int line, int column, LocatorType hilitePosition, bool showTemp = false)
         {
         {
-            var sourceViewPanel = ShowSourceFile(filePath, null, showTemp ? SourceShowType.Temp : SourceShowType.ShowExisting).panel;
+			if (filePath.StartsWith("$Emit$"))
+			{
+				var compiler = mBfResolveCompiler;
+				if (compiler.IsPerformingBackgroundOperation())
+				{
+					DeleteAndNullify!(mDeferredShowSource);
+					mDeferredShowSource = new DeferredShowSource()
+						{
+							mFilePath = new .(filePath),
+							mShowHotIdx = (.)showHotIdx,
+							mRefHotIdx = (.)refHotIdx,
+							mLine = (.)line,
+							mColumn = (.)column,
+							mHilitePosition = hilitePosition,
+							mShowTemp = showTemp
+						};
+					return null;
+				}
+
+				var itr = filePath.Split('$');
+				itr.GetNext();
+				itr.GetNext();
+				var typeName = itr.GetNext().Value;
+
+				//var compiler = (kindStr == "Emit") ? mBfBuildCompiler : mBfResolveCompiler;
+				
+				compiler.mBfSystem.Lock(0);
+				var embedFilePath = compiler.GetEmitLocation(typeName, line, .. scope .(), var embedLine, var embedLineChar);
+				compiler.mBfSystem.Unlock();
+
+				if (!embedFilePath.IsEmpty)
+				{
+					var sourceViewPanel = ShowSourceFile(scope .(embedFilePath), null, showTemp ? SourceShowType.Temp : SourceShowType.ShowExisting).panel;
+					if (sourceViewPanel == null)
+					    return null;
+
+					var sewc = sourceViewPanel.mEditWidget.mEditWidgetContent as SourceEditWidgetContent;
+					var data = sewc.mData as SourceEditWidgetContent.Data;
+
+					QueuedEmitShowData emitShowData = new .();
+					emitShowData.mPrevCollapseParseRevision = data.mCollapseParseRevision;
+					emitShowData.mTypeName = new .(typeName);
+					emitShowData.mLine = (.)line;
+					emitShowData.mColumn = (.)column;
+					DeleteAndNullify!(sourceViewPanel.[Friend]mQueuedEmitShowData);
+					sourceViewPanel.[Friend]mQueuedEmitShowData = emitShowData;
+
+					//sourceViewPanel.ShowHotFileIdx(showHotIdx);
+					sourceViewPanel.ShowFileLocation(refHotIdx, embedLine, embedLineChar, .None);
+					//sourceViewPanel.QueueFullRefresh(false);
+					//sourceViewPanel.mBackgroundDelay = 1; // Don't immediately perform the full classify
+
+					if (typeName.Contains('<'))
+					{
+						if (sourceViewPanel.AddExplicitEmitType(typeName))
+							sourceViewPanel.QueueFullRefresh(false);
+					}
+
+					if (!sourceViewPanel.[Friend]mWantsFullRefresh)
+						sourceViewPanel.UpdateQueuedEmitShowData();
+
+					return sourceViewPanel;
+				}
+			}
+
+            var (sourceViewPanel, tabButton) = ShowSourceFile(filePath, null, showTemp ? SourceShowType.Temp : SourceShowType.ShowExisting);
             if (sourceViewPanel == null)
             if (sourceViewPanel == null)
                 return null;
                 return null;
+			if (((filePath.StartsWith("$")) && (var svTabButton = tabButton as SourceViewTabButton)))
+				svTabButton.mIsTemp = true;
             sourceViewPanel.ShowHotFileIdx(showHotIdx);
             sourceViewPanel.ShowHotFileIdx(showHotIdx);
             sourceViewPanel.ShowFileLocation(refHotIdx, Math.Max(0, line), Math.Max(0, column), hilitePosition);
             sourceViewPanel.ShowFileLocation(refHotIdx, Math.Max(0, line), Math.Max(0, column), hilitePosition);
             return sourceViewPanel;
             return sourceViewPanel;
@@ -7155,6 +7245,10 @@ namespace IDE
 						checkForOldFileInfo = true;
 						checkForOldFileInfo = true;
 				}
 				}
 			}
 			}
+			else if (filePath.StartsWith("$Emit"))
+			{
+				// Check this later
+			}
 			else
 			else
 			{
 			{
 				if (!File.Exists(filePath))
 				if (!File.Exists(filePath))
@@ -7207,6 +7301,12 @@ namespace IDE
 					ShowCallstack();
 					ShowCallstack();
 				}
 				}
 
 
+				if (filePath.StartsWith("$"))
+				{
+					ShowSourceFileLocation(filePath, hotIdx, hotIdx, line, column, .Smart);
+					return;
+				}
+
                 var (sourceViewPanel, tabButton) = ShowSourceFile(filePath, null, SourceShowType.ShowExisting, setFocus);
                 var (sourceViewPanel, tabButton) = ShowSourceFile(filePath, null, SourceShowType.ShowExisting, setFocus);
                 if (sourceViewPanel != null)
                 if (sourceViewPanel != null)
                 {
                 {
@@ -7957,6 +8057,8 @@ namespace IDE
 
 
         public static bool IsBeefFile(String fileName)
         public static bool IsBeefFile(String fileName)
         {
         {
+			if (fileName.StartsWith('$'))
+				return true;
             return fileName.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".bf", StringComparison.OrdinalIgnoreCase);
             return fileName.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".bf", StringComparison.OrdinalIgnoreCase);
         }
         }
 
 
@@ -7971,6 +8073,8 @@ namespace IDE
 
 
 		public static bool IsSourceCode(String fileName)
 		public static bool IsSourceCode(String fileName)
 		{
 		{
+			if (fileName.StartsWith('$'))
+				return true;
 			return fileName.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".bf", StringComparison.OrdinalIgnoreCase) ||
 			return fileName.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".bf", StringComparison.OrdinalIgnoreCase) ||
 				fileName.EndsWith(".h", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".cpp", StringComparison.OrdinalIgnoreCase) ||
 				fileName.EndsWith(".h", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".cpp", StringComparison.OrdinalIgnoreCase) ||
 				fileName.EndsWith(".c", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".cc", StringComparison.OrdinalIgnoreCase) ||
 				fileName.EndsWith(".c", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".cc", StringComparison.OrdinalIgnoreCase) ||
@@ -8775,6 +8879,30 @@ namespace IDE
 					// Already handled
 					// Already handled
 					(void)scriptCmd;
 					(void)scriptCmd;
 				}
 				}
+				else if (var writeEmitCmd = next as WriteEmitCmd)
+				{
+					String projectName = new String(writeEmitCmd.mProjectName);
+					String filePath = new String(writeEmitCmd.mPath);
+
+					mBfBuildCompiler.DoBackground(new () =>
+						{
+							if (var project = mWorkspace.FindProject(projectName))
+							{
+								var bfProject = mBfBuildSystem.GetBfProject(project);
+								if (bfProject != null)
+								{
+									mBfBuildSystem.Lock(0);
+									mBfBuildCompiler.WriteEmitData(filePath, bfProject);
+									mBfBuildSystem.Unlock();
+								}
+							}
+						}
+						~
+						{
+							delete projectName;
+							delete filePath;
+						});
+				}
                 else
                 else
                 {
                 {
                     Runtime.FatalError("Unknown command");
                     Runtime.FatalError("Unknown command");
@@ -10758,49 +10886,49 @@ namespace IDE
 				return;
 				return;
 			}
 			}
 
 
+			bool hasTempFiles = false;
+			WithTabs(scope [&] (tabButton) =>
+				{
+					if (var svTabButton = tabButton as SourceViewTabButton)
+					{
+						if (svTabButton.mIsTemp)
+							hasTempFiles = true;
+					}
+				});
+
+			if (hasTempFiles)
+			{
+				var dialog = ThemeFactory.mDefault.CreateDialog("Close Temp Files", 
+					"Do you want to close temporary files opened from the debugger?");
+				dialog.mDefaultButton = dialog.AddButton("Yes", new (evt) =>
+					{
+						List<SourceViewTabButton> closeTabs = scope .();
+						WithTabs(scope [&] (tabButton) =>
+							{
+								if (var svTabButton = tabButton as SourceViewTabButton)
+								{
+									if (svTabButton.mIsTemp)
+										closeTabs.Add(svTabButton);
+								}
+							});
+						for (var tab in closeTabs)
+						{
+							CloseDocument(tab.mContent);
+						}	
+					});
+				dialog.AddButton("No", new (evt) =>
+					{
+						
+					});
+				dialog.PopupWindow(GetActiveWindow());
+			}
+
 			if (mCrashDumpPath != null)
 			if (mCrashDumpPath != null)
 			{
 			{
 				DeleteAndNullify!(mCrashDumpPath);
 				DeleteAndNullify!(mCrashDumpPath);
 				mDebugger.Detach();
 				mDebugger.Detach();
 				mDebugger.mIsRunning = false;
 				mDebugger.mIsRunning = false;
 				mExecutionPaused = false;
 				mExecutionPaused = false;
-
-				bool hasTempFiles = false;
-				WithTabs(scope [&] (tabButton) =>
-					{
-						if (var svTabButton = tabButton as SourceViewTabButton)
-						{
-							if (svTabButton.mIsTemp)
-								hasTempFiles = true;
-						}
-					});
-
-				if (hasTempFiles)
-				{
-					var dialog = ThemeFactory.mDefault.CreateDialog("Close Temp Files", 
-						"Do you want to close temporary files referenced in the dump file?");
-					dialog.mDefaultButton = dialog.AddButton("Yes", new (evt) =>
-						{
-							List<SourceViewTabButton> closeTabs = scope .();
-							WithTabs(scope [&] (tabButton) =>
-								{
-									if (var svTabButton = tabButton as SourceViewTabButton)
-									{
-										if (svTabButton.mIsTemp)
-											closeTabs.Add(svTabButton);
-									}
-								});
-							for (var tab in closeTabs)
-							{
-								CloseDocument(tab.mContent);
-							}	
-						});
-					dialog.AddButton("No", new (evt) =>
-						{
-							
-						});
-					dialog.PopupWindow(GetActiveWindow());
-				}
 			}
 			}
 
 
 			if (mDebugger.mIsRunning)
 			if (mDebugger.mIsRunning)
@@ -11349,6 +11477,7 @@ namespace IDE
 			CheckDebugVisualizers();
 			CheckDebugVisualizers();
 
 
 			mDebugger.mIsRunning = true;
 			mDebugger.mIsRunning = true;
+			mDebugger.mDebugIdx++;
 			WithSourceViewPanels(scope (sourceView) =>
 			WithSourceViewPanels(scope (sourceView) =>
 				{
 				{
 					sourceView.RehupAlias();
 					sourceView.RehupAlias();
@@ -11407,6 +11536,7 @@ namespace IDE
 
 
 			CheckDebugVisualizers();
 			CheckDebugVisualizers();
 			mDebugger.mIsRunning = true;
 			mDebugger.mIsRunning = true;
+			mDebugger.mDebugIdx++;
 			mDebugger.RehupBreakpoints(true);
 			mDebugger.RehupBreakpoints(true);
 			mDebugger.Run();
 			mDebugger.Run();
 			mIsAttachPendingSourceShow = true;
 			mIsAttachPendingSourceShow = true;
@@ -11866,6 +11996,7 @@ namespace IDE
 				if (mDebugger.OpenMiniDump(mCrashDumpPath))
 				if (mDebugger.OpenMiniDump(mCrashDumpPath))
 				{
 				{
 					mDebugger.mIsRunning = true;
 					mDebugger.mIsRunning = true;
+					mDebugger.mDebugIdx++;
 					mExecutionPaused = false; // Make this false so we can detect a Pause immediately
 					mExecutionPaused = false; // Make this false so we can detect a Pause immediately
 					mIsAttachPendingSourceShow = true;
 					mIsAttachPendingSourceShow = true;
 				}
 				}
@@ -14015,6 +14146,15 @@ namespace IDE
 			if (IDEApp.sApp.mSpellChecker != null)
 			if (IDEApp.sApp.mSpellChecker != null)
 				IDEApp.sApp.mSpellChecker.CheckThreadDone();
 				IDEApp.sApp.mSpellChecker.CheckThreadDone();
 
 
+			if ((mDeferredShowSource != null) && (mBfResolveCompiler?.IsPerformingBackgroundOperation() == false))
+			{
+				var deferredShowSource = mDeferredShowSource;
+				mDeferredShowSource = null;
+				defer delete deferredShowSource;
+				ShowSourceFileLocation(deferredShowSource.mFilePath, deferredShowSource.mShowHotIdx, deferredShowSource.mRefHotIdx,
+					deferredShowSource.mLine, deferredShowSource.mColumn, deferredShowSource.mHilitePosition, deferredShowSource.mShowTemp);
+			}
+
 			///
 			///
 			//TODO: REMOVE
 			//TODO: REMOVE
 			//mDebugger.InitiateHotResolve(.ActiveMethods | .Allocations);
 			//mDebugger.InitiateHotResolve(.ActiveMethods | .Allocations);

+ 42 - 0
IDE/src/IDEUtils.bf

@@ -17,6 +17,48 @@ namespace IDE
 		public const char8 cNativeSlash = Path.DirectorySeparatorChar;
 		public const char8 cNativeSlash = Path.DirectorySeparatorChar;
 		public const char8 cOtherSlash = Path.AltDirectorySeparatorChar;        
 		public const char8 cOtherSlash = Path.AltDirectorySeparatorChar;        
 
 
+		public static bool GenericEquals(StringView lhs, StringView rhs)
+		{
+			void SkipGeneric(StringView str, ref int i)
+			{
+				int depth = 0;
+				while (i < str.Length)
+				{
+					char8 c = str[i++];
+					if (c == '<')
+						depth++;
+					if (c == '>')
+					{
+						if (--depth == 0)
+							return;
+					}
+				}
+			}
+
+			int li = 0;
+			int ri = 0;
+
+			while ((li < lhs.Length) && (ri < rhs.Length))
+			{
+				char8 lc = lhs[li];
+				char8 rc = rhs[ri];
+				if (lc != rc)
+					return false;
+
+				if (lc == '<')
+				{
+					SkipGeneric(lhs, ref li);
+					SkipGeneric(rhs, ref ri);
+					continue;
+				}
+
+				li++;
+				ri++;
+			}
+
+			return (li == lhs.Length) && (ri == rhs.Length);
+		}
+
 		public static void AppendWithOptionalQuotes(String targetStr, StringView srcFileName)
 		public static void AppendWithOptionalQuotes(String targetStr, StringView srcFileName)
 		{
 		{
 			bool hasSpace = srcFileName.Contains(' ');
 			bool hasSpace = srcFileName.Contains(' ');

+ 1 - 0
IDE/src/TestManager.bf

@@ -627,6 +627,7 @@ namespace IDE
 					gApp.mDebugger.RehupBreakpoints(true);
 					gApp.mDebugger.RehupBreakpoints(true);
 					gApp.mDebugger.Run();
 					gApp.mDebugger.Run();
 					gApp.mDebugger.mIsRunning = true;
 					gApp.mDebugger.mIsRunning = true;
+					gApp.mDebugger.mDebugIdx++;
 				}
 				}
 
 
 				mTestInstance.mThread.Start(false);
 				mTestInstance.mThread.Start(false);

+ 7 - 0
IDE/src/Workspace.bf

@@ -584,6 +584,13 @@ namespace IDE
 		{
 		{
 			if (inRelPath.IsEmpty)
 			if (inRelPath.IsEmpty)
 				return;
 				return;
+
+			if (inRelPath.StartsWith('$'))
+			{
+				outAbsPath.Append(inRelPath);
+				return;
+			}
+
 			Path.GetAbsolutePath(inRelPath, mDir, outAbsPath);
 			Path.GetAbsolutePath(inRelPath, mDir, outAbsPath);
 		}
 		}
 
 

+ 2 - 1
IDE/src/ui/ErrorsPanel.bf

@@ -75,13 +75,14 @@ namespace IDE.ui
 			mErrorLV.AddColumn(40, "Line");
 			mErrorLV.AddColumn(40, "Line");
 			mErrorLV.mOnItemMouseDown.Add(new (item, x, y, btnNum, btnCount) =>
 			mErrorLV.mOnItemMouseDown.Add(new (item, x, y, btnNum, btnCount) =>
 				{
 				{
+					ListViewItemMouseDown(item, x, y, btnNum, btnCount);
+
 					if ((btnNum == 0) && (btnCount == 2))
 					if ((btnNum == 0) && (btnCount == 2))
 					{
 					{
 						let mainItem = (ErrorsListViewItem)item.GetSubItem(0);
 						let mainItem = (ErrorsListViewItem)item.GetSubItem(0);
 						mainItem.Goto();
 						mainItem.Goto();
 					}
 					}
 
 
-					ListViewItemMouseDown(item, x, y, btnNum, btnCount);
 					//mErrorLV.GetRoot().SelectItemExclusively()
 					//mErrorLV.GetRoot().SelectItemExclusively()
 				});
 				});
 			//let newItem = mErrorLV.GetRoot().CreateChildItem();
 			//let newItem = mErrorLV.GetRoot().CreateChildItem();

+ 5 - 1
IDE/src/ui/OutputWidget.bf

@@ -206,7 +206,11 @@ namespace IDE.ui
 
 
 			if ((errLine != -1) && (errLineChar != -1) && (filePath != null))
 			if ((errLine != -1) && (errLineChar != -1) && (filePath != null))
 			{
 			{
-				if ((!filePath.Contains('\\')) && (!filePath.Contains('/')) && (!filePath.Contains('.')))
+				if (filePath.StartsWith("$Emit"))
+				{
+					// Is good
+				}
+				else if ((!filePath.Contains('\\')) && (!filePath.Contains('/')) && (!filePath.Contains('.')))
 					return false;
 					return false;
 				IDEApp.sApp.CheckProjectRelativePath(filePath);
 				IDEApp.sApp.CheckProjectRelativePath(filePath);
 
 

+ 0 - 4
IDE/src/ui/QuickFind.bf

@@ -277,8 +277,6 @@ namespace IDE.ui
 
 
         public void FindAll(bool doSelect = true)
         public void FindAll(bool doSelect = true)
         {
         {
-			Debug.WriteLine($"FindAll({doSelect})");
-
             mIsShowingMatches = true;
             mIsShowingMatches = true;
             mFoundMatches = false;
             mFoundMatches = false;
 
 
@@ -305,8 +303,6 @@ namespace IDE.ui
             }
             }
             mCurFindIdx = curFindIdx;
             mCurFindIdx = curFindIdx;
             mCurFindCount = 0;
             mCurFindCount = 0;
-
-			Debug.WriteLine($"FindAll CurFindIdx{mCurFindIdx} CurFindStart:{mCurFindStart}");
         }
         }
 
 
         public void ShowCurrentSelection()
         public void ShowCurrentSelection()

+ 43 - 13
IDE/src/ui/RenameSymbolDialog.bf

@@ -135,7 +135,7 @@ namespace IDE.ui
             mVertPos = sourceViewPanel.mEditWidget.mVertPos.mDest;
             mVertPos = sourceViewPanel.mEditWidget.mVertPos.mDest;
 
 
 			mAwaitingGetSymbolInfo = true;
 			mAwaitingGetSymbolInfo = true;
-			CheckGetSymbolInfo(kind == .ShowFileReferences);
+			CheckGetSymbolInfo((kind == .ShowFileReferences) || (kind == .GoToDefinition));
         }
         }
 
 
 
 
@@ -153,6 +153,9 @@ namespace IDE.ui
 			if (!mAwaitingGetSymbolInfo)
 			if (!mAwaitingGetSymbolInfo)
 				return true;
 				return true;
 
 
+			if (gApp.mBfResolveCompiler.IsPerformingBackgroundOperationHi())
+				return false;
+
 			if (!force)
 			if (!force)
 			{
 			{
 				if (!gApp.mBfResolveCompiler.HasResolvedAll())
 				if (!gApp.mBfResolveCompiler.HasResolvedAll())
@@ -160,7 +163,7 @@ namespace IDE.ui
 			}
 			}
 
 
 			mAwaitingGetSymbolInfo = false;
 			mAwaitingGetSymbolInfo = false;
-			mSourceViewPanel.Classify(.GetSymbolInfo);
+			mSourceViewPanel.Classify((mKind == .GoToDefinition) ? .GoToDefinition : .GetSymbolInfo);
 			mInitialized = true;
 			mInitialized = true;
 			mGettingSymbolInfo = true;
 			mGettingSymbolInfo = true;
 			return true;
 			return true;
@@ -231,9 +234,21 @@ namespace IDE.ui
 					mResolveParams.mNamespace = new String(lineDataItr.GetNext().Get());
 					mResolveParams.mNamespace = new String(lineDataItr.GetNext().Get());
 					foundSymbol = true;
 					foundSymbol = true;
 				case "defLoc":
 				case "defLoc":
+					StringView filePath = lineDataItr.GetNext().Get();
+					int32 line = int32.Parse(lineDataItr.GetNext().Value);
+					int32 lineChar = int32.Parse(lineDataItr.GetNext().Value);
+
+					if (mKind == .GoToDefinition)
+					{
+					    mSourceViewPanel.RecordHistoryLocation();
+					    var sourceViewPanel = gApp.ShowSourceFileLocation(scope .(filePath), -1, -1, line, lineChar, LocatorType.Smart, true);
+					    sourceViewPanel.RecordHistoryLocation(true);
+						Close();
+						return;
+					}
+
 					if (mKind == .Rename)
 					if (mKind == .Rename)
 					{
 					{
-						StringView filePath = lineDataItr.GetNext().Get();
 						let editData = gApp.GetEditData(scope String(filePath), false, false);
 						let editData = gApp.GetEditData(scope String(filePath), false, false);
 						if (editData != null)
 						if (editData != null)
 						{
 						{
@@ -260,6 +275,12 @@ namespace IDE.ui
 				}
 				}
             }
             }
 
 
+			if (mKind == .GoToDefinition)
+			{
+				gApp.Fail("Unable to locate definition");
+				Close();
+			}
+
             if ((!foundSymbol) || (foundStr == null))
             if ((!foundSymbol) || (foundStr == null))
             {
             {
                 if ((mKind == .Rename) || (mKind == .FindAllReferences))
                 if ((mKind == .Rename) || (mKind == .FindAllReferences))
@@ -829,13 +850,22 @@ namespace IDE.ui
         {
         {
             base.Update();
             base.Update();
 
 
+			if ((mUpdatingProjectSources == null) && (mUpdateCnt > 30) && (gApp.mUpdateCnt % 4 == 0))
+				MarkDirty();
+
+			if (mAwaitingGetSymbolInfo)
+			{
+				if (!CheckGetSymbolInfo(false))
+					return;
+			}
+
 			if (mKind == .GoToDefinition)
 			if (mKind == .GoToDefinition)
 			{
 			{
-				if (gApp.mBfResolveCompiler.HasResolvedAll())
+				/*if (gApp.mBfResolveCompiler.HasResolvedAll())
 				{
 				{
 					Close();
 					Close();
 					gApp.GoToDefinition(true);
 					gApp.GoToDefinition(true);
-				}
+				}*/
 
 
 				if (mSourceViewPanel.EditWidget.Content.CursorTextPos != mCursorPos)
 				if (mSourceViewPanel.EditWidget.Content.CursorTextPos != mCursorPos)
 				{
 				{
@@ -845,12 +875,6 @@ namespace IDE.ui
 				return;
 				return;
 			}
 			}
 
 
-			if (mAwaitingGetSymbolInfo)
-			{
-				if (!CheckGetSymbolInfo(false))
-					return;
-			}
-
 			if (mStartingWork)
 			if (mStartingWork)
 				return;
 				return;
 
 
@@ -899,7 +923,7 @@ namespace IDE.ui
 
 
 			mClosed = true;
 			mClosed = true;
 
 
-			mSourceViewPanel.CancelResolve(.GetSymbolInfo);
+			mSourceViewPanel.CancelResolve((mKind == .GoToDefinition) ? .GoToDefinition : .GetSymbolInfo);
 			if (mBackgroundKind != .None)
 			if (mBackgroundKind != .None)
 			{
 			{
 				gApp.mBfResolveCompiler.CancelBackground();
 				gApp.mBfResolveCompiler.CancelBackground();
@@ -921,6 +945,12 @@ namespace IDE.ui
             if (mKind == Kind.ShowFileReferences)
             if (mKind == Kind.ShowFileReferences)
                 return;
                 return;
 
 
+			if ((mKind == .GoToDefinition) && (mUpdateCnt < 40))
+			{
+				// Reduce "flashing" for very fast finds
+				return;
+			}
+
 			int symCount = 0;
 			int symCount = 0;
 			int readOnlyRefCount = 0;
 			int readOnlyRefCount = 0;
 			int lockedFileCount = 0;
 			int lockedFileCount = 0;
@@ -993,7 +1023,7 @@ namespace IDE.ui
                 }
                 }
             }
             }
 
 
-            if ((mUpdatingProjectSources == null) && (mUpdateCnt > 30))            
+            if ((mUpdatingProjectSources == null) && (mUpdateCnt > 30))
                 IDEUtils.DrawWait(g, mWidth / 2, mHeight / 2 + 4, mUpdateCnt);
                 IDEUtils.DrawWait(g, mWidth / 2, mHeight / 2 + 4, mUpdateCnt);
         }
         }
 
 

+ 651 - 30
IDE/src/ui/SourceEditWidgetContent.bf

@@ -13,6 +13,7 @@ using Beefy.utils;
 using IDE.Debugger;
 using IDE.Debugger;
 using IDE.Compiler;
 using IDE.Compiler;
 using Beefy.geom;
 using Beefy.geom;
+using Beefy.events;
 
 
 namespace IDE.ui
 namespace IDE.ui
 {    
 {    
@@ -180,19 +181,393 @@ namespace IDE.ui
 			}
 			}
 		}
 		}
 
 
+		public class EmitEmbed : DarkEditWidgetContent.Embed
+		{
+			public class View : Widget
+			{
+				public class GenericTypeEntry
+				{
+					public String mTypeName ~ delete _;
+				}
+
+				public enum WorkState
+				{
+					Idle,
+					Queued,
+					Performing,
+					Done
+				}
+
+				public EmitEmbed mEmitEmbed;
+				public String mTypeName ~ delete _;
+				public SourceViewPanel mSourceViewPanel;
+				public DarkComboBox mGenericTypeCombo;
+				public DarkComboBox mGenericMethodCombo;
+				public String mGenericTypeFilter;
+				public float mWantHeight;
+				public float? mMouseDownY;
+				public float? mDownWantHeight;
+
+				public float MinHeight => (mGenericTypeCombo != null) ? GS!(96+25) : GS!(96);
+				public float MaxAutoHeight => GS!(364);
+				public float HeightAdd => (mGenericTypeCombo != null) ? GS!(28+25) : GS!(28);
+
+				public int32 mCollapseParseRevision;
+				public List<GenericTypeEntry> mGenericTypeData = new .() ~ DeleteContainerAndItems!(_);
+				public Monitor mMonitor = new .() ~ delete _;
+				public WorkState mTypeWorkState;
+				public bool mAwaitingLoad;
+				bool mIgnoreChange = false;
+
+				public this(EmitEmbed emitEmbed)
+				{
+					mTypeName = new .(emitEmbed.mTypeName);
+					mEmitEmbed = emitEmbed;
+					mSourceViewPanel = new SourceViewPanel((emitEmbed.mEmitKind == .Method) ? .Method : .Type);
+					mSourceViewPanel.mEmbedParent = mEmitEmbed.mEditWidgetContent.mSourceViewPanel;
+					var emitPath = scope $"$Emit${emitEmbed.mTypeName}";
+
+					mSourceViewPanel.Show(emitPath, false, null);
+					mSourceViewPanel.mEditWidget.mEditWidgetContent.mIsReadOnly = true;
+					mSourceViewPanel.mEmitRevision = emitEmbed.mRevision;
+					AddWidget(mSourceViewPanel);
+
+					mSourceViewPanel.mEditWidget.mOnGotFocus.Add(new (val1) =>
+						{
+							if (mGenericTypeCombo != null)
+								UpdateGenericTypeCombo();
+						});
+
+					mSourceViewPanel.mEditWidget.mHorzScrollbar.mAllowMouseWheel = false;
+					mSourceViewPanel.mEditWidget.mVertScrollbar.mAllowMouseWheel = false;
+
+					var sewc = mSourceViewPanel.mEditWidget.mEditWidgetContent as SourceEditWidgetContent;
+					sewc.mLineRange = Range(emitEmbed.mStartLine, emitEmbed.mEndLine);
+					sewc.mAllowMaximalScroll = false;
+					mSourceViewPanel.mEditWidget.UpdateScrollbars();
+
+					mClipGfx = true;
+
+					if (mTypeName.Contains('<'))
+					{
+						mGenericTypeCombo = new DarkComboBox();
+						mGenericTypeCombo.mFocusDropdown = false;
+						mGenericTypeCombo.mLabelAlign = .Left;
+						mGenericTypeCombo.MakeEditable();
+						UpdateGenericTypeCombo();
+						mGenericTypeCombo.mPopulateMenuAction.Add(new => PopulateTypeData);
+						AddWidget(mGenericTypeCombo);
+
+						mGenericTypeCombo.mEditWidget.mOnContentChanged.Add(new => GenericTypeEditChanged);
+						mGenericTypeCombo.mEditWidget.mOnKeyDown.Add(new => EditKeyDownHandler);
+						mGenericTypeCombo.mEditWidget.mOnGotFocus.Add(new (widget) => mGenericTypeCombo.mEditWidget.mEditWidgetContent.SelectAll());
+					}
+				}
+
+				private void GenericTypeEditChanged(EditEvent theEvent)
+				{
+					if (mIgnoreChange)
+						return;
+
+				    var editWidget = (EditWidget)theEvent.mSender;
+				    var searchText = scope String();
+				    editWidget.GetText(searchText);
+					searchText.Trim();
+
+				    mGenericTypeFilter = searchText;
+				    mGenericTypeCombo.ShowDropdown();
+				    mGenericTypeFilter = null;
+				}
+
+				void EditKeyDownHandler(KeyDownEvent evt)
+				{
+				    if (evt.mKeyCode == KeyCode.Escape)
+				        mEmitEmbed.mEditWidgetContent.mSourceViewPanel.FocusEdit();
+				}
+
+				void UpdateGenericTypeCombo()
+				{
+					var typeName = mEmitEmbed.mTypeName;
+					for (var explicitTypeName in mEmitEmbed.mEditWidgetContent.mSourceViewPanel.[Friend]mExplicitEmitTypes)
+					{
+						if (IDEUtils.GenericEquals(typeName, explicitTypeName))
+							typeName = explicitTypeName;
+					}
+
+					mIgnoreChange = true;
+					int colonPos = typeName.IndexOf(':');
+					if (colonPos != -1)
+						mGenericTypeCombo.Label = typeName.Substring(colonPos + 1);
+					else
+						mGenericTypeCombo.Label = typeName;
+					mIgnoreChange = false;
+				}
+
+				void PopulateTypeData(Menu menu)
+				{
+					List<StringView> findStrs = null;
+					if (mGenericTypeFilter != null)
+					 	findStrs = scope:: List<StringView>(mGenericTypeFilter.Split(' '));
+
+					using (mMonitor.Enter())
+					{
+						EntryLoop: for (var entry in mGenericTypeData)
+						{
+							StringView useName = entry.mTypeName;
+							int colonPos = useName.IndexOf(':');
+							if (colonPos != -1)
+								useName.RemoveFromStart(colonPos + 1);
+
+							if (findStrs != null)
+							{
+								for (let findStr in findStrs)
+								{
+								    if (useName.IndexOf(findStr, true) == -1)
+								        continue EntryLoop;
+								}
+							}
+
+							var item = menu.AddItem(useName);
+
+							var origName = new String(entry.mTypeName);
+							item.mOnMenuItemSelected.Add(new (menu) =>
+								{
+									mEmitEmbed.mEditWidgetContent.mSourceViewPanel.AddExplicitEmitType(origName);
+									mEmitEmbed.mEditWidgetContent.mSourceViewPanel.QueueFullRefresh(false);
+									UpdateGenericTypeCombo();
+									mGenericTypeCombo.mEditWidget.SetFocus();
+								}
+								~
+								{
+									delete origName;
+								});
+						}
+					}
+					
+					if ((mTypeWorkState == .Idle) && (mCollapseParseRevision != mEmitEmbed.mEditWidgetContent.mCollapseParseRevision))
+					{
+						mCollapseParseRevision = mEmitEmbed.mEditWidgetContent.mCollapseParseRevision;
+						mTypeWorkState = .Queued;
+					}
+
+					/*menu.AddItem("Abc");
+					menu.AddItem("Def");*/
+				}
+
+				public override void Update()
+				{
+					base.Update();
+
+					using (mMonitor.Enter())
+					{
+						if ((mTypeWorkState == .Queued) && (gApp?.mBfResolveCompiler.IsPerformingBackgroundOperation() == false))
+						{
+							mTypeWorkState = .Performing;
+							gApp.mBfResolveCompiler.DoBackground(new => GetGenericTypes);
+						}
+
+						if (mTypeWorkState == .Done)
+						{
+							mGenericTypeCombo.ShowDropdown();
+							mGenericTypeCombo.SelectFromLabel();
+							mTypeWorkState = .Idle;
+						}
+					}
+
+					mAwaitingLoad = false;
+					for (var explicitTypeName in mEmitEmbed.mEditWidgetContent.mSourceViewPanel.[Friend]mExplicitEmitTypes)
+					{
+						if ((IDEUtils.GenericEquals(mTypeName, explicitTypeName)) && (mTypeName != explicitTypeName))
+							mAwaitingLoad = true;
+					}
+
+					if (mSourceViewPanel.mEditWidget.mEditWidgetContent.mData.mTextLength == 0)
+						mAwaitingLoad = true;
+
+					if ((mAwaitingLoad) && (gApp.mUpdateCnt % 4 == 0))
+						MarkDirty();
+				}
+
+				public void GetGenericTypes()
+				{
+					gApp.mBfResolveSystem.Lock(0);
+					var genericTypeNames = gApp.mBfResolveCompiler.GetGenericTypeInstances(mTypeName, .. scope .());
+					gApp.mBfResolveSystem.Unlock();
+
+					using (mMonitor.Enter())
+					{
+						mGenericTypeData.ClearAndDeleteItems();
+						mTypeWorkState = .Done;
+
+						for (var genericTypeName in genericTypeNames.Split('\n', .RemoveEmptyEntries))
+						{
+							GenericTypeEntry entry = new .();
+							entry.mTypeName = new .(genericTypeName);
+							mGenericTypeData.Add(entry);
+							mGenericTypeData.Sort(scope (lhs, rhs) => lhs.mTypeName <=> rhs.mTypeName);
+						}
+					}
+				}
+
+				public override void DrawAll(Graphics g)
+				{
+					base.DrawAll(g);
+
+					if (mAwaitingLoad)
+					{
+						var rect = mSourceViewPanel.mEditWidget.GetRect();
+						mSourceViewPanel.mEditWidget.SelfToOtherTranslate(this, 0, 0, out rect.mX, out rect.mY);
+
+						using (g.PushColor(Color.Mult(gApp.mSettings.mUISettings.mColors.mWindow, 0x60FFFFFF)))
+						{
+							g.FillRect(rect.mX, rect.mY, rect.mWidth, rect.mHeight);
+						}
+						IDEUtils.DrawWait(g, rect.mX + rect.mWidth / 2, rect.mY + rect.mHeight / 2, mUpdateCnt);
+					}
+				}
+
+				public override void Resize(float x, float y, float width, float height)
+				{
+					base.Resize(x, y, width, height);
+
+					float curY = GS!(2);
+					if (mGenericTypeCombo != null)
+					{
+						mGenericTypeCombo.Resize(GS!(38), curY, Math.Max(0, width - GS!(38)), GS!(22));
+						curY += GS!(25);
+					}
+
+					mSourceViewPanel.Resize(0, curY, width, Math.Max(0, height - curY - GS!(7)));
+				}
+
+				public void SizeTo(float x, float y, float width, float height)
+				{
+					Resize(x, y, width, height + GS!(3));
+				}
+
+				public override void RehupScale(float oldScale, float newScale)
+				{
+					base.RehupScale(oldScale, newScale);
+					mWantHeight = mWantHeight * newScale / oldScale;
+				}
+
+				public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
+				{
+					base.MouseDown(x, y, btn, btnCount);
+					if (btn == 0)
+					{
+						mMouseDownY = y;
+						mDownWantHeight = mWantHeight;
+					}
+				}
+
+				public override void MouseUp(float x, float y, int32 btn)
+				{
+					base.MouseUp(x, y, btn);
+					if (btn == 0)
+					{
+						mMouseDownY = null;
+						mDownWantHeight = null;
+					}
+				}
+
+				public override void MouseMove(float x, float y)
+				{
+					base.MouseMove(x, y);
+
+					if (mMouseDownY != null)
+					{
+						mWantHeight = Math.Max(MinHeight, mDownWantHeight.Value + y - mMouseDownY.Value);
+						mEmitEmbed.mEditWidgetContent.RehupLineCoords();
+					}
+
+					if (y > mHeight - GS!(6))
+						gApp.SetCursor(.SizeNS);
+				}
+
+				public override void MouseLeave()
+				{
+					base.MouseLeave();
+					gApp.SetCursor(.Pointer);
+				}
+			}
+
+			public SourceEditWidgetContent mEditWidgetContent;
+			public SourceEditWidgetContent.CollapseData.Kind mEmitKind;
+			public String mTypeName;
+			public bool mIsOpen;
+			public float mOpenPct;
+			public int32 mAnchorId;
+			public int32 mCollapseIndex;
+			public int32 mRevision;
+			public int32 mPartialIdx;
+			public int32 mStartLine;
+			public int32 mEndLine;
+			public View mView;
+
+			public ~this()
+			{
+				if (mView != null)
+				{
+					mView.RemoveSelf();
+					delete mView;
+				}
+			}
+
+			public override float GetWidth(bool hideLine)
+			{
+				return GS!(42);
+			}
+
+			public override void Draw(Graphics g, Rect rect, bool hideLine)
+			{
+				if (rect.mHeight >= DarkTheme.sDarkTheme.mSmallBoldFont.GetLineSpacing())
+					g.SetFont(DarkTheme.sDarkTheme.mSmallBoldFont);
+
+				using (g.PushColor(0x20FFFFFF))
+				{
+					g.FillRect(rect.mX, rect.mY, rect.mWidth, rect.mHeight);
+				}
+
+				if ((mEditWidgetContent.mSelection != null) && (mCollapseIndex < mEditWidgetContent.mOrderedCollapseEntries.Count))
+				{
+					var collapseEntry = mEditWidgetContent.mOrderedCollapseEntries[mCollapseIndex];
+					int32 startIdx = mEditWidgetContent.mData.mLineStarts[collapseEntry.mStartLine];
+					if ((mEditWidgetContent.mSelection.Value.MinPos <= collapseEntry.mEndIdx) && (mEditWidgetContent.mSelection.Value.MaxPos >= startIdx))
+					{
+						using (g.PushColor(mEditWidgetContent.GetSelectionColor(0)))
+							g.FillRect(rect.mX, rect.mY, rect.mWidth, rect.mHeight);
+					}
+				}
+
+				using (g.PushColor(0x48FFFFFF))
+				{
+					g.OutlineRect(rect.mX, rect.mY, rect.mWidth, rect.mHeight);
+				}
+
+				var summaryString = "Emit";
+				g.DrawString(summaryString, rect.mX, rect.mY + (int)((rect.mHeight - g.mFont.GetLineSpacing()) * 0.5f), .Centered, rect.mWidth);
+			}
+		}
+
 		public struct CollapseData
 		public struct CollapseData
 		{
 		{
 			public enum Kind : char8
 			public enum Kind : char8
 			{
 			{
-				Zero = 0,
-				Comment = 'C',
-				Method = 'M',
-				Namespace = 'N',
-				Property = 'P',
-				Region = 'R',
-				Type = 'T',
-				UsingNamespaces = 'U',
-				Unknown = '?'
+				case Zero = 0;
+				case Comment = 'C';
+				case Method = 'M';
+				case Namespace = 'N';
+				case Property = 'P';
+				case Region = 'R';
+				case Type = 'T';
+				case UsingNamespaces = 'U';
+				case Unknown = '?';
+				case EmitInType = 't';
+				case EmitInMethod = 'm';
+				case EmitAddType = '+';
+
+				public bool IsEmit => (this == .EmitInType) || (this == .EmitInMethod);
 			}
 			}
 
 
 			public Kind mKind;
 			public Kind mKind;
@@ -218,6 +593,19 @@ namespace IDE.ui
 			public bool mDeleted;
 			public bool mDeleted;
 		}
 		}
 
 
+		public struct EmitData
+		{
+			public SourceEditWidgetContent.CollapseEntry.Kind mKind;
+			public int32 mTypeNameIdx;
+			public int32 mRevision;
+			public int32 mPartialIdx;
+			public int32 mAnchorIdx;
+			public int32 mStartLine;
+			public int32 mEndLine;
+
+			public int32 mAnchorId;
+		}
+
 		public class Data : DarkEditWidgetContent.Data
 		public class Data : DarkEditWidgetContent.Data
 		{
 		{
 			public List<PersistentTextPosition> mPersistentTextPositions = new List<PersistentTextPosition>() ~ DeleteContainerAndItems!(_);
 			public List<PersistentTextPosition> mPersistentTextPositions = new List<PersistentTextPosition>() ~ DeleteContainerAndItems!(_);
@@ -225,6 +613,19 @@ namespace IDE.ui
 			public int32 mCollapseParseRevision;
 			public int32 mCollapseParseRevision;
 			public int32 mCollapseTextVersionId;
 			public int32 mCollapseTextVersionId;
 			public List<CollapseData> mCollapseData = new .() ~ delete _;
 			public List<CollapseData> mCollapseData = new .() ~ delete _;
+			public List<EmitData> mEmitData = new .() ~ delete _;
+			public List<String> mTypeNames = new .() ~ DeleteContainerAndItems!(_);
+
+			public void Clear()
+			{
+				mCollapseData.Clear();
+				mEmitData.Clear();
+				ClearAndDeleteItems(mTypeNames);
+			}
+
+			public ~this()
+			{
+			}
 		}
 		}
 
 
 		struct QueuedTextEntry
 		struct QueuedTextEntry
@@ -327,6 +728,7 @@ namespace IDE.ui
 		HilitePairedCharState mHilitePairedCharState = .NeedToRecalculate;
 		HilitePairedCharState mHilitePairedCharState = .NeedToRecalculate;
 		public Dictionary<int32, CollapseEntry> mCollapseMap = new .() ~ delete _;
 		public Dictionary<int32, CollapseEntry> mCollapseMap = new .() ~ delete _;
 		public List<CollapseEntry*> mOrderedCollapseEntries = new .() ~ delete _;
 		public List<CollapseEntry*> mOrderedCollapseEntries = new .() ~ delete _;
+		public List<String> mCollapseTypeNames = new .() ~ DeleteContainerAndItems!(_);
 		public int32 mCollapseParseRevision;
 		public int32 mCollapseParseRevision;
 		public int32 mCollapseTextVersionId;
 		public int32 mCollapseTextVersionId;
 		public bool mCollapseNeedsUpdate;
 		public bool mCollapseNeedsUpdate;
@@ -421,6 +823,12 @@ namespace IDE.ui
 		    String curText = scope String();
 		    String curText = scope String();
 		    mEditWidget.GetText(curText);
 		    mEditWidget.GetText(curText);
 
 
+			if (curText == text)
+			{
+				// No change
+				return true;
+			}
+
 		    char8* diffCmdsPtr = BfDiff_DiffText(curText, text);
 		    char8* diffCmdsPtr = BfDiff_DiffText(curText, text);
 		    String diffCmds = scope String();
 		    String diffCmds = scope String();
 			diffCmds.Append(diffCmdsPtr);
 			diffCmds.Append(diffCmdsPtr);
@@ -4538,15 +4946,20 @@ namespace IDE.ui
 		public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
 		public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
 		{
 		{
 			int line = GetLineAt(y);
 			int line = GetLineAt(y);
-			if (mEmbeds.GetValue(line) case .Ok(let embed))
+			if (mEmbeds.GetValue((.)line) case .Ok(let embed))
 			{
 			{
 				Rect embedRect = GetEmbedRect(line, embed);
 				Rect embedRect = GetEmbedRect(line, embed);
 				if (embedRect.Contains(x, y))
 				if (embedRect.Contains(x, y))
 				{
 				{
-					if ((btn == 0) && (btnCount == 2))
+					if ((btn == 0) && (btnCount % 2 == 0))
 					{
 					{
 						if (var collapseSummary = embed as SourceEditWidgetContent.CollapseSummary)
 						if (var collapseSummary = embed as SourceEditWidgetContent.CollapseSummary)
 							SetCollapseOpen(collapseSummary.mCollapseIndex, true);
 							SetCollapseOpen(collapseSummary.mCollapseIndex, true);
+						else if (var emitEmbed = embed as EmitEmbed)
+						{
+							emitEmbed.mIsOpen = !emitEmbed.mIsOpen;
+							mCollapseNeedsUpdate = true;
+						}
 					}
 					}
 					return;
 					return;
 				}
 				}
@@ -5047,10 +5460,23 @@ namespace IDE.ui
 			if (mLineCoordJumpTable == null)
 			if (mLineCoordJumpTable == null)
 				mLineCoordJumpTable = new .();
 				mLineCoordJumpTable = new .();
 
 
+			if (data.mLineStarts == null)
+				return;
+
 			mLineCoords.Clear();
 			mLineCoords.Clear();
 			mLineCoords.GrowUnitialized(data.mLineStarts.Count);
 			mLineCoords.GrowUnitialized(data.mLineStarts.Count);
 			mLineCoordJumpTable.Clear();
 			mLineCoordJumpTable.Clear();
 
 
+			List<(int32 line, EmitEmbed emitEmbed)> orderedEmitEmbeds = scope .();
+			for (var entry in mEmbeds)
+			{
+				if (var emitEmbed = entry.value as EmitEmbed)
+				{
+					orderedEmitEmbeds.Add((entry.key, emitEmbed));
+				}
+			}
+			orderedEmitEmbeds.Sort(scope (lhs, rhs) => lhs.line <=> rhs.line);
+			
 			float fontHeight = mFont.GetLineSpacing();
 			float fontHeight = mFont.GetLineSpacing();
 			int prevJumpIdx = -1;
 			int prevJumpIdx = -1;
 			float jumpCoordSpacing = GetJumpCoordSpacing();
 			float jumpCoordSpacing = GetJumpCoordSpacing();
@@ -5067,6 +5493,7 @@ namespace IDE.ui
 			int32 curAnimLineIdx = 0;
 			int32 curAnimLineIdx = 0;
 			bool inAnim = false;
 			bool inAnim = false;
 			int checkOpenIdx = 0;
 			int checkOpenIdx = 0;
+			int orderedEmebedIdx = 0;
 
 
 			for (int line < data.mLineStarts.Count)
 			for (int line < data.mLineStarts.Count)
 			{
 			{
@@ -5129,6 +5556,28 @@ namespace IDE.ui
 						lineHeight = 0;
 						lineHeight = 0;
 				}
 				}
 
 
+				if ((orderedEmebedIdx < orderedEmitEmbeds.Count) && (line == orderedEmitEmbeds[orderedEmebedIdx].line))
+				{
+					var emitEmbed = orderedEmitEmbeds[orderedEmebedIdx++].emitEmbed;
+					if (lineHeight == 0)
+					{
+						if (emitEmbed.mView != null)
+							emitEmbed.mView.SetVisible(false);
+					}
+					else if (emitEmbed.mView != null)
+					{
+						if (emitEmbed.mView.mWantHeight == 0)
+						{
+							emitEmbed.mView.mWantHeight = Math.Clamp((emitEmbed.mEndLine - emitEmbed.mStartLine) * gApp.mCodeFont.GetLineSpacing() + emitEmbed.mView.HeightAdd,
+								emitEmbed.mView.MinHeight, emitEmbed.mView.MaxAutoHeight);
+						}
+
+						float height = emitEmbed.mView.mWantHeight * emitEmbed.mOpenPct;
+						emitEmbed.mView.SizeTo(GS!(0), (float)curY + lineHeight, mParent.mWidth, height);
+						lineHeight += height;
+					}
+				}
+
 				mLineCoords[line] = (float)curY;
 				mLineCoords[line] = (float)curY;
 
 
 				int jumpIdx = (.)(curY / jumpCoordSpacing);
 				int jumpIdx = (.)(curY / jumpCoordSpacing);
@@ -5200,13 +5649,88 @@ namespace IDE.ui
 			{
 			{
 				mCollapseParseRevision = data.mCollapseParseRevision;
 				mCollapseParseRevision = data.mCollapseParseRevision;
 				mCollapseTextVersionId = data.mCollapseTextVersionId;
 				mCollapseTextVersionId = data.mCollapseTextVersionId;
+				mCollapseTypeNames.ClearAndDeleteItems();
+				for (var name in data.mTypeNames)
+					mCollapseTypeNames.Add(new .(name));
+
+				Dictionary<int, EmitEmbed> emitEmbedMap = scope .(64);
+				for (var embed in mEmbeds.Values)
+				{
+					if (var emitEmbed = embed as SourceEditWidgetContent.EmitEmbed)
+					{
+						emitEmbedMap[emitEmbed.mAnchorId] = emitEmbed;
+					}
+				}
+
+				for (var emitData in ref data.mEmitData)
+				{
+					GetLineCharAtIdx(emitData.mAnchorIdx, var line, var lineChar);
+
+					SourceEditWidgetContent.EmitEmbed emitEmbed = null;
+					if (emitEmbedMap.GetAndRemove(emitData.mAnchorId) case .Ok((?, out emitEmbed)))
+					{
+						if (line != emitEmbed.mLine)
+						{
+						   	mEmbeds.Remove(emitEmbed.mLine);
+							emitEmbed.mLine = (.)line;
+							mEmbeds[(.)line] = emitEmbed;
+						}
+					}
+					else if (mEmbeds.TryAdd((.)line, var keyPtr, var valuePtr))
+					{
+						emitEmbed = new .();
+						*valuePtr = emitEmbed;
+					}
+					else 
+					{
+						emitEmbed = *valuePtr as SourceEditWidgetContent.EmitEmbed;
+					}
+
+					if (emitEmbed == null)
+						continue;
+
+					emitEmbed.mLine = (.)line;
+					emitEmbed.mAnchorId = emitData.mAnchorId;
+					emitEmbed.mEmitKind = emitData.mKind;
+					emitEmbed.mTypeName = mCollapseTypeNames[emitData.mTypeNameIdx];
+					emitEmbed.mRevision = emitData.mRevision;
+					emitEmbed.mPartialIdx = emitData.mPartialIdx;
+
+					if (emitEmbed.mView != null)
+					{
+						Range range = .(emitData.mStartLine, emitData.mEndLine);
+						var ew = emitEmbed.mView.mSourceViewPanel.mEditWidget;
+						var ewc = ew.mEditWidgetContent as DarkEditWidgetContent;
+						if (ewc.mLineRange != range)
+						{
+							ewc.mLineRange = range;
+							ew.UpdateScrollbars();
+						}
+					}
+
+					emitEmbed.mStartLine = emitData.mStartLine;
+					emitEmbed.mEndLine = emitData.mEndLine;
+					emitEmbed.mEditWidgetContent = this;
+					emitEmbed.mCollapseIndex = (.)emitData.mAnchorIdx;
+					emitEmbed.mKind = .LineEnd;
+				}
+
+				for (var emitEmbed in emitEmbedMap.Values)
+				{
+					mCollapseNeedsUpdate = true;
+					mEmbeds.Remove(emitEmbed.mLine);
+					delete emitEmbed;
+				}
 
 
 				for (var collapseData in ref data.mCollapseData)
 				for (var collapseData in ref data.mCollapseData)
 				{
 				{
 					if (mCollapseMap.TryAdd(collapseData.mAnchorId, ?, var entry))
 					if (mCollapseMap.TryAdd(collapseData.mAnchorId, ?, var entry))
+					{
 						*entry = .();
 						*entry = .();
+					}
+					int32 prevAnchorLine = entry.mAnchorLine;
 					Internal.MemCpy(entry, &collapseData, sizeof(CollapseData));
 					Internal.MemCpy(entry, &collapseData, sizeof(CollapseData));
-					entry.mPrevAnchorLine = entry.mAnchorLine;
+					entry.mPrevAnchorLine = prevAnchorLine;
 					entry.mParseRevision = mCollapseParseRevision;
 					entry.mParseRevision = mCollapseParseRevision;
 					entry.mDeleted = false;
 					entry.mDeleted = false;
 				}
 				}
@@ -5216,7 +5740,10 @@ namespace IDE.ui
 					if (entry.mParseRevision != data.mCollapseParseRevision)
 					if (entry.mParseRevision != data.mCollapseParseRevision)
 					{
 					{
 						if (mEmbeds.GetAndRemove(entry.mAnchorLine) case .Ok(let val))
 						if (mEmbeds.GetAndRemove(entry.mAnchorLine) case .Ok(let val))
-							delete val.value;
+						{
+							if (val.value is CollapseSummary)
+								delete val.value;
+						}
 						@entry.Remove();
 						@entry.Remove();
 					}
 					}
 				}
 				}
@@ -5236,23 +5763,31 @@ namespace IDE.ui
 					if (entry.mDeleted)
 					if (entry.mDeleted)
 					{
 					{
 						if (mEmbeds.GetAndRemove(entry.mAnchorIdx) case .Ok(let val))
 						if (mEmbeds.GetAndRemove(entry.mAnchorIdx) case .Ok(let val))
-							delete val.value;
+						{
+							if (val.value is CollapseSummary)
+								delete val.value;
+						}
 						continue;
 						continue;
 					}
 					}
 
 
 					if ((entry.mPrevAnchorLine != -1) && (entry.mPrevAnchorLine != entry.mAnchorLine))
 					if ((entry.mPrevAnchorLine != -1) && (entry.mPrevAnchorLine != entry.mAnchorLine))
 					{
 					{
-						if (mEmbeds.GetAndRemove(entry.mPrevAnchorLine) case .Ok(let val))
+						if (!mEmbeds.TryGetValue(entry.mPrevAnchorLine, let val))
+							continue;
+
+						if (!(val is CollapseSummary))
+							continue;
+						mEmbeds.Remove(entry.mPrevAnchorLine);
+					
+						if (mEmbeds.TryAdd(entry.mAnchorLine, var keyPtr, var valuePtr))
 						{
 						{
-							if (!mEmbeds.TryAdd(entry.mAnchorLine, var keyPtr, var valuePtr))
-							{
-								if (var collapseSummary = val.value as SourceEditWidgetContent.CollapseSummary)
-									collapseSummary.mCollapseIndex = (.)@entry.Index;
-								*valuePtr = val.value;
-							}
-							else
-								delete val.value;
-						}	
+							if (var collapseSummary = val as SourceEditWidgetContent.CollapseSummary)
+								collapseSummary.mCollapseIndex = (.)@entry.Index;
+							val.mLine = entry.mAnchorLine;
+							*valuePtr = val;
+						}
+						else
+							delete val;
 					}
 					}
 				}
 				}
 
 
@@ -5432,6 +5967,20 @@ namespace IDE.ui
 			}
 			}
         }
         }
 
 
+		public override void Resize(float x, float y, float width, float height)
+		{
+			base.Resize(x, y, width, height);
+
+			for (var embed in mEmbeds.Values)
+			{
+				if (var emitEmbed = embed as EmitEmbed)
+				{
+					if (emitEmbed.mView != null)
+						emitEmbed.mView.Resize(emitEmbed.mView.mX, emitEmbed.mView.mY, mParent.mWidth - emitEmbed.mView.mX, emitEmbed.mView.mHeight);
+				}
+			}
+		}
+
 		public void CollapseToggle()
 		public void CollapseToggle()
 		{
 		{
 			CollapseEntry* foundEntry = null;
 			CollapseEntry* foundEntry = null;
@@ -5560,10 +6109,13 @@ namespace IDE.ui
 			{
 			{
 				if (mEmbeds.GetValue(entry.mAnchorLine) case .Ok(let embed))
 				if (mEmbeds.GetValue(entry.mAnchorLine) case .Ok(let embed))
 				{
 				{
-					if ((embed.mKind == .HideLine) || (embed.mKind == .LineEnd))
+					if (embed is CollapseSummary)
 					{
 					{
-						delete embed;
-						mEmbeds.Remove(entry.mAnchorLine);
+						if ((embed.mKind == .HideLine) || (embed.mKind == .LineEnd))
+						{
+							delete embed;
+							mEmbeds.Remove(entry.mAnchorLine);
+						}
 					}
 					}
 				}
 				}
 			}
 			}
@@ -5591,6 +6143,7 @@ namespace IDE.ui
 			}
 			}
 		}
 		}
 
 
+
 		public void RefreshCollapseRegion(SourceEditWidgetContent.CollapseEntry* entry, int32 prevAnchorLine, bool failed)
 		public void RefreshCollapseRegion(SourceEditWidgetContent.CollapseEntry* entry, int32 prevAnchorLine, bool failed)
 		{
 		{
 			if (failed)
 			if (failed)
@@ -5605,7 +6158,10 @@ namespace IDE.ui
 				if (mEmbeds.GetAndRemove(prevAnchorLine) case .Ok(let val))
 				if (mEmbeds.GetAndRemove(prevAnchorLine) case .Ok(let val))
 				{
 				{
 					if (mEmbeds.TryAdd(entry.mAnchorLine, var keyPtr, var valuePtr))
 					if (mEmbeds.TryAdd(entry.mAnchorLine, var keyPtr, var valuePtr))
+					{
+						val.value.mLine = entry.mAnchorLine;
 						*valuePtr = val.value;
 						*valuePtr = val.value;
+					}
 					else
 					else
 						delete val.value;
 						delete val.value;
 				}
 				}
@@ -5685,14 +6241,34 @@ namespace IDE.ui
 
 
 			var data = PreparedData;
 			var data = PreparedData;
 
 
-			data.mCollapseData.Clear();
+			data.Clear();
 
 
 			for (var line in collapseText.Split('\n', .RemoveEmptyEntries))
 			for (var line in collapseText.Split('\n', .RemoveEmptyEntries))
 			{
 			{
 				SourceEditWidgetContent.CollapseEntry.Kind kind = (.)line[0];
 				SourceEditWidgetContent.CollapseEntry.Kind kind = (.)line[0];
 				line.RemoveFromStart(1);
 				line.RemoveFromStart(1);
 
 
+				if (kind == .EmitAddType)
+				{
+					data.mTypeNames.Add(new String(line));
+					continue;
+				}
+
 				var itr = line.Split(',');
 				var itr = line.Split(',');
+				if (kind.IsEmit)
+				{
+					EmitData emitData;
+					emitData.mKind = kind;
+					emitData.mTypeNameIdx = int32.Parse(itr.GetNext().Value);
+					emitData.mRevision = int32.Parse(itr.GetNext().Value);
+					emitData.mPartialIdx = int32.Parse(itr.GetNext().Value);
+					emitData.mAnchorIdx = int32.Parse(itr.GetNext().Value);
+					emitData.mStartLine = int32.Parse(itr.GetNext().Value);
+					emitData.mEndLine = int32.Parse(itr.GetNext().Value);
+					emitData.mAnchorId = lookupCtx.GetIdAtIndex(emitData.mAnchorIdx);
+					data.mEmitData.Add(emitData);
+					continue;
+				}
 
 
 				CollapseData collapseData;
 				CollapseData collapseData;
 
 
@@ -5730,6 +6306,7 @@ namespace IDE.ui
 				if (mEmbeds.TryAdd(entry.mAnchorLine, var keyPtr, var valuePtr))
 				if (mEmbeds.TryAdd(entry.mAnchorLine, var keyPtr, var valuePtr))
 				{
 				{
 					SourceEditWidgetContent.CollapseSummary collapseSummary = new .();
 					SourceEditWidgetContent.CollapseSummary collapseSummary = new .();
+					collapseSummary.mLine = entry.mAnchorLine;
 					collapseSummary.mEditWidgetContent = this;
 					collapseSummary.mEditWidgetContent = this;
 					collapseSummary.mCollapseIndex = (.)collapseIdx;
 					collapseSummary.mCollapseIndex = (.)collapseIdx;
 					collapseSummary.mKind = .HideLine;
 					collapseSummary.mKind = .HideLine;
@@ -5774,11 +6351,20 @@ namespace IDE.ui
 				if (mEmbeds.TryAdd(entry.mAnchorLine, var keyPtr, var valuePtr))
 				if (mEmbeds.TryAdd(entry.mAnchorLine, var keyPtr, var valuePtr))
 				{
 				{
 					SourceEditWidgetContent.CollapseSummary collapseSummary = new .();
 					SourceEditWidgetContent.CollapseSummary collapseSummary = new .();
+					collapseSummary.mLine = entry.mAnchorLine;
 					collapseSummary.mEditWidgetContent = this;
 					collapseSummary.mEditWidgetContent = this;
 					collapseSummary.mCollapseIndex = (.)collapseIdx;
 					collapseSummary.mCollapseIndex = (.)collapseIdx;
 					collapseSummary.mKind = .LineEnd;
 					collapseSummary.mKind = .LineEnd;
 					*valuePtr = collapseSummary;
 					*valuePtr = collapseSummary;
 				}
 				}
+				else
+				{
+					if (var emitEntry = *valuePtr as EmitEmbed)
+					{
+						emitEntry.mIsOpen = false;
+						mCollapseNeedsUpdate = true;
+					}
+				}
 			}
 			}
 		}
 		}
 
 
@@ -5830,8 +6416,44 @@ namespace IDE.ui
 
 
 			if (animIdx == -1)
 			if (animIdx == -1)
 			{
 			{
-				RehupLineCoords();
 				mCollapseNeedsUpdate = false;
 				mCollapseNeedsUpdate = false;
+
+				for (var embed in mEmbeds.Values)
+				{
+					if (var emitEmbed = embed as EmitEmbed)
+					{
+						if (emitEmbed.mIsOpen)
+						{
+							emitEmbed.mOpenPct = Math.Min(1.0f, emitEmbed.mOpenPct + 0.1f);
+							if (emitEmbed.mOpenPct != 1.0f)
+								mCollapseNeedsUpdate = true;
+
+							if (emitEmbed.mView == null)
+							{
+								mSourceViewPanel.QueueFullRefresh(false);
+								emitEmbed.mView = new SourceEditWidgetContent.EmitEmbed.View(emitEmbed);
+								AddWidget(emitEmbed.mView);
+							}
+						}
+						else
+						{
+							emitEmbed.mOpenPct = Math.Max(0.0f, emitEmbed.mOpenPct - 0.1f);
+							if (emitEmbed.mOpenPct == 0.0f)
+							{
+								if (emitEmbed.mView != null)
+								{
+									emitEmbed.mView.RemoveSelf();
+									DeleteAndNullify!(emitEmbed.mView);
+								}
+							}
+							else
+								mCollapseNeedsUpdate = true;
+						}
+					}
+				}
+
+				RehupLineCoords();
+
 				return;
 				return;
 			}
 			}
 
 
@@ -5915,6 +6537,5 @@ namespace IDE.ui
 
 
 			RehupLineCoords(animIdx, animLines);
 			RehupLineCoords(animIdx, animLines);
 		}
 		}
-
     }
     }
 }
 }

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 488 - 118
IDE/src/ui/SourceViewPanel.bf


+ 2 - 0
IDE/src/ui/StatusBar.bf

@@ -408,6 +408,8 @@ namespace IDE.ui
 			{
 			{
 				DrawStatusBox("Loading Projects");
 				DrawStatusBox("Loading Projects");
 			}
 			}
+			else if (gApp.mDeferredShowSource != null)
+				DrawStatusBox("Queued Showing Source");
 			else
 			else
 				mStatusBoxUpdateCnt = -1;
 				mStatusBoxUpdateCnt = -1;
 
 

+ 81 - 5
IDEHelper/COFF.cpp

@@ -5,14 +5,18 @@
 #include "DebugTarget.h"
 #include "DebugTarget.h"
 #include "DebugManager.h"
 #include "DebugManager.h"
 #include "DWARFInfo.h"
 #include "DWARFInfo.h"
-#include "BeefySysLib/Util/PerfTimer.h"
-#include "BeefySysLib/Util/Dictionary.h"
-#include "BeefySysLib/Util/BeefPerf.h"
+#include "BeefySysLib/util/PerfTimer.h"
+#include "BeefySysLib/util/Dictionary.h"
+#include "BeefySysLib/util/BeefPerf.h"
+#include "BeefySysLib/util/BeefPerf.h"
+#include "BeefySysLib/util/ZipFile.h"
+#include "BeefySysLib/util/Hash.h"
 #include "BeefySysLib/platform/PlatformHelper.h"
 #include "BeefySysLib/platform/PlatformHelper.h"
 #include "WinDebugger.h"
 #include "WinDebugger.h"
 #include "MiniDumpDebugger.h"
 #include "MiniDumpDebugger.h"
 #include "Linker/BlHash.h"
 #include "Linker/BlHash.h"
 #include "Backend/BeLibManger.h"
 #include "Backend/BeLibManger.h"
+#include "Compiler/BfUtil.h"
 #include <shlobj.h>
 #include <shlobj.h>
 
 
 #include "BeefySysLib/util/AllocDebug.h"
 #include "BeefySysLib/util/AllocDebug.h"
@@ -262,6 +266,7 @@ COFF::COFF(DebugTarget* debugTarget) : DbgModule(debugTarget)
 	mPrevScanName = NULL;
 	mPrevScanName = NULL;
 	mProcSymCount = 0;	
 	mProcSymCount = 0;	
 	mCvSrcSrvStream = -1;
 	mCvSrcSrvStream = -1;
+	mCvEmitStream = -1;
 	mIsFastLink = false;
 	mIsFastLink = false;
 	mHotThunkCurAddr = 0;
 	mHotThunkCurAddr = 0;
 	mHotThunkDataLeft = 0;
 	mHotThunkDataLeft = 0;
@@ -270,6 +275,7 @@ COFF::COFF(DebugTarget* debugTarget) : DbgModule(debugTarget)
 	mDbgSymRequest = NULL;	
 	mDbgSymRequest = NULL;	
 	mWantsAutoLoadDebugInfo = false;		
 	mWantsAutoLoadDebugInfo = false;		
 	mPDBLoaded = false;
 	mPDBLoaded = false;
+	mEmitSourceFile = NULL;
 }
 }
 
 
 COFF::~COFF()
 COFF::~COFF()
@@ -3605,8 +3611,17 @@ CvCompileUnit* COFF::ParseCompileUnit(CvModuleInfo* moduleInfo, CvCompileUnit* c
 					GET_INTO(uint, fileTableOfs);
 					GET_INTO(uint, fileTableOfs);
 					
 					
 					const char* fileName = mStringTable.mStrTable + fileTableOfs;
 					const char* fileName = mStringTable.mStrTable + fileTableOfs;
+
+					if ((fileName[0] == '\\') && (fileName[1] == '$'))
+						fileName++;
+
 					DbgSrcFile* srcFile = NULL;
 					DbgSrcFile* srcFile = NULL;
-					if ((fileName[0] == '/') || (fileName[0] == '\\') ||
+
+					if (fileName[0] == '$')
+					{
+						srcFile = AddSrcFile(compileUnit, fileName);
+					}					
+					else if ((fileName[0] == '/') || (fileName[0] == '\\') ||
 						((fileName[0] != 0) && (fileName[1] == ':')))					
 						((fileName[0] != 0) && (fileName[1] == ':')))					
 					{
 					{
 						srcFile = AddSrcFile(compileUnit, fileName);
 						srcFile = AddSrcFile(compileUnit, fileName);
@@ -4642,6 +4657,8 @@ void COFF::ScanCompileUnit(int compileUnitId)
 				else
 				else
 				{
 				{
 					const char* fileName = mStringTable.mStrTable + fileTableOfs;
 					const char* fileName = mStringTable.mStrTable + fileTableOfs;
+					if ((fileName[0] == '\\') && (fileName[1] == '$'))
+						fileName++;
 					srcFile = AddSrcFile(NULL, fileName);
 					srcFile = AddSrcFile(NULL, fileName);
 					mSrcFileDeferredRefs.Add(srcFile);
 					mSrcFileDeferredRefs.Add(srcFile);
 					*srcFilePtr = srcFile;
 					*srcFilePtr = srcFile;
@@ -4967,6 +4984,8 @@ bool COFF::CvParseHeader(uint8 wantGuid[16], int32 wantAge)
 			mStringTable.mStream = streamNum;
 			mStringTable.mStream = streamNum;
 		if (strcmp(tableName, "srcsrv") == 0)
 		if (strcmp(tableName, "srcsrv") == 0)
 			mCvSrcSrvStream = streamNum;
 			mCvSrcSrvStream = streamNum;
+		if (strcmp(tableName, "emit") == 0)
+			mCvEmitStream = streamNum;
 
 
 		/*if (tableIdx == nameTableIdx)
 		/*if (tableIdx == nameTableIdx)
 		{
 		{
@@ -6095,6 +6114,9 @@ void COFF::ClosePDB()
 		delete kv.mValue;
 		delete kv.mValue;
 	mHotLibMap.Clear();	
 	mHotLibMap.Clear();	
 	mHotLibSymMap.Clear();
 	mHotLibSymMap.Clear();
+
+	delete mEmitSourceFile;
+	mEmitSourceFile = NULL;
 }
 }
 
 
 bool COFF::LoadPDB(const String& pdbPath, uint8 wantGuid[16], int32 wantAge)
 bool COFF::LoadPDB(const String& pdbPath, uint8 wantGuid[16], int32 wantAge)
@@ -6669,6 +6691,60 @@ String COFF::GetOldSourceCommand(const StringImpl& path)
 	return "";
 	return "";
 }
 }
 
 
+bool COFF::GetEmitSource(const StringImpl& filePath, String& outText)
+{
+	if (!filePath.StartsWith("$Emit"))
+		return false;
+	
+	if (mEmitSourceFile == NULL)
+	{
+		mEmitSourceFile = new ZipFile();
+
+		String zipPath = mPDBPath;
+		int dotPos = zipPath.LastIndexOf('.');
+		zipPath.RemoveToEnd(dotPos);
+		zipPath.Append("__emit.zip");
+		if (!mEmitSourceFile->Open(zipPath))
+		{
+			if (mCvEmitStream == -1)
+				return "";
+			
+			int outSize;
+			uint8* data = CvReadStream(mCvEmitStream, &outSize);
+						
+			FileStream fileStream;
+			fileStream.Open(zipPath, "wb");
+			fileStream.Write(data, outSize);
+			fileStream.Close();
+
+			delete data;
+
+			mEmitSourceFile->Open(zipPath);
+		}
+	}
+
+	if (mEmitSourceFile->IsOpen())
+	{
+		String usePath = filePath;
+		if (usePath.StartsWith("$Emit"))
+		{
+			int dollarPos = usePath.IndexOf('$', 1);
+			usePath.Remove(0, dollarPos + 1);
+		}		
+		usePath = EncodeFileName(usePath);
+		usePath.Append(".bf");
+
+		Array<uint8> data;
+		if (mEmitSourceFile->Get(usePath, data))
+		{
+			outText.Insert(outText.mLength, (char*)data.mVals, data.mSize);
+			return true;
+		}
+	}
+
+	return false;
+}
+
 bool COFF::HasPendingDebugInfo()
 bool COFF::HasPendingDebugInfo()
 {
 {
 	if (mDbgSymRequest == NULL)
 	if (mDbgSymRequest == NULL)
@@ -7016,7 +7092,7 @@ addr_target COFF::LocateSymbol(const StringImpl& name)
 		delete dbgModule;
 		delete dbgModule;
 		return 0;
 		return 0;
 	}	
 	}	
-	mDebugger->mDebugTarget->mDbgModules.push_back(dbgModule);
+	mDebugger->mDebugTarget->AddDbgModule(dbgModule);
 
 
 	auto symbolEntry = mSymbolNameMap.Find(name.c_str());
 	auto symbolEntry = mSymbolNameMap.Find(name.c_str());
 	if (symbolEntry != NULL)
 	if (symbolEntry != NULL)

+ 4 - 0
IDEHelper/COFF.h

@@ -13,6 +13,7 @@ namespace Beefy
 	class DataStream;
 	class DataStream;
 	class MemStream;
 	class MemStream;
 	class SafeMemStream;
 	class SafeMemStream;
+	class ZipFile;
 }
 }
 
 
 struct CV_LVAR_ADDR_RANGE;
 struct CV_LVAR_ADDR_RANGE;
@@ -214,6 +215,7 @@ public:
 	};
 	};
 
 
 public:	
 public:	
+	ZipFile* mEmitSourceFile;
 	uint8 mWantPDBGuid[16];
 	uint8 mWantPDBGuid[16];
 	int mWantAge;
 	int mWantAge;
 
 
@@ -262,6 +264,7 @@ public:
 	int mCvPublicSymbolInfoStream;
 	int mCvPublicSymbolInfoStream;
 	int mCvSymbolRecordStream;	
 	int mCvSymbolRecordStream;	
 	int mCvSrcSrvStream;
 	int mCvSrcSrvStream;
+	int mCvEmitStream;
 	int mCvNewFPOStream;
 	int mCvNewFPOStream;
 	Array<CvModuleInfo*> mCvModuleInfo;	
 	Array<CvModuleInfo*> mCvModuleInfo;	
 	Dictionary<int, DbgSrcFile*> mCVSrcFileRefCache;
 	Dictionary<int, DbgSrcFile*> mCVSrcFileRefCache;
@@ -320,6 +323,7 @@ public:
 	virtual intptr EvaluateLocation(DbgSubprogram* dwSubprogram, const uint8* locData, int locDataLen, WdStackFrame* stackFrame, DbgAddrType* outAddrType, DbgEvalLocFlags flags = DbgEvalLocFlag_None) override;
 	virtual intptr EvaluateLocation(DbgSubprogram* dwSubprogram, const uint8* locData, int locDataLen, WdStackFrame* stackFrame, DbgAddrType* outAddrType, DbgEvalLocFlags flags = DbgEvalLocFlag_None) override;
 	virtual bool CanGetOldSource() override;
 	virtual bool CanGetOldSource() override;
 	virtual String GetOldSourceCommand(const StringImpl& path) override;	
 	virtual String GetOldSourceCommand(const StringImpl& path) override;	
+	virtual bool GetEmitSource(const StringImpl& filePath, String& outText) override;
 	virtual bool HasPendingDebugInfo() override;
 	virtual bool HasPendingDebugInfo() override;
 	virtual void PreCacheImage() override;
 	virtual void PreCacheImage() override;
 	virtual void PreCacheDebugInfo() override;
 	virtual void PreCacheDebugInfo() override;

+ 39 - 25
IDEHelper/Compiler/BfAutoComplete.cpp

@@ -276,10 +276,15 @@ int BfAutoComplete::GetCursorIdx(BfAstNode* node)
 	if (node == NULL)
 	if (node == NULL)
 		return -1;
 		return -1;
 
 
-	if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
-		return -1;
+// 	if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
+// 		return -1;
 
 
+	if (node->IsTemporary())
+		return false;
 	auto bfParser = node->GetSourceData()->ToParser();
 	auto bfParser = node->GetSourceData()->ToParser();
+	if (bfParser == NULL)
+		return -1;
+
 	if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
 	if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
 		return -1;
 		return -1;
 
 
@@ -291,10 +296,14 @@ bool BfAutoComplete::IsAutocompleteNode(BfAstNode* node, int lengthAdd, int star
 	if (node == NULL)
 	if (node == NULL)
 		return false;
 		return false;
 	
 	
-	if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
-		return false;
+// 	if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
+// 		return false;
 
 
+	if (node->IsTemporary())
+		return false;
 	auto bfParser = node->GetSourceData()->ToParser();
 	auto bfParser = node->GetSourceData()->ToParser();
+	if (bfParser == NULL)
+		return false;
 	if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
 	if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
 		return false;
 		return false;
 			
 			
@@ -313,10 +322,14 @@ bool BfAutoComplete::IsAutocompleteNode(BfAstNode* startNode, BfAstNode* endNode
 	if ((startNode == NULL) || (endNode == NULL))
 	if ((startNode == NULL) || (endNode == NULL))
 		return false;
 		return false;
 
 
-	if (!startNode->IsFromParser(mCompiler->mResolvePassData->mParser))
-		return false;
+// 	if (!startNode->IsFromParser(mCompiler->mResolvePassData->mParser))
+// 		return false;
 
 
+	if (startNode->IsTemporary())
+		return false;
 	auto bfParser = startNode->GetSourceData()->ToParser();
 	auto bfParser = startNode->GetSourceData()->ToParser();
+	if (bfParser == NULL)
+		return false;
 	if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
 	if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
 		return false;
 		return false;
 
 
@@ -335,10 +348,14 @@ bool BfAutoComplete::IsAutocompleteLineNode(BfAstNode* node)
 	if (node == NULL)
 	if (node == NULL)
 		return false;
 		return false;
 
 
-	if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
-		return false;
+// 	if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
+// 		return false;
 
 
+	if (node->IsTemporary())
+		return false;
 	auto bfParser = node->GetSourceData()->ToParser();
 	auto bfParser = node->GetSourceData()->ToParser();
+	if (bfParser == NULL)
+		return false;
 	if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
 	if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
 		return false;
 		return false;
 
 
@@ -414,7 +431,7 @@ BfTypedValue BfAutoComplete::LookupTypeRefOrIdentifier(BfAstNode* node, bool* is
 				{
 				{
 					// This keeps the classifier from colorizing properties - this causes 'flashing' when we go back over this with a resolve pass
 					// This keeps the classifier from colorizing properties - this causes 'flashing' when we go back over this with a resolve pass
 					//  that wouldn't catch this
 					//  that wouldn't catch this
-					SetAndRestoreValue<BfSourceClassifier*> prevClassifier(mModule->mCompiler->mResolvePassData->mSourceClassifier, NULL);
+					SetAndRestoreValue<bool> prevClassifier(mModule->mCompiler->mResolvePassData->mIsClassifying, false);
 
 
 					BfExprEvaluator exprEvaluator(mModule);
 					BfExprEvaluator exprEvaluator(mModule);
 					auto fieldResult = exprEvaluator.LookupField(qualifiedTypeRef->mRight, leftValue, rightNamedTypeRef->mNameNode->ToString());
 					auto fieldResult = exprEvaluator.LookupField(qualifiedTypeRef->mRight, leftValue, rightNamedTypeRef->mNameNode->ToString());
@@ -1271,11 +1288,17 @@ BfProject* BfAutoComplete::GetActiveProject()
 	auto activeTypeDef = mModule->GetActiveTypeDef();
 	auto activeTypeDef = mModule->GetActiveTypeDef();
 	if (activeTypeDef != NULL)
 	if (activeTypeDef != NULL)
 		bfProject = activeTypeDef->mProject;
 		bfProject = activeTypeDef->mProject;
-	else
-		bfProject = mCompiler->mResolvePassData->mParser->mProject;
+	else if (!mCompiler->mResolvePassData->mParsers.IsEmpty())
+		bfProject = mCompiler->mResolvePassData->mParsers[0]->mProject;
 	return bfProject;
 	return bfProject;
 }
 }
 
 
+bool BfAutoComplete::WantsEntries()
+{
+	return (mResolveType == BfResolveType_Autocomplete) || 
+		(mResolveType == BfResolveType_Autocomplete_HighPri);
+}
+
 void BfAutoComplete::AddTopLevelNamespaces(BfAstNode* identifierNode)
 void BfAutoComplete::AddTopLevelNamespaces(BfAstNode* identifierNode)
 {	
 {	
 	String filter;
 	String filter;
@@ -1419,8 +1442,8 @@ void BfAutoComplete::AddTopLevelTypes(BfAstNode* identifierNode, bool onlyAttrib
 	else
 	else
 	{
 	{
 		BfProject* curProject = NULL;
 		BfProject* curProject = NULL;
-		if (mModule->mCompiler->mResolvePassData->mParser != NULL)
-			curProject = mModule->mCompiler->mResolvePassData->mParser->mProject;
+		if (!mModule->mCompiler->mResolvePassData->mParsers.IsEmpty())
+			curProject = mModule->mCompiler->mResolvePassData->mParsers[0]->mProject;
 
 
 		String prevName;
 		String prevName;
 		for (auto typeDef : mModule->mSystem->mTypeDefs)
 		for (auto typeDef : mModule->mSystem->mTypeDefs)
@@ -1468,14 +1491,6 @@ void BfAutoComplete::CheckIdentifier(BfAstNode* identifierNode, bool isInExpress
 			}
 			}
 		}
 		}
 	}
 	}
-
-	//bool isUsingDirective = false;
-	//bool isUsingDirective = (identifierNode != NULL) && (identifierNode->mParent != NULL) && (identifierNode->mParent->IsA<BfUsingDirective>());
-	if (mCompiler->mResolvePassData->mSourceClassifier != NULL)
-	{
-		//TODO: Color around dots
-		//mCompiler->mResolvePassData->mSourceClassifier->SetElementType(identifierNode, BfSourceElementType_Namespace);
-	}
 	
 	
 	if (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(identifierNode))
 	if (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(identifierNode))
 	{
 	{
@@ -1483,10 +1498,6 @@ void BfAutoComplete::CheckIdentifier(BfAstNode* identifierNode, bool isInExpress
 		return;
 		return;
 	}
 	}
 
 
-	//bool isInExpression = true;
-// 	if (identifierNode != NULL)
-// 		isInExpression = IsInExpression(identifierNode);
-	
 	AddTopLevelNamespaces(identifierNode);
 	AddTopLevelNamespaces(identifierNode);
 	if (isUsingDirective)
 	if (isUsingDirective)
 		return; // Only do namespaces
 		return; // Only do namespaces
@@ -1759,6 +1770,9 @@ String BfAutoComplete::GetFilter(BfAstNode* node)
 
 
 bool BfAutoComplete::CheckMemberReference(BfAstNode* target, BfAstNode* dotToken, BfAstNode* memberName, bool onlyShowTypes, BfType* expectingType, bool isUsingDirective, bool onlyAttribute)
 bool BfAutoComplete::CheckMemberReference(BfAstNode* target, BfAstNode* dotToken, BfAstNode* memberName, bool onlyShowTypes, BfType* expectingType, bool isUsingDirective, bool onlyAttribute)
 {
 {
+	if (!WantsEntries())
+		return false;
+
 	BfAttributedIdentifierNode* attrIdentifier = NULL;
 	BfAttributedIdentifierNode* attrIdentifier = NULL;
 	bool isAutocompletingName = false;
 	bool isAutocompletingName = false;
 	if ((attrIdentifier = BfNodeDynCast<BfAttributedIdentifierNode>(memberName)))
 	if ((attrIdentifier = BfNodeDynCast<BfAttributedIdentifierNode>(memberName)))

+ 1 - 0
IDEHelper/Compiler/BfAutoComplete.h

@@ -208,6 +208,7 @@ public:
 
 
 public:	
 public:	
 	BfProject* GetActiveProject();
 	BfProject* GetActiveProject();
+	bool WantsEntries();
 	bool CheckProtection(BfProtection protection, BfTypeDef* typeDef, bool allowProtected, bool allowPrivate);
 	bool CheckProtection(BfProtection protection, BfTypeDef* typeDef, bool allowProtected, bool allowPrivate);
 	String GetFilter(BfAstNode* node);
 	String GetFilter(BfAstNode* node);
 	const char* GetTypeName(BfType* type);
 	const char* GetTypeName(BfType* type);

+ 499 - 118
IDEHelper/Compiler/BfCompiler.cpp

@@ -27,6 +27,7 @@
 #include "BfAutoComplete.h"
 #include "BfAutoComplete.h"
 #include "BfResolvePass.h"
 #include "BfResolvePass.h"
 #include "BeefySysLib/util/BeefPerf.h"
 #include "BeefySysLib/util/BeefPerf.h"
+#include "BeefySysLib/util/ZipFile.h"
 #include "../LLVMUtils.h"
 #include "../LLVMUtils.h"
 #include "BfNamespaceVisitor.h"
 #include "BfNamespaceVisitor.h"
 #include "CeMachine.h"
 #include "CeMachine.h"
@@ -2276,7 +2277,7 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork)
 	bool madeFullPass = true;
 	bool madeFullPass = true;
 	if (mCanceling)
 	if (mCanceling)
 		madeFullPass = false;
 		madeFullPass = false;
-	if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL))
+	if ((mResolvePassData != NULL) && (!mResolvePassData->mParsers.IsEmpty()))
 		madeFullPass = false;
 		madeFullPass = false;
 	
 	
 	SetAndRestoreValue<bool> prevAssertOnPopulateType(mContext->mAssertOnPopulateType, deleteUnusued && madeFullPass);
 	SetAndRestoreValue<bool> prevAssertOnPopulateType(mContext->mAssertOnPopulateType, deleteUnusued && madeFullPass);
@@ -3736,19 +3737,19 @@ void BfCompiler::VisitAutocompleteExteriorIdentifiers()
 
 
 		if (mResolvePassData->mAutoComplete != NULL)
 		if (mResolvePassData->mAutoComplete != NULL)
 			mResolvePassData->mAutoComplete->CheckIdentifier(checkIdentifier, false, isUsingDirective);
 			mResolvePassData->mAutoComplete->CheckIdentifier(checkIdentifier, false, isUsingDirective);
-
-		if ((checkIdentifier->IsFromParser(mResolvePassData->mParser)) && (mResolvePassData->mSourceClassifier != NULL))
+		
+		if (auto sourceClassifier = mResolvePassData->GetSourceClassifier(checkIdentifier))
 		{
 		{
 			if (isUsingDirective)
 			if (isUsingDirective)
 			{
 			{
 				while (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(checkIdentifier))
 				while (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(checkIdentifier))
 				{
 				{
-					mResolvePassData->mSourceClassifier->SetElementType(qualifiedNameNode->mRight, BfSourceElementType_Namespace);
+					sourceClassifier->SetElementType(qualifiedNameNode->mRight, BfSourceElementType_Namespace);
 					checkIdentifier = qualifiedNameNode->mLeft;
 					checkIdentifier = qualifiedNameNode->mLeft;
 				}
 				}
 
 
 				if (checkIdentifier != NULL)
 				if (checkIdentifier != NULL)
-					mResolvePassData->mSourceClassifier->SetElementType(checkIdentifier, BfSourceElementType_Namespace);
+					sourceClassifier->SetElementType(checkIdentifier, BfSourceElementType_Namespace);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -3903,9 +3904,10 @@ void BfCompiler::VisitSourceExteriorNodes()
 			parser->mParserData->mExteriorNodesCheckIdx = mSystem->mTypeMapVersion;
 			parser->mParserData->mExteriorNodesCheckIdx = mSystem->mTypeMapVersion;
 	};
 	};
 
 
-	if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL))
+	if (mResolvePassData != NULL)
 	{
 	{
-		_CheckParser(mResolvePassData->mParser);
+		for (auto parser : mResolvePassData->mParsers)
+			_CheckParser(parser);
 	}
 	}
 	else		
 	else		
 	{
 	{
@@ -3936,18 +3938,21 @@ void BfCompiler::ProcessAutocompleteTempType()
 
 
 	if (autoComplete->mResolveType == BfResolveType_GetNavigationData)
 	if (autoComplete->mResolveType == BfResolveType_GetNavigationData)
 	{
 	{
-		for (auto node : mResolvePassData->mParser->mSidechannelRootNode->mChildArr)
+		for (auto parser : mResolvePassData->mParsers)
 		{
 		{
-			if (auto preprocNode = BfNodeDynCast<BfPreprocessorNode>(node))
+			for (auto node : parser->mSidechannelRootNode->mChildArr)
 			{
 			{
-				if (preprocNode->mCommand->Equals("region"))
+				if (auto preprocNode = BfNodeDynCast<BfPreprocessorNode>(node))
 				{
 				{
-					if (!autoCompleteResultString.empty())
-						autoCompleteResultString += "\n";
-					autoCompleteResultString += "#";
-					preprocNode->mArgument->ToString(autoCompleteResultString);
-					mContext->mScratchModule->UpdateSrcPos(preprocNode, (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
-					autoCompleteResultString += StrFormat("\tregion\t%d\t%d", module->mCurFilePosition.mCurLine, module->mCurFilePosition.mCurColumn);
+					if (preprocNode->mCommand->Equals("region"))
+					{
+						if (!autoCompleteResultString.empty())
+							autoCompleteResultString += "\n";
+						autoCompleteResultString += "#";
+						preprocNode->mArgument->ToString(autoCompleteResultString);
+						mContext->mScratchModule->UpdateSrcPos(preprocNode, (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
+						autoCompleteResultString += StrFormat("\tregion\t%d\t%d", module->mCurFilePosition.mCurLine, module->mCurFilePosition.mCurColumn);
+					}
 				}
 				}
 			}
 			}
 		}
 		}
@@ -4041,7 +4046,7 @@ void BfCompiler::ProcessAutocompleteTempType()
 	if (autoComplete->mResolveType == BfResolveType_GetCurrentLocation)
 	if (autoComplete->mResolveType == BfResolveType_GetCurrentLocation)
 	{
 	{
 		for (auto tempTypeDef : mResolvePassData->mAutoCompleteTempTypes)
 		for (auto tempTypeDef : mResolvePassData->mAutoCompleteTempTypes)
-		{						
+		{
 			String typeName = tempTypeDef->mNamespace.ToString();
 			String typeName = tempTypeDef->mNamespace.ToString();
 			if (!typeName.empty())
 			if (!typeName.empty())
 				typeName += ".";
 				typeName += ".";
@@ -4049,16 +4054,21 @@ void BfCompiler::ProcessAutocompleteTempType()
 
 
 			autoCompleteResultString = typeName;
 			autoCompleteResultString = typeName;
 
 
-			int cursorPos = mResolvePassData->mParser->mCursorIdx;
-
 			for (auto methodDef : tempTypeDef->mMethods)
 			for (auto methodDef : tempTypeDef->mMethods)
 			{	
 			{	
 				BfAstNode* defNode = methodDef->mMethodDeclaration;
 				BfAstNode* defNode = methodDef->mMethodDeclaration;
 				if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
 				if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
 					defNode = propertyDeclaration;
 					defNode = propertyDeclaration;
 
 
+				if (defNode == NULL)
+					continue;
+
+				auto parser = defNode->GetParser();
+				if ((parser == NULL) || (parser->mCursorIdx == -1))
+					continue;
+
 				if ((defNode != NULL) && 
 				if ((defNode != NULL) && 
-					(defNode->Contains(cursorPos)))
+					(defNode->Contains(parser->mCursorIdx)))
 				{
 				{
 					String methodText = methodDef->ToString();
 					String methodText = methodDef->ToString();
 					if (typeName != "@")
 					if (typeName != "@")
@@ -4070,6 +4080,53 @@ void BfCompiler::ProcessAutocompleteTempType()
 			}			
 			}			
 		}
 		}
 
 
+		if (mResolvePassData->mAutoCompleteTempTypes.IsEmpty())
+		{
+			for (auto& kv : mResolvePassData->mEmitEmbedEntries)
+			{
+				if (kv.mValue.mCursorIdx < 0)
+					continue;
+
+				String typeName = kv.mKey;
+				auto type = GetType(typeName);
+				if (type == NULL)
+					continue;
+				auto typeInst = type->ToTypeInstance();
+				if (typeInst == NULL)
+					continue;
+
+				if (mResolvePassData->mParsers.IsEmpty())
+					break;
+				
+				autoCompleteResultString = mContext->mScratchModule->TypeToString(typeInst);
+
+				for (auto methodDef : typeInst->mTypeDef->mMethods)
+				{					
+					BfAstNode* defNode = methodDef->mMethodDeclaration;
+					if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
+						defNode = propertyDeclaration;
+
+					if (defNode == NULL)
+						continue;					
+
+					if ((defNode != NULL) &&
+						(defNode->Contains(kv.mValue.mCursorIdx)))
+					{
+						auto defParser = defNode->GetParser();
+						if (defParser == NULL)
+							continue;
+
+						if (!defParser->mIsEmitted)
+							continue;
+						
+						autoCompleteResultString += ".";
+						autoCompleteResultString += methodDef->ToString();						
+						break;
+					}
+				}
+			}
+		}
+
 		module->CleanupFileInstances();
 		module->CleanupFileInstances();
 		return;
 		return;
 	}
 	}
@@ -4094,59 +4151,58 @@ void BfCompiler::ProcessAutocompleteTempType()
 		BfAstNode* conflictStart = NULL;
 		BfAstNode* conflictStart = NULL;
 		BfAstNode* conflictSplit = NULL;		
 		BfAstNode* conflictSplit = NULL;		
 
 
-		auto src = mResolvePassData->mParser->mSrc;
-
-		for (int checkIdx = 0; checkIdx < (int)mResolvePassData->mParser->mSidechannelRootNode->mChildArr.mSize; checkIdx++)
+		for (auto parser : mResolvePassData->mParsers)
 		{
 		{
-			auto sideNode = mResolvePassData->mParser->mSidechannelRootNode->mChildArr.mVals[checkIdx];
-			if (autoComplete->CheckFixit(sideNode))
-			{
-				if (src[sideNode->mSrcStart] == '<')
-				{
-					conflictStart = sideNode;
-					conflictSplit = NULL;
-				}				
-			}
-			else
+			auto src = parser->mSrc;
+
+			for (int checkIdx = 0; checkIdx < (int)parser->mSidechannelRootNode->mChildArr.mSize; checkIdx++)
 			{
 			{
-				if (src[sideNode->mSrcStart] == '<')
+				auto sideNode = parser->mSidechannelRootNode->mChildArr.mVals[checkIdx];
+				if (autoComplete->CheckFixit(sideNode))
 				{
 				{
-					conflictStart = NULL;
-					conflictSplit = NULL;
-				}
-				else if (src[sideNode->mSrcStart] == '=')
-				{
-					if (conflictStart != NULL)
-						conflictSplit = sideNode;
+					if (src[sideNode->mSrcStart] == '<')
+					{
+						conflictStart = sideNode;
+						conflictSplit = NULL;
+					}
 				}
 				}
-				else if (src[sideNode->mSrcStart] == '>')
+				else
 				{
 				{
-					if (conflictSplit != NULL)
+					if (src[sideNode->mSrcStart] == '<')
+					{
+						conflictStart = NULL;
+						conflictSplit = NULL;
+					}
+					else if (src[sideNode->mSrcStart] == '=')
 					{
 					{
-						autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept First\tdelete|%s-%d|\x01""delete|%s-%d|",
-							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictSplit->mSrcStart).c_str(), sideNode->mSrcEnd - conflictSplit->mSrcStart + 1,
-							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictStart->mSrcStart).c_str(), conflictStart->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
+						if (conflictStart != NULL)
+							conflictSplit = sideNode;
+					}
+					else if (src[sideNode->mSrcStart] == '>')
+					{
+						if (conflictSplit != NULL)
+						{
+							autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept First\tdelete|%s-%d|\x01""delete|%s-%d|",
+								autoComplete->FixitGetLocation(parser->mParserData, conflictSplit->mSrcStart).c_str(), sideNode->mSrcEnd - conflictSplit->mSrcStart + 1,
+								autoComplete->FixitGetLocation(parser->mParserData, conflictStart->mSrcStart).c_str(), conflictStart->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
 
 
-						autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept Second\tdelete|%s-%d|\x01""delete|%s-%d|",
-							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, sideNode->mSrcStart).c_str(), sideNode->mSrcEnd - sideNode->mSrcStart + 1,
-							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictStart->mSrcStart).c_str(), conflictSplit->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
+							autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept Second\tdelete|%s-%d|\x01""delete|%s-%d|",
+								autoComplete->FixitGetLocation(parser->mParserData, sideNode->mSrcStart).c_str(), sideNode->mSrcEnd - sideNode->mSrcStart + 1,
+								autoComplete->FixitGetLocation(parser->mParserData, conflictStart->mSrcStart).c_str(), conflictSplit->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
 
 
-						autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept Both\tdelete|%s-%d|\x01""delete|%s-%d|\x01""delete|%s-%d|",
-							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, sideNode->mSrcStart).c_str(), sideNode->mSrcEnd - sideNode->mSrcStart + 1,
-							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictSplit->mSrcStart).c_str(), conflictSplit->mSrcEnd - conflictSplit->mSrcStart + 1,
-							autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictStart->mSrcStart).c_str(), conflictStart->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
+							autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept Both\tdelete|%s-%d|\x01""delete|%s-%d|\x01""delete|%s-%d|",
+								autoComplete->FixitGetLocation(parser->mParserData, sideNode->mSrcStart).c_str(), sideNode->mSrcEnd - sideNode->mSrcStart + 1,
+								autoComplete->FixitGetLocation(parser->mParserData, conflictSplit->mSrcStart).c_str(), conflictSplit->mSrcEnd - conflictSplit->mSrcStart + 1,
+								autoComplete->FixitGetLocation(parser->mParserData, conflictStart->mSrcStart).c_str(), conflictStart->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
 
 
-						conflictStart = NULL;
-						conflictSplit = NULL;
+							conflictStart = NULL;
+							conflictSplit = NULL;
+						}
 					}
 					}
 				}
 				}
 			}
 			}
 		}
 		}
 
 
-		for (auto sideNode : mResolvePassData->mParser->mSidechannelRootNode->mChildArr)
-		{
-			
-		}
 	}
 	}
 
 
 	if (autoComplete->mResolveType == BfResolveType_GetSymbolInfo)
 	if (autoComplete->mResolveType == BfResolveType_GetSymbolInfo)
@@ -4154,7 +4210,8 @@ void BfCompiler::ProcessAutocompleteTempType()
 		BfNamespaceVisitor namespaceVisitor;
 		BfNamespaceVisitor namespaceVisitor;
 		namespaceVisitor.mResolvePassData = mResolvePassData;
 		namespaceVisitor.mResolvePassData = mResolvePassData;
 		namespaceVisitor.mSystem = mSystem;
 		namespaceVisitor.mSystem = mSystem;
-		namespaceVisitor.Visit(mResolvePassData->mParser->mRootNode);
+		for (auto parser : mResolvePassData->mParsers)
+			namespaceVisitor.Visit(parser->mRootNode);
 	}
 	}
 	
 	
 	auto _FindAcutalTypeDef = [&](BfTypeDef* tempTypeDef)
 	auto _FindAcutalTypeDef = [&](BfTypeDef* tempTypeDef)
@@ -4204,6 +4261,9 @@ void BfCompiler::ProcessAutocompleteTempType()
 			mContext->HandleChangedTypeDef(checkTempType, true);
 			mContext->HandleChangedTypeDef(checkTempType, true);
 		}
 		}
 
 
+		auto sourceClassifier = mResolvePassData->GetSourceClassifier(checkTempType->mTypeDeclaration->mNameNode);
+		if (sourceClassifier == NULL)
+			continue;
 		BfSourceElementType elemType = BfSourceElementType_Type;
 		BfSourceElementType elemType = BfSourceElementType_Type;
 		if (checkTempType->mTypeCode == BfTypeCode_Interface)
 		if (checkTempType->mTypeCode == BfTypeCode_Interface)
 			elemType = BfSourceElementType_Interface;
 			elemType = BfSourceElementType_Interface;
@@ -4211,11 +4271,32 @@ void BfCompiler::ProcessAutocompleteTempType()
 			elemType = BfSourceElementType_RefType;
 			elemType = BfSourceElementType_RefType;
 		else if (checkTempType->mTypeCode == BfTypeCode_Struct)
 		else if (checkTempType->mTypeCode == BfTypeCode_Struct)
 			elemType = BfSourceElementType_Struct;
 			elemType = BfSourceElementType_Struct;
-		mResolvePassData->mSourceClassifier->SetElementType(checkTempType->mTypeDeclaration->mNameNode, elemType);
+		sourceClassifier->SetElementType(checkTempType->mTypeDeclaration->mNameNode, elemType);
 	}
 	}
 
 
 	if (tempTypeDef == NULL)
 	if (tempTypeDef == NULL)
 	{
 	{
+		if ((autoComplete != NULL) && (autoComplete->mResolveType == BfResolveType_GoToDefinition))
+		{
+			for (auto& kv : mResolvePassData->mEmitEmbedEntries)
+			{
+				String typeName = kv.mKey;
+				auto type = GetType(typeName);
+				if (type == NULL)
+					continue;
+				auto typeInst = type->ToTypeInstance();
+				if (typeInst == NULL)
+					continue;
+
+				mContext->RebuildType(typeInst);
+				if (!typeInst->mModule->mIsModuleMutable)
+					typeInst->mModule->StartNewRevision(BfModule::RebuildKind_All, true);
+				mContext->mScratchModule->PopulateType(typeInst, Beefy::BfPopulateType_Full_Force);
+			}
+
+			DoWorkLoop();
+		}
+
 		GenerateAutocompleteInfo();
 		GenerateAutocompleteInfo();
 		BfLogSysM("ProcessAutocompleteTempType - no tempTypeDef\n");
 		BfLogSysM("ProcessAutocompleteTempType - no tempTypeDef\n");
 		return;
 		return;
@@ -4319,10 +4400,11 @@ void BfCompiler::ProcessAutocompleteTempType()
 		return;
 		return;
 	}
 	}
 	
 	
+	auto sourceClassifier = mResolvePassData->GetSourceClassifier(tempTypeDef->mTypeDeclaration);
 	if (tempTypeDef->mTypeCode == BfTypeCode_Extension)
 	if (tempTypeDef->mTypeCode == BfTypeCode_Extension)
-		mResolvePassData->mSourceClassifier->SetElementType(tempTypeDef->mTypeDeclaration->mNameNode, actualTypeDef->mTypeCode);
+		sourceClassifier->SetElementType(tempTypeDef->mTypeDeclaration->mNameNode, actualTypeDef->mTypeCode);
 	if (tempTypeDef->mTypeDeclaration->mAttributes != NULL)
 	if (tempTypeDef->mTypeDeclaration->mAttributes != NULL)
-		mResolvePassData->mSourceClassifier->VisitChild(tempTypeDef->mTypeDeclaration->mAttributes);
+		sourceClassifier->VisitChild(tempTypeDef->mTypeDeclaration->mAttributes);
 
 
 	BfTypeInstance* typeInst;
 	BfTypeInstance* typeInst;
 	{
 	{
@@ -4750,10 +4832,16 @@ BfType* BfCompiler::CheckSymbolReferenceTypeRef(BfModule* module, BfTypeReferenc
 
 
 void BfCompiler::AddToRebuildTypeList(BfTypeInstance* typeInst, HashSet<BfTypeInstance*>& rebuildTypeInstList)
 void BfCompiler::AddToRebuildTypeList(BfTypeInstance* typeInst, HashSet<BfTypeInstance*>& rebuildTypeInstList)
 {
 {
-	if (mResolvePassData->mParser != NULL)
+	if (!mResolvePassData->mParsers.IsEmpty())
 	{
 	{
-		// Only find references within the current file
-		if (!typeInst->mTypeDef->GetDefinition()->HasSource(mResolvePassData->mParser))
+		bool found = false;
+		for (auto parser : mResolvePassData->mParsers)
+		{
+			// Only find references within the current file
+			if (typeInst->mTypeDef->GetDefinition()->HasSource(parser))
+				found = true;
+		}
+		if (!found)
 			return;
 			return;
 	}
 	}
 
 
@@ -4922,7 +5010,17 @@ void BfCompiler::GetSymbolReferences()
 				for (auto checkTypeDef : typeDef->mPartials)
 				for (auto checkTypeDef : typeDef->mPartials)
 				{
 				{
 					auto nameNode = checkTypeDef->mTypeDeclaration->mNameNode;
 					auto nameNode = checkTypeDef->mTypeDeclaration->mNameNode;
-					if ((mResolvePassData->mParser == NULL) || (nameNode->IsFromParser(mResolvePassData->mParser)))
+
+					for (auto parser : mResolvePassData->mParsers)
+					{
+						if (nameNode->IsFromParser(parser))
+						{							
+							mResolvePassData->HandleTypeReference(nameNode, typeDef);
+							break;
+						}
+					}
+
+					if (mResolvePassData->mParsers.IsEmpty())
 						mResolvePassData->HandleTypeReference(nameNode, typeDef);
 						mResolvePassData->HandleTypeReference(nameNode, typeDef);
 
 
 					if (checkTypeDef->IsExtension())
 					if (checkTypeDef->IsExtension())
@@ -5365,9 +5463,7 @@ bool BfCompiler::IsDataResolvePass()
 
 
 bool BfCompiler::WantsClassifyNode(BfAstNode* node)
 bool BfCompiler::WantsClassifyNode(BfAstNode* node)
 {
 {
-	return ((mResolvePassData != NULL) &&
-		(node->IsFromParser(mResolvePassData->mParser)) &&
-		(mResolvePassData->mSourceClassifier != NULL));
+	return (mResolvePassData != NULL) && (mResolvePassData->GetSourceClassifier(node) != NULL);		
 }
 }
 
 
 BfAutoComplete* BfCompiler::GetAutoComplete()
 BfAutoComplete* BfCompiler::GetAutoComplete()
@@ -6673,7 +6769,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 	mHasComptimeRebuilds = false;
 	mHasComptimeRebuilds = false;
 	int revision = mRevision;
 	int revision = mRevision;
 	BfLogSysM("Compile Start. Revision: %d. HasParser:%d AutoComplete:%d\n", revision, 
 	BfLogSysM("Compile Start. Revision: %d. HasParser:%d AutoComplete:%d\n", revision, 
-		(mResolvePassData != NULL) && (mResolvePassData->mParser != NULL), 
+		(mResolvePassData != NULL) && (!mResolvePassData->mParsers.IsEmpty()), 
 		(mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL));
 		(mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL));
 
 
 	if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
 	if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
@@ -6785,7 +6881,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 	BfTypeDef* typeDef;						
 	BfTypeDef* typeDef;						
 
 
 	BfLogSysM("UpdateRevisedTypes Revision %d. ResolvePass:%d CursorIdx:%d\n", mRevision, mIsResolveOnly, 
 	BfLogSysM("UpdateRevisedTypes Revision %d. ResolvePass:%d CursorIdx:%d\n", mRevision, mIsResolveOnly, 
-		((mResolvePassData == NULL) || (mResolvePassData->mParser == NULL)) ? - 1 : mResolvePassData->mParser->mCursorIdx);	
+		((mResolvePassData == NULL) || (mResolvePassData->mParsers.IsEmpty())) ? - 1 : mResolvePassData->mParsers[0]->mCursorIdx);
 	
 	
 	mCompileState = CompileState_Normal;
 	mCompileState = CompileState_Normal;
 	UpdateRevisedTypes();	
 	UpdateRevisedTypes();	
@@ -7455,7 +7551,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 		}
 		}
 		else
 		else
 		{
 		{
-			bool isTargeted = (mResolvePassData != NULL) && (mResolvePassData->mParser != NULL);
+			bool isTargeted = (mResolvePassData != NULL) && (!mResolvePassData->mParsers.IsEmpty());
 			if (!isTargeted)
 			if (!isTargeted)
 			{				
 			{				
 				for (auto bfModule : mContext->mModules)
 				for (auto bfModule : mContext->mModules)
@@ -7477,7 +7573,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 	//CompileLog("%d object files written: %s\n", numModulesWritten, moduleListStr.c_str());
 	//CompileLog("%d object files written: %s\n", numModulesWritten, moduleListStr.c_str());
 	
 	
 	//printf("Compile done, waiting for finish\n");
 	//printf("Compile done, waiting for finish\n");
-
+	
 	while (true)
 	while (true)
 	{		
 	{		
 		if (mCanceling)
 		if (mCanceling)
@@ -7543,7 +7639,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 		libManager->mErrors.Clear();
 		libManager->mErrors.Clear();
 	}
 	}
 #endif		
 #endif		
-
+	
 	int numObjFilesWritten = 0;
 	int numObjFilesWritten = 0;
 	for (auto& fileEntry : mCodeGen.mCodeGenFiles)
 	for (auto& fileEntry : mCodeGen.mCodeGenFiles)
 	{
 	{
@@ -7588,7 +7684,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 
 
 	String compileInfo;
 	String compileInfo;
 	if (mIsResolveOnly)
 	if (mIsResolveOnly)
-		compileInfo += StrFormat("ResolveOnly ResolveType:%d Parser:%d\n", mResolvePassData->mResolveType, mResolvePassData->mParser != NULL);
+		compileInfo += StrFormat("ResolveOnly ResolveType:%d Parser:%d\n", mResolvePassData->mResolveType, !mResolvePassData->mParsers.IsEmpty());
 	compileInfo += StrFormat("TotalTypes:%d\nTypesPopulated:%d\nMethodsDeclared:%d\nMethodsProcessed:%d\nCanceled? %d\n", mStats.mTotalTypes, mStats.mTypesPopulated, mStats.mMethodDeclarations, mStats.mMethodsProcessed, mCanceling);
 	compileInfo += StrFormat("TotalTypes:%d\nTypesPopulated:%d\nMethodsDeclared:%d\nMethodsProcessed:%d\nCanceled? %d\n", mStats.mTotalTypes, mStats.mTypesPopulated, mStats.mMethodDeclarations, mStats.mMethodsProcessed, mCanceling);
 	compileInfo += StrFormat("TypesPopulated:%d\n", mStats.mTypesPopulated);
 	compileInfo += StrFormat("TypesPopulated:%d\n", mStats.mTypesPopulated);
 	compileInfo += StrFormat("MethodDecls:%d\nMethodsProcessed:%d\nModulesStarted:%d\nModulesFinished:%d\n", mStats.mMethodDeclarations, mStats.mMethodsProcessed, mStats.mModulesFinished);
 	compileInfo += StrFormat("MethodDecls:%d\nMethodsProcessed:%d\nModulesStarted:%d\nModulesFinished:%d\n", mStats.mMethodDeclarations, mStats.mMethodsProcessed, mStats.mModulesFinished);
@@ -7854,8 +7950,11 @@ void BfCompiler::GenerateAutocompleteInfo()
 
 
 			if (autoComplete->mInsertEndIdx > 0)
 			if (autoComplete->mInsertEndIdx > 0)
 			{
 			{
-				if (mResolvePassData->mParser->mSrc[autoComplete->mInsertEndIdx - 1] == '!')
-					autoComplete->mInsertEndIdx--;
+				if (!mResolvePassData->mParsers.IsEmpty())
+				{
+					if (mResolvePassData->mParsers[0]->mSrc[autoComplete->mInsertEndIdx - 1] == '!')
+						autoComplete->mInsertEndIdx--;
+				}
 			}
 			}
 		}
 		}
 
 
@@ -9065,17 +9164,75 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
 	return result;
 	return result;
 }
 }
 
 
+int BfCompiler::GetTypeId(const StringImpl& typeName)
+{	
+	auto type = GetType(typeName);
+	if (type != NULL)
+		return type->mTypeId;
+	return -1;
+}
+
+BfType* BfCompiler::GetType(const StringImpl& fullTypeName)
+{
+	AutoCrit autoCrit(mSystem->mSystemLock);
+
+	BfPassInstance passInstance(mSystem);
+
+	BfProject* activeProject = NULL;
+	
+	String typeName = fullTypeName;
+	int colonPos = (int)typeName.IndexOf(':');
+	if (colonPos != -1)
+	{
+		activeProject = mSystem->GetProject(typeName.Substring(0, colonPos));
+		typeName.Remove(0, colonPos + 1);
+	}
+
+	BfTypeState typeState;
+	typeState.mPrevState = mContext->mCurTypeState;
+	typeState.mActiveProject = activeProject;
+	SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
+
+	BfParser parser(mSystem);
+	parser.SetSource(typeName.c_str(), (int)typeName.length());
+	parser.Parse(&passInstance);
+
+	BfReducer reducer;
+	reducer.mAlloc = parser.mAlloc;
+	reducer.mPassInstance = &passInstance;
+
+	if (parser.mRootNode->mChildArr.mSize == 0)
+		return NULL;
+
+	auto firstNode = parser.mRootNode->mChildArr[0];
+	auto endIdx = parser.mRootNode->mSrcEnd;
+	reducer.mVisitorPos = BfReducer::BfVisitorPos(parser.mRootNode);
+
+	reducer.mVisitorPos.MoveNext();
+	auto typeRef = reducer.CreateTypeRef(firstNode);
+	if (typeRef == NULL)
+		return NULL;
+
+	BfResolvePassData resolvePass;
+	SetAndRestoreValue<bool> prevIgnoreError(mContext->mScratchModule->mIgnoreErrors, true);
+	SetAndRestoreValue<bool> prevIgnoreWarnings(mContext->mScratchModule->mIgnoreWarnings, true);
+	SetAndRestoreValue<BfResolvePassData*> prevResolvePass(mResolvePassData, &resolvePass);
+
+	auto type = mContext->mScratchModule->ResolveTypeRef(typeRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoCreate | BfResolveTypeRefFlag_AllowUnboundGeneric));
+	if (type != NULL)
+		return type;
+
+	return NULL;
+}
+
 int BfCompiler::GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer)
 int BfCompiler::GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer)
 {	
 {	
 	int lastDollarPos = (int)fileName.LastIndexOf('$');
 	int lastDollarPos = (int)fileName.LastIndexOf('$');
 	if (lastDollarPos == -1)
 	if (lastDollarPos == -1)
 		return -1;	
 		return -1;	
-	int dotPos = (int)fileName.LastIndexOf('.');
-	if (dotPos == -1)
-		return -1;
 	
 	
-	String typeIdStr = fileName.Substring(lastDollarPos + 1, dotPos - lastDollarPos - 1);	
-	int typeId = (int)atoi(typeIdStr.c_str());
+	String typeName = fileName.Substring(lastDollarPos + 1);	
+	int typeId = GetTypeId(typeName);
 	if ((typeId <= 0) || (typeId >= mContext->mTypes.mSize))
 	if ((typeId <= 0) || (typeId >= mContext->mTypes.mSize))
 		return -1;
 		return -1;
 
 
@@ -9097,6 +9254,96 @@ int BfCompiler::GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer)
 	return typeInst->mRevision;
 	return typeInst->mRevision;
 }
 }
 
 
+String BfCompiler::GetEmitLocation(const StringImpl& typeName, int emitLine, int& outEmbedLine, int& outEmbedLineChar)
+{
+	outEmbedLine = 0;
+
+	int typeId = GetTypeId(typeName);
+	if (typeId <= 0)
+		return "";
+
+	auto bfType = mContext->FindTypeById(typeId);
+	if (bfType == NULL)
+		return "";
+
+	auto typeInst = bfType->ToTypeInstance();
+	if (typeInst == NULL)
+		return "";
+
+	if (typeInst->mCeTypeInfo == NULL)
+		return "";
+
+	for (auto& kv : typeInst->mCeTypeInfo->mEmitSourceMap)
+	{
+		int partialIdx = (int)(kv.mKey >> 32);
+		int charIdx = (int)(kv.mKey & 0xFFFFFFFF);
+
+		auto typeDef = typeInst->mTypeDef;
+		if (partialIdx > 0)
+			typeDef = typeDef->mPartials[partialIdx];
+
+		auto origParser = typeDef->GetDefinition()->GetLastSource()->ToParser();
+		if (origParser == NULL)
+			continue;
+
+		auto emitParser = typeInst->mTypeDef->GetLastSource()->ToParser();
+		if (emitParser == NULL)
+			continue;
+
+		int startLine = 0;
+		int startLineChar = 0;
+		emitParser->GetLineCharAtIdx(kv.mValue.mSrcStart, startLine, startLineChar);
+
+		int endLine = 0;
+		int endLineChar = 0;
+		emitParser->GetLineCharAtIdx(kv.mValue.mSrcEnd - 1, endLine, endLineChar);
+
+		if ((emitLine >= startLine) && (emitLine <= endLine))
+		{			
+			origParser->GetLineCharAtIdx(charIdx, outEmbedLine, outEmbedLineChar);
+			return origParser->mFileName;
+		}
+	}
+
+	return "";
+}
+
+bool BfCompiler::WriteEmitData(const StringImpl& filePath, BfProject* project)
+{
+	ZipFile zipFile;
+
+	for (auto type : mContext->mResolvedTypes)
+	{
+		auto typeInst = type->ToTypeInstance();
+		if (typeInst == NULL)
+			continue;
+		if (typeInst->mTypeDef->mEmitParent == NULL)
+			continue;
+		if (!project->ContainsReference(typeInst->mTypeDef->mProject))
+			continue;
+
+		auto bfParser = typeInst->mTypeDef->GetLastSource()->ToParser();
+		String name = bfParser->mFileName;
+		if (name.StartsWith("$Emit$"))
+			name.Remove(0, 6);
+		String path = EncodeFileName(name);
+		path.Append(".bf");
+
+		if (!zipFile.IsOpen())
+		{
+			if (!zipFile.Create(filePath))
+				return false;
+		}
+
+		zipFile.Add(path, Span<uint8>((uint8*)bfParser->mSrc, bfParser->mSrcLength));
+	}
+
+	if (zipFile.IsOpen())
+		return zipFile.Close();
+
+	return true;
+}
+
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
 
 PerfManager* BfGetPerfManager(BfParser* bfParser);
 PerfManager* BfGetPerfManager(BfParser* bfParser);
@@ -9122,57 +9369,33 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_ClearResults(BfCompiler* bfCompiler)
 	bfCompiler->ClearResults();
 	bfCompiler->ClearResults();
 }
 }
 
 
-BF_EXPORT bool BF_CALLTYPE BfCompiler_ClassifySource(BfCompiler* bfCompiler, BfPassInstance* bfPassInstance, BfParser* bfParser, BfResolvePassData* resolvePassData, BfSourceClassifier::CharData* charData)
+BF_EXPORT bool BF_CALLTYPE BfCompiler_ClassifySource(BfCompiler* bfCompiler, BfPassInstance* bfPassInstance, BfResolvePassData* resolvePassData)
 {
 {
 	BP_ZONE("BfCompiler_ClassifySource");	
 	BP_ZONE("BfCompiler_ClassifySource");	
-	BfSourceClassifier bfSourceClassifier(bfParser, charData);
-	bfSourceClassifier.mClassifierPassId = bfPassInstance->mClassifierPassId;
 	
 	
 	String& autoCompleteResultString = *gTLStrReturn.Get();
 	String& autoCompleteResultString = *gTLStrReturn.Get();
 	autoCompleteResultString.clear();
 	autoCompleteResultString.clear();
-
-	bool doClassifyPass = (charData != NULL) && (resolvePassData->mResolveType <= BfResolveType_Autocomplete_HighPri); 
-	bfSourceClassifier.mEnabled = doClassifyPass;
-
-	// Full classifier pass?
 	
 	
-	bfSourceClassifier.mSkipMethodInternals = true;	
-	bfSourceClassifier.mSkipTypeDeclarations = true;	
-	if (charData != NULL)
-	{
-		resolvePassData->mSourceClassifier = &bfSourceClassifier;
-		if (doClassifyPass)
-			bfSourceClassifier.Visit(bfParser->mRootNode);
-	}
-	bfSourceClassifier.mSkipTypeDeclarations = false;
-	bfSourceClassifier.mSkipMethodInternals = false;		
-
-	bfPassInstance->mFilterErrorsTo = bfParser;
+	bfPassInstance->mCompiler = bfCompiler;
+	for (auto parser : resolvePassData->mParsers)
+		bfPassInstance->mFilterErrorsTo.Add(parser->mSourceData);	
 	bfPassInstance->mTrimMessagesToCursor = true;
 	bfPassInstance->mTrimMessagesToCursor = true;
+
 	SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, resolvePassData);
 	SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, resolvePassData);
 	SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, bfPassInstance);
 	SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, bfPassInstance);
 	bool canceled = false;
 	bool canceled = false;
-	if (resolvePassData->mAutoComplete != NULL)
-	{		
+	
+	if ((resolvePassData->mAutoComplete != NULL) && (!resolvePassData->mParsers.IsEmpty()))
+	{
 		bfCompiler->ProcessAutocompleteTempType();
 		bfCompiler->ProcessAutocompleteTempType();
 	}
 	}
 	else
 	else
-		canceled = !bfCompiler->Compile("");	
-	resolvePassData->mSourceClassifier = NULL;
+		canceled = !bfCompiler->Compile("");
 		
 		
-	if ((charData != NULL) && (doClassifyPass))
-	{
-		bfSourceClassifier.mIsSideChannel = false;
-		bfSourceClassifier.Visit(bfParser->mErrorRootNode);
-
-		bfSourceClassifier.mIsSideChannel = true;
-		bfSourceClassifier.Visit(bfParser->mSidechannelRootNode);				
-	}
-
 	return !canceled;
 	return !canceled;
 }
 }
 
 
-BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCompiler, BfParser* bfParser)
+BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCompiler, BfParser* bfParser, BfResolvePassData* resolvePassData, char* explicitEmitTypeNames)
 {
 {
 	String& outString = *gTLStrReturn.Get();
 	String& outString = *gTLStrReturn.Get();
 	outString.Clear();
 	outString.Clear();
@@ -9515,6 +9738,112 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCo
 
 
 	collapseVisitor.FlushSeries();
 	collapseVisitor.FlushSeries();
 
 
+	Array<BfTypeInstance*> explicitEmitTypes;
+	String checkStr = explicitEmitTypeNames;
+	for (auto& typeName : checkStr.Split('\n'))
+	{
+		if (typeName.IsEmpty())
+			continue;
+		auto bfType = bfCompiler->GetType(typeName);
+		if ((bfType != NULL) && (bfType->IsTypeInstance()))
+			explicitEmitTypes.Add(bfType->ToTypeInstance());
+	}
+
+	// Embed emit info
+	BfPassInstance bfPassInstance(bfCompiler->mSystem);
+
+	SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, resolvePassData);
+	SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, &bfPassInstance);
+
+	Dictionary<int, int> foundTypeIds;
+
+	for (auto typeDef : bfParser->mTypeDefs)
+	{
+		auto useTypeDef = typeDef;
+		if (useTypeDef->mIsPartial)
+		{
+			useTypeDef = bfCompiler->mSystem->GetCombinedPartial(useTypeDef);
+			if (useTypeDef == NULL)
+				continue;
+		}
+
+		auto type = bfCompiler->mContext->mScratchModule->ResolveTypeDef(useTypeDef);
+		if (type == NULL)
+			continue;
+		if (auto typeInst = type->ToTypeInstance())
+		{
+			auto origTypeInst = typeInst;
+
+			if (typeInst->mCeTypeInfo == NULL)
+				continue;
+			
+			for (auto checkIdx = explicitEmitTypes.mSize - 1; checkIdx >= 0; checkIdx--)
+			{
+				auto checkType = explicitEmitTypes[checkIdx];
+				if (checkType->mTypeDef->GetDefinition()->GetLatest() == typeInst->mTypeDef->GetDefinition()->GetLatest())
+				{
+					typeInst = checkType;
+					bfCompiler->mContext->mScratchModule->PopulateType(typeInst);
+					break;
+				}
+			}
+
+			for (auto& kv : typeInst->mCeTypeInfo->mEmitSourceMap)
+			{
+				int partialIdx = (int)(kv.mKey >> 32);
+				int charIdx = (int)(kv.mKey & 0xFFFFFFFF);
+
+				auto typeDef = typeInst->mTypeDef;
+				if (partialIdx > 0)
+					typeDef = typeDef->mPartials[partialIdx];
+
+				auto parser = typeDef->GetDefinition()->GetLastSource()->ToParser();
+				if (parser == NULL)
+					continue;
+
+				if (!FileNameEquals(parser->mFileName, bfParser->mFileName))
+					continue;
+				
+				auto emitParser = typeInst->mTypeDef->GetLastSource()->ToParser();
+				if (emitParser == NULL)
+					continue;
+
+				int startLine = 0;
+				int startLineChar = 0;
+				emitParser->GetLineCharAtIdx(kv.mValue.mSrcStart, startLine, startLineChar);
+
+				int srcEnd = kv.mValue.mSrcEnd - 1;
+				while (srcEnd >= kv.mValue.mSrcStart)
+				{
+					char c = emitParser->mSrc[srcEnd];
+					if (!::isspace((uint8)c))
+						break;
+					srcEnd--;
+				}
+
+				int endLine = 0;
+				int endLineChar = 0;
+				emitParser->GetLineCharAtIdx(srcEnd, endLine, endLineChar);
+				
+				int dollarPos = (int)emitParser->mFileName.LastIndexOf('$');
+				if (dollarPos == -1)
+					continue;
+
+				int* keyPtr = NULL;
+				int* valuePtr = NULL;
+				if (foundTypeIds.TryAdd(typeInst->mTypeId, &keyPtr, &valuePtr))
+				{
+					*valuePtr = foundTypeIds.mCount - 1;
+					outString += "+";
+					outString += emitParser->mFileName.Substring(dollarPos + 1);
+					outString += "\n";
+				}
+
+				outString += (kv.mValue.mKind == BfCeTypeEmitSourceKind_Method) ? 'm' : 't';
+				outString += StrFormat("%d,%d,%d,%d,%d,%d\n", *valuePtr, typeInst->mRevision, partialIdx, charIdx, startLine, endLine + 1);
+			}
+		}
+	}
 	
 	
 	return outString.c_str();
 	return outString.c_str();
 }
 }
@@ -9587,7 +9916,7 @@ BF_EXPORT bool BF_CALLTYPE BfCompiler_VerifyTypeName(BfCompiler* bfCompiler, cha
 		resolvePassData.mAutoComplete->mCompiler = bfCompiler;
 		resolvePassData.mAutoComplete->mCompiler = bfCompiler;
 		resolvePassData.mAutoComplete->mModule = bfCompiler->mContext->mScratchModule;
 		resolvePassData.mAutoComplete->mModule = bfCompiler->mContext->mScratchModule;
 	}
 	}
-	resolvePassData.mParser = &parser;
+	resolvePassData.mParsers.Add(&parser);
 			
 			
 	SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, &resolvePassData);
 	SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, &resolvePassData);
 	SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, &passInstance);
 	SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, &passInstance);
@@ -9733,6 +10062,11 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefInfo(BfCompiler* bfCompil
 	return outString.c_str();
 	return outString.c_str();
 }
 }
 
 
+BF_EXPORT int BF_CALLTYPE BfCompiler_GetTypeId(BfCompiler* bfCompiler, const char* name)
+{
+	return bfCompiler->GetTypeId(name);	
+}
+
 BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeInfo(BfCompiler* bfCompiler, const char* name)
 BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeInfo(BfCompiler* bfCompiler, const char* name)
 {
 {
 	String& outString = *gTLStrReturn.Get();
 	String& outString = *gTLStrReturn.Get();
@@ -9820,6 +10154,40 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeInfo(BfCompiler* bfCompiler,
 	return outString.c_str();
 	return outString.c_str();
 }
 }
 
 
+BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetGenericTypeInstances(BfCompiler* bfCompiler, const char* typeName)
+{
+	String& outString = *gTLStrReturn.Get();
+	outString = "";
+
+	auto lookupType = bfCompiler->GetType(typeName);
+	if (lookupType == NULL)
+		return "";
+
+	auto lookupTypeInst = lookupType->ToTypeInstance();
+	if (lookupTypeInst == NULL)
+		return "";
+
+	for (auto type : bfCompiler->mContext->mResolvedTypes)
+	{
+		auto typeInst = type->ToTypeInstance();
+		if (typeInst == NULL)
+			continue;
+
+		if (typeInst->IsUnspecializedTypeVariation())
+			continue;
+
+		if (typeInst->mTypeDef->GetDefinition()->GetLatest() == lookupTypeInst->mTypeDef->GetDefinition()->GetLatest())
+		{
+			outString += typeInst->mTypeDef->mProject->mName;
+			outString += ":";
+			outString += bfCompiler->mContext->mScratchModule->TypeToString(typeInst, BfTypeNameFlags_None);
+			outString += "\n";
+		}
+	}
+
+	return outString.c_str();
+}
+
 enum BfUsedOutputFlags
 enum BfUsedOutputFlags
 {
 {
 	BfUsedOutputFlags_None = 0,
 	BfUsedOutputFlags_None = 0,
@@ -10236,3 +10604,16 @@ BF_EXPORT int32 BF_CALLTYPE BfCompiler_GetEmitSourceVersion(BfCompiler* bfCompil
 {
 {
 	return bfCompiler->GetEmitSource(fileName, NULL);
 	return bfCompiler->GetEmitSource(fileName, NULL);
 }
 }
+
+BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetEmitLocation(BfCompiler* bfCompiler, char* typeName, int line, int& outEmbedLine, int& outEmbedLineChar)
+{
+	String& outString = *gTLStrReturn.Get();
+	outString.clear();
+	outString = bfCompiler->GetEmitLocation(typeName, line, outEmbedLine, outEmbedLineChar);
+	return outString.c_str();
+}
+
+BF_EXPORT bool BF_CALLTYPE BfCompiler_WriteEmitData(BfCompiler* bfCompiler, char* filePath, BfProject* project)
+{
+	return bfCompiler->WriteEmitData(filePath, project);
+}

+ 4 - 0
IDEHelper/Compiler/BfCompiler.h

@@ -543,7 +543,11 @@ public:
 	String GetTypeDefMatches(const StringImpl& searchSrc);	
 	String GetTypeDefMatches(const StringImpl& searchSrc);	
 	void GetTypeDefs(const StringImpl& typeName, Array<BfTypeDef*>& typeDefs);
 	void GetTypeDefs(const StringImpl& typeName, Array<BfTypeDef*>& typeDefs);
 	String GetTypeDefInfo(const StringImpl& typeName);	
 	String GetTypeDefInfo(const StringImpl& typeName);	
+	int GetTypeId(const StringImpl& typeName);
+	BfType* GetType(const StringImpl& typeName);
 	int GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer);
 	int GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer);
+	String GetEmitLocation(const StringImpl& typeName, int line, int& outEmbedLine, int& outEmbedLineChar);
+	bool WriteEmitData(const StringImpl& filePath, BfProject* project);
 
 
 	void CompileLog(const char* fmt ...);
 	void CompileLog(const char* fmt ...);
 	void ReportMemory(MemReporter* memReporter);
 	void ReportMemory(MemReporter* memReporter);

+ 20 - 12
IDEHelper/Compiler/BfContext.cpp

@@ -355,8 +355,8 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
 	while (!mCompiler->mCanceling)
 	while (!mCompiler->mCanceling)
 	{		
 	{		
 		BfParser* resolveParser = NULL;
 		BfParser* resolveParser = NULL;
-		if (mCompiler->mResolvePassData != NULL)
-			resolveParser = mCompiler->mResolvePassData->mParser;
+		if ((mCompiler->mResolvePassData != NULL) && (!mCompiler->mResolvePassData->mParsers.IsEmpty()))
+			resolveParser = mCompiler->mResolvePassData->mParsers[0];
 
 
 		bool didWork = false;				
 		bool didWork = false;				
 		
 		
@@ -549,8 +549,16 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
 
 
 				BF_ASSERT(!module->mAwaitingFinish);
 				BF_ASSERT(!module->mAwaitingFinish);
 				if ((resolveParser != NULL) && (methodInstance->mMethodDef->mDeclaringType != NULL) && (methodInstance->mMethodDef->mDeclaringType->GetDefinition()->mSource != resolveParser))
 				if ((resolveParser != NULL) && (methodInstance->mMethodDef->mDeclaringType != NULL) && (methodInstance->mMethodDef->mDeclaringType->GetDefinition()->mSource != resolveParser))
-				{					
-					continue;
+				{
+					bool allow = false;
+					if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mHasCursorIdx))
+					{
+						auto parser = methodInstance->mMethodDef->mDeclaringType->GetLastSource()->ToParser();
+						if ((parser != NULL) && (parser->mCursorIdx >= 0))
+							allow = true;
+					}
+					if (!allow)
+						continue;
 				}
 				}
 				
 				
 				hasBeenProcessed = methodInstance->mHasBeenProcessed;
 				hasBeenProcessed = methodInstance->mHasBeenProcessed;
@@ -722,7 +730,7 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
 				BP_ZONE("PWL_CheckIncompleteGenerics");				
 				BP_ZONE("PWL_CheckIncompleteGenerics");				
 
 
 				for (auto type : mResolvedTypes)
 				for (auto type : mResolvedTypes)
-				{					
+				{
 					if ((type->IsIncomplete()) && (type->HasBeenReferenced()))
 					if ((type->IsIncomplete()) && (type->HasBeenReferenced()))
 					{
 					{
 						// The only reason a type instance wouldn't have already been in the work list is
 						// The only reason a type instance wouldn't have already been in the work list is
@@ -759,12 +767,13 @@ void BfContext::HandleChangedTypeDef(BfTypeDef* typeDef, bool isAutoCompleteTemp
 {
 {
 	BF_ASSERT(typeDef->mEmitParent == NULL);
 	BF_ASSERT(typeDef->mEmitParent == NULL);
 
 
-	if ((mCompiler->mResolvePassData == NULL) || (!typeDef->HasSource(mCompiler->mResolvePassData->mParser)))
+	if ((mCompiler->mResolvePassData == NULL) || (mCompiler->mResolvePassData->mParsers.IsEmpty()) ||
+		(!typeDef->HasSource(mCompiler->mResolvePassData->mParsers[0])))
 		return;
 		return;
 
 
 	if (typeDef->mDefState != BfTypeDef::DefState_Defined)
 	if (typeDef->mDefState != BfTypeDef::DefState_Defined)
 	{		
 	{		
-		if (mCompiler->mResolvePassData->mSourceClassifier != NULL)
+		if (mCompiler->mResolvePassData->mIsClassifying)		
 		{							
 		{							
 			auto _CheckSource = [&](BfTypeDef* checkTypeDef)
 			auto _CheckSource = [&](BfTypeDef* checkTypeDef)
 			{
 			{
@@ -774,12 +783,11 @@ void BfContext::HandleChangedTypeDef(BfTypeDef* typeDef, bool isAutoCompleteTemp
 				if (typeDecl == NULL)
 				if (typeDecl == NULL)
 					return;
 					return;
 
 
-				if (typeDecl->GetSourceData() == mCompiler->mResolvePassData->mParser->mSourceData)
+				if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(typeDecl))
 				{
 				{
-					SetAndRestoreValue<bool> prevSkipTypeDeclaration(mCompiler->mResolvePassData->mSourceClassifier->mSkipTypeDeclarations, true);
-					auto classifier = mCompiler->mResolvePassData->mSourceClassifier;
-					classifier->mSkipMethodInternals = isAutoCompleteTempType;
-					classifier->Handle(typeDecl);
+					SetAndRestoreValue<bool> prevSkipTypeDeclaration(sourceClassifier->mSkipTypeDeclarations, true);					
+					sourceClassifier->mSkipMethodInternals = isAutoCompleteTempType;
+					sourceClassifier->Handle(typeDecl);
 				}
 				}
 			};
 			};
 
 

+ 2 - 0
IDEHelper/Compiler/BfContext.h

@@ -156,6 +156,7 @@ public:
 	BfFieldDef* mCurFieldDef;	
 	BfFieldDef* mCurFieldDef;	
 	BfTypeDef* mCurTypeDef;
 	BfTypeDef* mCurTypeDef;
 	BfTypeDef* mForceActiveTypeDef;	
 	BfTypeDef* mForceActiveTypeDef;	
+	BfProject* mActiveProject;
 	ResolveKind mResolveKind;
 	ResolveKind mResolveKind;
 	BfAstNode* mCurVarInitializer;
 	BfAstNode* mCurVarInitializer;
 	int mArrayInitializerSize;
 	int mArrayInitializerSize;
@@ -174,6 +175,7 @@ public:
 		mCurAttributeTypeRef = NULL;
 		mCurAttributeTypeRef = NULL;
 		mCurTypeDef = NULL;
 		mCurTypeDef = NULL;
 		mForceActiveTypeDef = NULL;
 		mForceActiveTypeDef = NULL;
+		mActiveProject = NULL;
 		mCurVarInitializer = NULL;
 		mCurVarInitializer = NULL;
 		mArrayInitializerSize = -1;
 		mArrayInitializerSize = -1;
 		mResolveKind = ResolveKind_None;
 		mResolveKind = ResolveKind_None;

+ 20 - 9
IDEHelper/Compiler/BfDefBuilder.cpp

@@ -153,8 +153,12 @@ void BfDefBuilder::Visit(BfIdentifierNode* identifier)
 //  already been handled, so we need to ignore that space while determining if we're "inside" this method or not during
 //  already been handled, so we need to ignore that space while determining if we're "inside" this method or not during
 //  autocompletion
 //  autocompletion
 bool BfDefBuilder::WantsNode(BfAstNode* wholeNode, BfAstNode* startNode, int addLen)
 bool BfDefBuilder::WantsNode(BfAstNode* wholeNode, BfAstNode* startNode, int addLen)
-{	
-	if ((mResolvePassData == NULL) || (mResolvePassData->mParser->mCursorIdx == -1))
+{		
+	if ((mResolvePassData == NULL) || (!mResolvePassData->mHasCursorIdx))
+		return true;
+
+	auto parser = wholeNode->GetParser();
+	if (parser->mCursorIdx == -1)
 		return true;
 		return true;
 
 
 	// We need to get all nodes when we get fixits because the cursor could be either before or after fields with
 	// We need to get all nodes when we get fixits because the cursor could be either before or after fields with
@@ -163,9 +167,9 @@ bool BfDefBuilder::WantsNode(BfAstNode* wholeNode, BfAstNode* startNode, int add
 		//return true;
 		//return true;
 
 
 	addLen++;
 	addLen++;
-	if ((mResolvePassData->mParser->mCursorIdx >= wholeNode->GetSrcStart()) && (mResolvePassData->mParser->mCursorIdx < wholeNode->GetSrcEnd() + addLen))
+	if ((parser->mCursorIdx >= wholeNode->GetSrcStart()) && (parser->mCursorIdx < wholeNode->GetSrcEnd() + addLen))
 	{
 	{
-		if ((startNode == NULL) || (mResolvePassData->mParser->mCursorIdx >= startNode->GetSrcStart()))
+		if ((startNode == NULL) || (parser->mCursorIdx >= startNode->GetSrcStart()))
 			return true;
 			return true;
 	}
 	}
 	return false; 
 	return false; 
@@ -1417,13 +1421,20 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
 	{
 	{
 		isAutoCompleteTempType = (mResolvePassData->mAutoComplete != NULL);
 		isAutoCompleteTempType = (mResolvePassData->mAutoComplete != NULL);
 
 
-		int cursorIdx = mResolvePassData->mParser->mCursorIdx;		
-		if (typeDeclaration->Contains(cursorIdx, 1, 0))
+		if (mResolvePassData->mHasCursorIdx)
 		{
 		{
-			// Within bounds
+			auto parser = typeDeclaration->GetParser();
+			if (parser != NULL)
+			{
+				int cursorIdx = parser->mCursorIdx;
+				if (typeDeclaration->Contains(cursorIdx, 1, 0))
+				{
+					// Within bounds
+				}
+				else if (cursorIdx != -1)
+					return;
+			}
 		}
 		}
-		else if (cursorIdx != -1)
-			return;
 	}
 	}
 
 
 	int curLine = 0;
 	int curLine = 0;

+ 10 - 6
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -4260,7 +4260,8 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
 			
 			
 			if ((resolvingFieldDef != NULL) && 
 			if ((resolvingFieldDef != NULL) && 
 				(mModule->mCompiler->mResolvePassData != NULL) && 
 				(mModule->mCompiler->mResolvePassData != NULL) && 
-				(mModule->mCompiler->mResolvePassData->mParser == resolvingFieldDef->mFieldDeclaration->GetParser()) &&
+				(!mModule->mCompiler->mResolvePassData->mParsers.IsEmpty()) &&
+				(mModule->mCompiler->mResolvePassData->mParsers[0] == resolvingFieldDef->mFieldDeclaration->GetParser()) &&
 				(GetAutoComplete() != NULL))
 				(GetAutoComplete() != NULL))
 			{
 			{
 				return mModule->GetDefaultTypedValue(mModule->mCurTypeInstance);
 				return mModule->GetDefaultTypedValue(mModule->mCurTypeInstance);
@@ -8805,7 +8806,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 	auto autoComplete = GetAutoComplete();
 	auto autoComplete = GetAutoComplete();
 	if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo))
 	if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo))
 	{
 	{
-		if ((!targetSrc->IsFromParser(mModule->mCompiler->mResolvePassData->mParser)) ||
+		if ((!targetSrc->IsFromParser(mModule->mCompiler->mResolvePassData->mParsers[0])) ||
 			((autoComplete->mMethodMatchInfo->mInvocationSrcIdx != -1) && (autoComplete->mMethodMatchInfo->mInvocationSrcIdx != targetSrc->GetSrcStart())))
 			((autoComplete->mMethodMatchInfo->mInvocationSrcIdx != -1) && (autoComplete->mMethodMatchInfo->mInvocationSrcIdx != targetSrc->GetSrcStart())))
 		{
 		{
 			autoComplete->mIsCapturingMethodMatchInfo = false;
 			autoComplete->mIsCapturingMethodMatchInfo = false;
@@ -9247,10 +9248,13 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 		}
 		}
 
 
 		if (enumResult)
 		if (enumResult)
-		{
-			if (mModule->mCompiler->WantsClassifyNode(targetSrc))
+		{			
+			if (mModule->mCompiler->mResolvePassData != NULL)
 			{
 			{
-				mModule->mCompiler->mResolvePassData->mSourceClassifier->SetElementType(targetSrc, BfSourceElementType_Normal);
+				if (auto sourceClassifier = mModule->mCompiler->mResolvePassData->GetSourceClassifier(targetSrc))
+				{
+					sourceClassifier->SetElementType(targetSrc, BfSourceElementType_Normal);
+				}
 			}
 			}
 			return enumResult;
 			return enumResult;
 		}
 		}
@@ -14444,7 +14448,7 @@ void BfExprEvaluator::CheckObjectCreateTypeRef(BfType* expectingType, BfAstNode*
 {
 {
 	auto autoComplete = GetAutoComplete();	
 	auto autoComplete = GetAutoComplete();	
 	if ((autoComplete != NULL) && (afterNode != NULL) && (autoComplete->mIsAutoComplete) &&
 	if ((autoComplete != NULL) && (afterNode != NULL) && (autoComplete->mIsAutoComplete) &&
-		(afterNode->IsFromParser(mModule->mCompiler->mResolvePassData->mParser)) &&
+		(afterNode->IsFromParser(mModule->mCompiler->mResolvePassData->mParsers[0])) &&
 		(afterNode->GetParser()->mCursorIdx == afterNode->GetSrcEnd() + 1))
 		(afterNode->GetParser()->mCursorIdx == afterNode->GetSrcEnd() + 1))
 	{
 	{
 		BfType* expectingType = mExpectingType;
 		BfType* expectingType = mExpectingType;

+ 45 - 32
IDEHelper/Compiler/BfModule.cpp

@@ -2874,11 +2874,10 @@ bool BfModule::CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* me
 
 
 void BfModule::SetElementType(BfAstNode* astNode, BfSourceElementType elementType)
 void BfModule::SetElementType(BfAstNode* astNode, BfSourceElementType elementType)
 {
 {
-	if ((mCompiler->mResolvePassData != NULL) &&
-		(mCompiler->mResolvePassData->mSourceClassifier != NULL) &&
-		(astNode->IsFromParser(mCompiler->mResolvePassData->mParser)))
+	if (mCompiler->mResolvePassData != NULL)		
 	{
 	{
-		mCompiler->mResolvePassData->mSourceClassifier->SetElementType(astNode, elementType);
+		if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(astNode))
+			sourceClassifier->SetElementType(astNode, elementType);
 	}
 	}
 }
 }
 
 
@@ -4441,10 +4440,13 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance,
 	}
 	}
 	else
 	else
 	{
 	{
-		if ((mCompiler->mIsResolveOnly) && (mCompiler->mResolvePassData->mSourceClassifier != NULL) && (initializer->IsFromParser(mCompiler->mResolvePassData->mParser)))
+		if (mCompiler->mIsResolveOnly)
 		{
 		{
-			mCompiler->mResolvePassData->mSourceClassifier->SetElementType(initializer, BfSourceElementType_Normal);
-			mCompiler->mResolvePassData->mSourceClassifier->VisitChildNoRef(initializer);
+			if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(initializer))
+			{
+				sourceClassifier->SetElementType(initializer, BfSourceElementType_Normal);
+				sourceClassifier->VisitChildNoRef(initializer);
+			}
 		}
 		}
 
 
 		if ((mCurTypeInstance->IsPayloadEnum()) && (fieldDef->IsEnumCaseEntry()))
 		if ((mCurTypeInstance->IsPayloadEnum()) && (fieldDef->IsEnumCaseEntry()))
@@ -11631,10 +11633,10 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
 	if (!mCompiler->mHasRequiredTypes)
 	if (!mCompiler->mHasRequiredTypes)
 		return;
 		return;
 
 
-	if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL) && 
-		(attributesDirective->IsFromParser(mCompiler->mResolvePassData->mParser)) && (mCompiler->mResolvePassData->mSourceClassifier != NULL))
+	if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL))		
 	{
 	{
-		mCompiler->mResolvePassData->mSourceClassifier->VisitChild(attributesDirective);
+		if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(attributesDirective))
+			sourceClassifier->VisitChild(attributesDirective);
 	}
 	}
 
 
 	SetAndRestoreValue<bool> prevIsCapturingMethodMatchInfo;
 	SetAndRestoreValue<bool> prevIsCapturingMethodMatchInfo;
@@ -11644,6 +11646,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
 	BfTypeInstance* baseAttrTypeInst = mContext->mUnreifiedModule->ResolveTypeDef(mCompiler->mAttributeTypeDef)->ToTypeInstance();
 	BfTypeInstance* baseAttrTypeInst = mContext->mUnreifiedModule->ResolveTypeDef(mCompiler->mAttributeTypeDef)->ToTypeInstance();
 	BfAttributeTargets targetOverride = (BfAttributeTargets)0;
 	BfAttributeTargets targetOverride = (BfAttributeTargets)0;
 
 
+	BfTypeDef* activeTypeDef = GetActiveTypeDef();
 	BfAutoComplete* autoComplete = NULL;
 	BfAutoComplete* autoComplete = NULL;
 	if (mCompiler->mResolvePassData != NULL)
 	if (mCompiler->mResolvePassData != NULL)
 		autoComplete = mCompiler->mResolvePassData->mAutoComplete;
 		autoComplete = mCompiler->mResolvePassData->mAutoComplete;
@@ -11674,6 +11677,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
 
 
 		BfCustomAttribute customAttribute;
 		BfCustomAttribute customAttribute;
 		customAttribute.mAwaitingValidation = true;
 		customAttribute.mAwaitingValidation = true;
+		customAttribute.mDeclaringType = activeTypeDef;
 		customAttribute.mRef = attributesDirective;
 		customAttribute.mRef = attributesDirective;
 
 
 		if (attributesDirective->mAttrOpenToken != NULL)
 		if (attributesDirective->mAttrOpenToken != NULL)
@@ -12109,7 +12113,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
 		}
 		}
 
 
 		if (success)
 		if (success)
-		{
+		{			
 			customAttributes->mAttributes.push_back(customAttribute);
 			customAttributes->mAttributes.push_back(customAttribute);
 		}
 		}
 	}
 	}
@@ -13446,10 +13450,10 @@ BfModule* BfModule::GetOrCreateMethodModule(BfMethodInstance* methodInstance)
 		if (methodDecl != NULL)
 		if (methodDecl != NULL)
 		{
 		{
 			auto attributesDirective = methodDecl->mAttributes;
 			auto attributesDirective = methodDecl->mAttributes;
-			if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL) &&
-				(attributesDirective->IsFromParser(mCompiler->mResolvePassData->mParser)) && (mCompiler->mResolvePassData->mSourceClassifier != NULL))
+			if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL))				
 			{
 			{
-				mCompiler->mResolvePassData->mSourceClassifier->VisitChild(attributesDirective);
+				if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(attributesDirective))
+					sourceClassifier->VisitChild(attributesDirective);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -16239,7 +16243,7 @@ bool BfModule::IsInterestedInMethod(BfTypeInstance* typeInstance, BfMethodDef* m
 	if (methodDeclaration == NULL)
 	if (methodDeclaration == NULL)
 		checkNode = methodDef->mBody;
 		checkNode = methodDef->mBody;
 	
 	
-	if ((mCompiler->mResolvePassData->mParser != NULL) && (typeDef->mTypeDeclaration->IsFromParser(mCompiler->mResolvePassData->mParser)))
+	if ((!mCompiler->mResolvePassData->mParsers.IsEmpty()) && (typeDef->mTypeDeclaration->IsFromParser(mCompiler->mResolvePassData->mParsers[0])))
 	{
 	{
 		if (mCompiler->mResolvePassData->mAutoComplete == NULL)
 		if (mCompiler->mResolvePassData->mAutoComplete == NULL)
 			return true;		
 			return true;		
@@ -16650,10 +16654,10 @@ void BfModule::CreateStaticCtor()
 					{
 					{
 						if (fieldDef->mInitializer != NULL)
 						if (fieldDef->mInitializer != NULL)
 						{
 						{
-							if (mCompiler->mResolvePassData->mSourceClassifier != NULL)
+							if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(fieldDef->mInitializer))
 							{
 							{
-								mCompiler->mResolvePassData->mSourceClassifier->SetElementType(fieldDef->mInitializer, BfSourceElementType_Normal);
-								mCompiler->mResolvePassData->mSourceClassifier->VisitChild(fieldDef->mInitializer);
+								sourceClassifier->SetElementType(fieldDef->mInitializer, BfSourceElementType_Normal);
+								sourceClassifier->VisitChild(fieldDef->mInitializer);
 							}
 							}
 							BfType* wantType = NULL;
 							BfType* wantType = NULL;
 							if ((!BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef)) && (!BfNodeIsA<BfLetTypeReference>(fieldDef->mTypeRef)))
 							if ((!BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef)) && (!BfNodeIsA<BfLetTypeReference>(fieldDef->mTypeRef)))
@@ -16835,10 +16839,13 @@ void BfModule::EmitDtorBody()
 
 
 				while (fieldDtor != NULL)
 				while (fieldDtor != NULL)
 				{
 				{
-					if (mCompiler->WantsClassifyNode(fieldDtor))
+					if (mCompiler->mResolvePassData != NULL)
 					{
 					{
-						mCompiler->mResolvePassData->mSourceClassifier->SetElementType(fieldDtor, BfSourceElementType_Normal);
-						mCompiler->mResolvePassData->mSourceClassifier->VisitChild(fieldDtor);
+						if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(fieldDtor))
+						{
+							sourceClassifier->SetElementType(fieldDtor, BfSourceElementType_Normal);
+							sourceClassifier->VisitChild(fieldDtor);
+						}
 					}
 					}
 
 
 					UpdateSrcPos(fieldDtor);										
 					UpdateSrcPos(fieldDtor);										
@@ -16910,7 +16917,7 @@ void BfModule::EmitDtorBody()
 				for (auto fieldDef : tempTypeDef->mFields)
 				for (auto fieldDef : tempTypeDef->mFields)
 				{
 				{
 					if ((fieldDef->mIsStatic == methodDef->mIsStatic) && (fieldDef->mFieldDeclaration != NULL) && 
 					if ((fieldDef->mIsStatic == methodDef->mIsStatic) && (fieldDef->mFieldDeclaration != NULL) && 
-						(fieldDef->mFieldDeclaration->mFieldDtor != NULL) && (mCompiler->mResolvePassData->mSourceClassifier != NULL))
+						(fieldDef->mFieldDeclaration->mFieldDtor != NULL) && (mCompiler->mResolvePassData->mIsClassifying))
 					{
 					{
 						BfType* fieldType = NULL;
 						BfType* fieldType = NULL;
 
 
@@ -16943,8 +16950,11 @@ void BfModule::EmitDtorBody()
 
 
 						while (fieldDtor != NULL)
 						while (fieldDtor != NULL)
 						{
 						{
-							mCompiler->mResolvePassData->mSourceClassifier->SetElementType(fieldDtor, BfSourceElementType_Normal);
-							mCompiler->mResolvePassData->mSourceClassifier->VisitChild(fieldDtor);
+							if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(fieldDtor))
+							{
+								sourceClassifier->SetElementType(fieldDtor, BfSourceElementType_Normal);
+								sourceClassifier->VisitChild(fieldDtor);
+							}
 
 
 							UpdateSrcPos(fieldDtor);							
 							UpdateSrcPos(fieldDtor);							
 							VisitEmbeddedStatement(fieldDtor->mBody);
 							VisitEmbeddedStatement(fieldDtor->mBody);
@@ -17659,10 +17669,13 @@ void BfModule::EmitCtorBody(bool& skipBody)
 				{
 				{
 					for (auto fieldDef : tempTypeDef->mFields)
 					for (auto fieldDef : tempTypeDef->mFields)
 					{
 					{
-						if ((!fieldDef->mIsStatic) && (fieldDef->mInitializer != NULL) && (mCompiler->mResolvePassData->mSourceClassifier != NULL))
+						if ((!fieldDef->mIsStatic) && (fieldDef->mInitializer != NULL) && (mCompiler->mResolvePassData->mIsClassifying))
 						{
 						{
-							mCompiler->mResolvePassData->mSourceClassifier->SetElementType(fieldDef->mInitializer, BfSourceElementType_Normal);
-							mCompiler->mResolvePassData->mSourceClassifier->VisitChild(fieldDef->mInitializer);
+							if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(fieldDef->mInitializer))
+							{
+								sourceClassifier->SetElementType(fieldDef->mInitializer, BfSourceElementType_Normal);
+								sourceClassifier->VisitChild(fieldDef->mInitializer);
+							}
 
 
 							BfType* wantType = NULL;
 							BfType* wantType = NULL;
 							if ((!BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef)) &&
 							if ((!BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef)) &&
@@ -19300,12 +19313,12 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
 		BF_ASSERT(!methodInstance->mIRFunction.IsFake() || (methodInstance->GetImportCallKind() != BfImportCallKind_None));
 		BF_ASSERT(!methodInstance->mIRFunction.IsFake() || (methodInstance->GetImportCallKind() != BfImportCallKind_None));
 	}
 	}
 
 
-	SetAndRestoreValue<BfSourceClassifier*> prevSourceClassifier;
+	SetAndRestoreValue<bool> prevIsClassifying;
 	if (((methodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend) || (methodInstance->mIsForeignMethodDef) || (methodInstance->IsSpecializedGenericMethod())) && 
 	if (((methodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend) || (methodInstance->mIsForeignMethodDef) || (methodInstance->IsSpecializedGenericMethod())) && 
 		(mCompiler->mResolvePassData != NULL))
 		(mCompiler->mResolvePassData != NULL))
 	{
 	{
 		// Don't classify on the CtorCalcAppend, just on the actual Ctor
 		// Don't classify on the CtorCalcAppend, just on the actual Ctor
-		prevSourceClassifier.Init(mCompiler->mResolvePassData->mSourceClassifier, NULL);
+		prevIsClassifying.Init(mCompiler->mResolvePassData->mIsClassifying, false);
 	}
 	}
 
 
 	if (methodInstance->mHasBeenProcessed)
 	if (methodInstance->mHasBeenProcessed)
@@ -19573,10 +19586,10 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
 		
 		
 	if ((mCurMethodState == NULL) && (!IsInSpecializedSection())) // Only do initial classify for the 'outer' method state, not any local methods or lambdas
 	if ((mCurMethodState == NULL) && (!IsInSpecializedSection())) // Only do initial classify for the 'outer' method state, not any local methods or lambdas
 	{
 	{
-		if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule) && (methodDef->mBody != NULL) && (!mCurTypeInstance->IsBoxed()) &&
-			(methodDef->mBody->IsFromParser(mCompiler->mResolvePassData->mParser)) && (mCompiler->mResolvePassData->mSourceClassifier != NULL))
+		if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule) && (methodDef->mBody != NULL) && (!mCurTypeInstance->IsBoxed()))
 		{
 		{
-			mCompiler->mResolvePassData->mSourceClassifier->VisitChildNoRef(methodDef->mBody);
+			if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(methodDef->mBody))
+				sourceClassifier->VisitChildNoRef(methodDef->mBody);
 		}
 		}
 	}		
 	}		
 
 

+ 3 - 2
IDEHelper/Compiler/BfModule.h

@@ -34,6 +34,7 @@ class BfResolvedType;
 class BfExprEvaluator;
 class BfExprEvaluator;
 class CeEmitContext;
 class CeEmitContext;
 class CeDbgState;
 class CeDbgState;
+enum BfCeTypeEmitSourceKind;
 
 
 enum BfPopulateType
 enum BfPopulateType
 {	
 {	
@@ -1780,8 +1781,8 @@ public:
 	BfModuleOptions GetModuleOptions();
 	BfModuleOptions GetModuleOptions();
 	BfCheckedKind GetDefaultCheckedKind();
 	BfCheckedKind GetDefaultCheckedKind();
 	void FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInstance, BfCEParseContext* ceParseContext);
 	void FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInstance, BfCEParseContext* ceParseContext);
-	BfCEParseContext CEEmitParse(BfTypeInstance* typeInstance, const StringImpl& src);
-	void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode);
+	BfCEParseContext CEEmitParse(BfTypeInstance* typeInstance, BfTypeDef* declaringType, const StringImpl& src, BfAstNode* refNode, BfCeTypeEmitSourceKind emitSourceKind);
+	void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* declaringType, const StringImpl& ctxString, BfAstNode* refNode, BfCeTypeEmitSourceKind emitSourceKind);
 	void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfCustomAttributes* customAttributes, Dictionary<BfTypeInstance*, BfIRValue>& foundAttributes, bool underlyingTypeDeferred);
 	void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfCustomAttributes* customAttributes, Dictionary<BfTypeInstance*, BfIRValue>& foundAttributes, bool underlyingTypeDeferred);
 	void CEMixin(BfAstNode* refNode, const StringImpl& src);
 	void CEMixin(BfAstNode* refNode, const StringImpl& src);
 	void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred);
 	void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred);

+ 212 - 72
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -2023,7 +2023,7 @@ void BfModule::SetTypeOptions(BfTypeInstance* typeInstance)
 	typeInstance->mTypeOptionsIdx = GenerateTypeOptions(typeInstance->mCustomAttributes, typeInstance, true);
 	typeInstance->mTypeOptionsIdx = GenerateTypeOptions(typeInstance->mCustomAttributes, typeInstance, true);
 }
 }
 
 
-BfCEParseContext BfModule::CEEmitParse(BfTypeInstance* typeInstance, const StringImpl& src)
+BfCEParseContext BfModule::CEEmitParse(BfTypeInstance* typeInstance, BfTypeDef* declaringType, const StringImpl& src, BfAstNode* refNode, BfCeTypeEmitSourceKind emitSourceKind)
 {
 {
 	BfCEParseContext ceParseContext;
 	BfCEParseContext ceParseContext;
 	ceParseContext.mFailIdx = mCompiler->mPassInstance->mFailedIdx;
 	ceParseContext.mFailIdx = mCompiler->mPassInstance->mFailedIdx;
@@ -2034,6 +2034,21 @@ BfCEParseContext BfModule::CEEmitParse(BfTypeInstance* typeInstance, const Strin
 	
 	
 	BfParser* emitParser = NULL;
 	BfParser* emitParser = NULL;
 
 
+	int64 emitSourceMapKey = ((int64)declaringType->mPartialIdx << 32) | refNode->mSrcStart;
+
+	if (typeInstance->mCeTypeInfo == NULL)
+		typeInstance->mCeTypeInfo = new BfCeTypeInfo();
+	auto ceTypeInfo = typeInstance->mCeTypeInfo;
+	if (ceTypeInfo->mNext != NULL)
+		ceTypeInfo = ceTypeInfo->mNext;	
+	BfCeTypeEmitSource* ceEmitSource = NULL;
+	ceTypeInfo->mEmitSourceMap.TryAdd(emitSourceMapKey, NULL, &ceEmitSource);
+	ceEmitSource->mKind = emitSourceKind;
+	
+	int emitSrcStart = 0;
+
+	BfEmitEmbedEntry* emitEmbedEntry = NULL;
+	
 	if (typeInstance->mTypeDef->mEmitParent == NULL)
 	if (typeInstance->mTypeDef->mEmitParent == NULL)
 	{
 	{
 		BF_ASSERT(typeInstance->mTypeDef->mNextRevision == NULL);
 		BF_ASSERT(typeInstance->mTypeDef->mNextRevision == NULL);
@@ -2048,21 +2063,38 @@ BfCEParseContext BfModule::CEEmitParse(BfTypeInstance* typeInstance, const Strin
 		createdParser = true;		
 		createdParser = true;		
 		emitParser = new BfParser(mSystem, typeInstance->mTypeDef->mProject);
 		emitParser = new BfParser(mSystem, typeInstance->mTypeDef->mProject);
 		emitParser->mIsEmitted = true;
 		emitParser->mIsEmitted = true;
-		emitParser->mFileName = typeInstance->mTypeDef->mName->ToString();
-
+		
 		BfLogSys(mSystem, "Emit typeDef for type %p created %p parser %p typeDecl %p\n", typeInstance, emitTypeDef, emitParser, emitTypeDef->mTypeDeclaration);
 		BfLogSys(mSystem, "Emit typeDef for type %p created %p parser %p typeDecl %p\n", typeInstance, emitTypeDef, emitParser, emitTypeDef->mTypeDeclaration);
 
 
-		if (mCompiler->mIsResolveOnly)
-			emitParser->mFileName += "$EmitR$";
-		else
-			emitParser->mFileName += "$Emit$";
+		String typeName;		
+		typeName += typeInstance->mTypeDef->mProject->mName;
+		typeName += ":";
+
+		typeName += TypeToString(typeInstance, BfTypeNameFlags_None);
+		if ((mCompiler->mResolvePassData != NULL) && (!mCompiler->mResolvePassData->mEmitEmbedEntries.IsEmpty()))
+			mCompiler->mResolvePassData->mEmitEmbedEntries.TryGetValue(typeName, &emitEmbedEntry);
+ 		
+		emitParser->mFileName = "$Emit$";
+		emitParser->mFileName += typeName;
 
 
-		emitParser->mFileName += StrFormat("%d", typeInstance->mTypeId);
-		emitParser->mFileName += StrFormat(".bf|%d", typeInstance->mRevision);
 		emitTypeDef->mSource = emitParser;
 		emitTypeDef->mSource = emitParser;
 		emitParser->mRefCount++;
 		emitParser->mRefCount++;
 		emitParser->SetSource(src.c_str(), src.mLength);
 		emitParser->SetSource(src.c_str(), src.mLength);
 
 
+		if (emitEmbedEntry != NULL)
+		{
+			emitEmbedEntry->mRevision = typeInstance->mRevision;
+			emitEmbedEntry->mParser = emitParser;
+			emitEmbedEntry->mParser->mSourceClassifier = new BfSourceClassifier(emitEmbedEntry->mParser, NULL);			
+			mCompiler->mPassInstance->mFilterErrorsTo.Add(emitEmbedEntry->mParser->mParserData);
+
+			if (emitEmbedEntry->mCursorIdx != -1)
+			{
+				emitParser->SetCursorIdx(emitEmbedEntry->mCursorIdx);
+				emitParser->mParserFlags = (BfParserFlag)(emitParser->mParserFlags | ParserFlag_Autocomplete | ParserFlag_Classifying);
+			}
+		}
+
 		// If we emit only from method attributes then we will already have method instances created
 		// If we emit only from method attributes then we will already have method instances created
 		auto _FixMethod = [&](BfMethodInstance* methodInstance)
 		auto _FixMethod = [&](BfMethodInstance* methodInstance)
 		{
 		{
@@ -2082,19 +2114,57 @@ BfCEParseContext BfModule::CEEmitParse(BfTypeInstance* typeInstance, const Strin
 		};
 		};
 	}
 	}
 	else
 	else
-	{		
+	{
 		emitParser = typeInstance->mTypeDef->mSource->ToParser();
 		emitParser = typeInstance->mTypeDef->mSource->ToParser();
 
 
-		int idx = emitParser->AllocChars(src.mLength + 1);
-		memcpy((uint8*)emitParser->mSrc + idx, src.c_str(), src.mLength + 1);
+		if ((mCompiler->mResolvePassData != NULL) && (!mCompiler->mResolvePassData->mEmitEmbedEntries.IsEmpty()))
+		{			
+			int dollarPos = (int)emitParser->mFileName.LastIndexOf('$');
+			if (dollarPos != -1)
+				mCompiler->mResolvePassData->mEmitEmbedEntries.TryGetValue(emitParser->mFileName.Substring(dollarPos + 1), &emitEmbedEntry);
+		}
+
+		int idx = emitParser->AllocChars(2 + src.mLength + 1);
+		emitSrcStart = idx + 2;
+
+		memcpy((uint8*)emitParser->mSrc + idx, "\n\n", 2);
+		memcpy((uint8*)emitParser->mSrc + idx + 2, src.c_str(), src.mLength + 1);
 		emitParser->mSrcIdx = idx;
 		emitParser->mSrcIdx = idx;
-		emitParser->mSrcLength = idx + src.mLength;
+		emitParser->mSrcLength = idx + src.mLength + 2;
 		emitParser->mParserData->mSrcLength = emitParser->mSrcLength;
 		emitParser->mParserData->mSrcLength = emitParser->mSrcLength;
+		emitParser->mOrigSrcLength = emitParser->mSrcLength;
+	}
+
+	if (ceEmitSource->mSrcStart == -1)
+	{
+		ceEmitSource->mSrcStart = emitSrcStart;
+		ceEmitSource->mSrcEnd = emitParser->mSrcLength;
+	}
+	else
+	{
+		ceEmitSource->mSrcStart = BF_MIN(ceEmitSource->mSrcStart, emitSrcStart);
+		ceEmitSource->mSrcEnd = BF_MAX(ceEmitSource->mSrcEnd, emitParser->mSrcLength);
 	}
 	}
 
 
 	emitParser->Parse(mCompiler->mPassInstance);
 	emitParser->Parse(mCompiler->mPassInstance);
 	emitParser->FinishSideNodes();
 	emitParser->FinishSideNodes();
 
 
+	if (emitEmbedEntry != NULL)
+	{
+		int prevStart = emitEmbedEntry->mCharData.mSize;
+		emitEmbedEntry->mCharData.GrowUninitialized(emitParser->mSrcLength - emitEmbedEntry->mCharData.mSize);
+		auto charDataPtr = emitEmbedEntry->mCharData.mVals;
+		for (int i = prevStart; i < emitParser->mSrcLength; i++)
+		{
+			charDataPtr[i].mChar = emitParser->mSrc[i];
+			charDataPtr[i].mDisplayPassId = 0;
+			charDataPtr[i].mDisplayTypeId = 0;
+			charDataPtr[i].mDisplayFlags = 0;
+		}
+
+		emitEmbedEntry->mParser->mSourceClassifier->mCharData = emitEmbedEntry->mCharData.mVals;		
+	}
+
 	if (createdParser)
 	if (createdParser)
 	{
 	{
 		AutoCrit crit(mSystem->mDataLock);
 		AutoCrit crit(mSystem->mDataLock);
@@ -2117,7 +2187,7 @@ void BfModule::FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInst
 	}
 	}
 }
 }
 
 
-void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode)
+void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* declaringType, const StringImpl& ctxString, BfAstNode* refNode, BfCeTypeEmitSourceKind emitSourceKind)
 {
 {
 	for (int ifaceTypeId : ceEmitContext->mInterfaces)
 	for (int ifaceTypeId : ceEmitContext->mInterfaces)
 		typeInstance->mCeTypeInfo->mPendingInterfaces.Add(ifaceTypeId);
 		typeInstance->mCeTypeInfo->mPendingInterfaces.Add(ifaceTypeId);
@@ -2127,16 +2197,16 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
 		
 		
 	String src;
 	String src;
 		
 		
-	if (typeInstance->mTypeDef->mEmitParent != NULL)
-		src += "\n\n";
+// 	if (typeInstance->mTypeDef->mEmitParent != NULL)
+// 		src += "\n\n";
 
 
-	src += "// Code emission in ";
-	src += ctxString;
-	src += "\n\n";
+// 	src += "// Code emission in ";
+// 	src += ctxString;
+// 	src += "\n\n";
 	src += ceEmitContext->mEmitData;	
 	src += ceEmitContext->mEmitData;	
 	ceEmitContext->mEmitData.Clear();
 	ceEmitContext->mEmitData.Clear();
 
 
-	BfCEParseContext ceParseContext = CEEmitParse(typeInstance, src);	
+	BfCEParseContext ceParseContext = CEEmitParse(typeInstance, declaringType, src, refNode, emitSourceKind);	
 	auto emitParser = typeInstance->mTypeDef->mSource->ToParser();
 	auto emitParser = typeInstance->mTypeDef->mSource->ToParser();
 				
 				
 	auto typeDeclaration = emitParser->mAlloc->Alloc<BfTypeDeclaration>();
 	auto typeDeclaration = emitParser->mAlloc->Alloc<BfTypeDeclaration>();
@@ -2167,6 +2237,13 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
 
 
 	FinishCEParseContext(refNode, typeInstance, &ceParseContext);
 	FinishCEParseContext(refNode, typeInstance, &ceParseContext);
 
 
+	if (emitParser->mSourceClassifier != NULL)
+	{
+		emitParser->mSourceClassifier->VisitChild(emitParser->mRootNode);
+		emitParser->mSourceClassifier->VisitChild(emitParser->mSidechannelRootNode);
+		emitParser->mSourceClassifier->VisitChild(emitParser->mErrorRootNode);
+	}
+
 	if (typeInstance->mTypeDef->mEmitParent != NULL)
 	if (typeInstance->mTypeDef->mEmitParent != NULL)
 	{
 	{
 		// Remove generated fields like the 'underlying type' enum field
 		// Remove generated fields like the 'underlying type' enum field
@@ -2347,7 +2424,8 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
 				ctxStr += TypeToString(typeInstance);
 				ctxStr += TypeToString(typeInstance);
 				ctxStr += " ";
 				ctxStr += " ";
 				ctxStr += customAttribute.mRef->LocationToString();
 				ctxStr += customAttribute.mRef->LocationToString();
-				UpdateCEEmit(ceEmitContext, typeInstance, ctxStr, customAttribute.mRef);
+
+				UpdateCEEmit(ceEmitContext, typeInstance, customAttribute.mDeclaringType, ctxStr, customAttribute.mRef, BfCeTypeEmitSourceKind_Type);
 			}
 			}
 		}
 		}
 
 
@@ -2361,11 +2439,11 @@ void BfModule::CEMixin(BfAstNode* refNode, const StringImpl& code)
 	//auto emitParser = activeTypeDef->mEmitParser;
 	//auto emitParser = activeTypeDef->mEmitParser;
 			
 			
 	String src;
 	String src;
-	if (mCurTypeInstance->mTypeDef->mEmitParent != NULL)
-		src += "\n\n";
-	src += "// Code emission in ";	
-	src += MethodToString(mCurMethodInstance);	
-	src += "\n";
+// 	if (mCurTypeInstance->mTypeDef->mEmitParent != NULL)
+// 		src += "\n\n";
+// 	src += "// Code emission in ";	
+// 	src += MethodToString(mCurMethodInstance);	
+// 	src += "\n";
 	src += code;
 	src += code;
 
 
 	BfReducer bfReducer;	
 	BfReducer bfReducer;	
@@ -2380,7 +2458,7 @@ void BfModule::CEMixin(BfAstNode* refNode, const StringImpl& code)
 	bool wantsDIData = (mBfIRBuilder->DbgHasInfo()) && (mHasFullDebugInfo);
 	bool wantsDIData = (mBfIRBuilder->DbgHasInfo()) && (mHasFullDebugInfo);
 	mBfIRBuilder->SaveDebugLocation();
 	mBfIRBuilder->SaveDebugLocation();
 
 
-	BfCEParseContext ceParseContext = CEEmitParse(mCurTypeInstance, src);
+	BfCEParseContext ceParseContext = CEEmitParse(mCurTypeInstance, activeTypeDef, src, refNode, BfCeTypeEmitSourceKind_Method);
 	auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser();
 	auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser();
 	bfReducer.mSource = emitParser;
 	bfReducer.mSource = emitParser;
 	bfReducer.mAlloc = emitParser->mAlloc;
 	bfReducer.mAlloc = emitParser->mAlloc;
@@ -2503,6 +2581,11 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
 		if (methodDeclaration->mAttributes == NULL)
 		if (methodDeclaration->mAttributes == NULL)
 			continue;
 			continue;
 
 
+		BfTypeState typeState;
+		typeState.mPrevState = mContext->mCurTypeState;
+		typeState.mForceActiveTypeDef = methodDef->mDeclaringType;
+		SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
+
 		bool wantsAttributes = false;		
 		bool wantsAttributes = false;		
 		BfAttributeDirective* checkAttributes = methodDeclaration->mAttributes;
 		BfAttributeDirective* checkAttributes = methodDeclaration->mAttributes;
 		while (checkAttributes != NULL)
 		while (checkAttributes != NULL)
@@ -2607,7 +2690,7 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
 				ctxStr += MethodToString(methodInstance);
 				ctxStr += MethodToString(methodInstance);
 				ctxStr += " ";
 				ctxStr += " ";
 				ctxStr += methodInstance->mMethodDef->GetRefNode()->LocationToString();
 				ctxStr += methodInstance->mMethodDef->GetRefNode()->LocationToString();
-				UpdateCEEmit(ceEmitContext, typeInstance, ctxStr, methodInstance->mMethodDef->GetRefNode());
+				UpdateCEEmit(ceEmitContext, typeInstance, methodDef->mDeclaringType, ctxStr, methodInstance->mMethodDef->GetRefNode(), BfCeTypeEmitSourceKind_Type);
 			}
 			}
 		}
 		}
 
 
@@ -2751,13 +2834,13 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
 		if ((!ceEmitContext.mEmitData.IsEmpty()) || (!ceEmitContext.mExitEmitData.IsEmpty()))
 		if ((!ceEmitContext.mEmitData.IsEmpty()) || (!ceEmitContext.mExitEmitData.IsEmpty()))
 		{
 		{
 			String src;				
 			String src;				
-			src += "// Code emission in comptime ApplyToMethod of ";
-			src += TypeToString(attrType);
-			src += " to ";
-			src += MethodToString(methodInstance);
-			src += " ";
-			src += customAttribute.mRef->LocationToString();
-			src += "\n";
+// 			src += "// Code emission in comptime ApplyToMethod of ";
+// 			src += TypeToString(attrType);
+// 			src += " to ";
+// 			src += MethodToString(methodInstance);
+// 			src += " ";
+// 			src += customAttribute.mRef->LocationToString();
+// 			src += "\n";
 				
 				
 			//auto emitTypeDef = typeInstance->mCeTypeInfo->mNext->mTypeDef;
 			//auto emitTypeDef = typeInstance->mCeTypeInfo->mNext->mTypeDef;
 			//auto emitParser = emitTypeDef->mSource->ToParser();
 			//auto emitParser = emitTypeDef->mSource->ToParser();
@@ -2771,16 +2854,29 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
 			bfReducer.mCurTypeDecl = activeTypeDef->mTypeDeclaration;
 			bfReducer.mCurTypeDecl = activeTypeDef->mTypeDeclaration;
 			bfReducer.mCurMethodDecl = BfNodeDynCast<BfMethodDeclaration>(methodInstance->mMethodDef->mMethodDeclaration);
 			bfReducer.mCurMethodDecl = BfNodeDynCast<BfMethodDeclaration>(methodInstance->mMethodDef->mMethodDeclaration);
 
 
+			BfAstNode* bodyNode = NULL;			
+			if (auto methodDecl = BfNodeDynCast<BfMethodDeclaration>(methodInstance->mMethodDef->mMethodDeclaration))
+				bodyNode = methodDecl->mBody;
+
 			if (!ceEmitContext.mEmitData.IsEmpty())
 			if (!ceEmitContext.mEmitData.IsEmpty())
 			{
 			{
-				SetAndRestoreValue<BfAstNode*> prevCustomAttribute(mCurMethodState->mEmitRefNode, customAttribute.mRef);
-
+				SetAndRestoreValue<BfAstNode*> prevCustomAttribute(mCurMethodState->mEmitRefNode, customAttribute.mRef);				
 				String entrySrc = src;
 				String entrySrc = src;
-				if (mCurTypeInstance->mTypeDef->mEmitParent != NULL)
-					entrySrc += "\n\n";
+// 				if (mCurTypeInstance->mTypeDef->mEmitParent != NULL)
+// 					entrySrc += "\n\n";
 				entrySrc += src;
 				entrySrc += src;
 				entrySrc += ceEmitContext.mEmitData;
 				entrySrc += ceEmitContext.mEmitData;
-				BfCEParseContext ceParseContext = CEEmitParse(typeInstance, entrySrc);
+
+				BfAstNode* refNode = customAttribute.mRef;
+				if (bodyNode != NULL)
+				{
+					refNode = bodyNode;
+					if (auto blockNode = BfNodeDynCast<BfBlock>(bodyNode))
+						if (blockNode->mOpenBrace != NULL)
+							refNode = blockNode->mOpenBrace;
+				}
+
+				BfCEParseContext ceParseContext = CEEmitParse(typeInstance, methodInstance->mMethodDef->mDeclaringType, entrySrc, refNode, BfCeTypeEmitSourceKind_Type);
 				auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser();
 				auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser();
 				bfReducer.mSource = emitParser;
 				bfReducer.mSource = emitParser;
 				bfReducer.mAlloc = emitParser->mAlloc;
 				bfReducer.mAlloc = emitParser->mAlloc;
@@ -2796,7 +2892,18 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
 					exitSrc += "\n\n";
 					exitSrc += "\n\n";
 				exitSrc += src;
 				exitSrc += src;
 				exitSrc += ceEmitContext.mExitEmitData;
 				exitSrc += ceEmitContext.mExitEmitData;
-				BfCEParseContext ceParseContext = CEEmitParse(typeInstance, exitSrc);
+
+				BfAstNode* refNode = customAttribute.mRef;
+				if (bodyNode != NULL)
+				{
+					refNode = bodyNode;
+					if (auto blockNode = BfNodeDynCast<BfBlock>(bodyNode))
+						if (blockNode->mCloseBrace != NULL)
+							refNode = blockNode->mCloseBrace;
+				}
+
+				BfCEParseContext ceParseContext = CEEmitParse(typeInstance, methodInstance->mMethodDef->mDeclaringType, exitSrc, refNode, BfCeTypeEmitSourceKind_Type);
+
 				auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser();
 				auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser();
 				bfReducer.mSource = emitParser;
 				bfReducer.mSource = emitParser;
 				bfReducer.mAlloc = emitParser->mAlloc;
 				bfReducer.mAlloc = emitParser->mAlloc;
@@ -4540,7 +4647,14 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 				if (typeInstance->mCeTypeInfo->mNext != NULL)
 				if (typeInstance->mCeTypeInfo->mNext != NULL)
 				{
 				{
 					auto ceInfo = typeInstance->mCeTypeInfo->mNext;
 					auto ceInfo = typeInstance->mCeTypeInfo->mNext;
+
 					HashContext hashCtx;
 					HashContext hashCtx;
+					hashCtx.Mixin(ceInfo->mEmitSourceMap.mCount);
+					for (auto& kv : ceInfo->mEmitSourceMap)
+					{
+						hashCtx.Mixin(kv.mKey);
+						hashCtx.Mixin(kv.mValue);
+					}
 					hashCtx.Mixin(ceInfo->mOnCompileMap.mCount);
 					hashCtx.Mixin(ceInfo->mOnCompileMap.mCount);
 					for (auto& kv : ceInfo->mOnCompileMap)
 					for (auto& kv : ceInfo->mOnCompileMap)
 					{
 					{
@@ -4559,15 +4673,26 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 					if (!typeInstance->mCeTypeInfo->mNext->mFailed)
 					if (!typeInstance->mCeTypeInfo->mNext->mFailed)
 					{
 					{
 						if ((typeInstance->mCeTypeInfo->mHash != typeInstance->mCeTypeInfo->mNext->mHash) && (!typeInstance->mCeTypeInfo->mHash.IsZero()))
 						if ((typeInstance->mCeTypeInfo->mHash != typeInstance->mCeTypeInfo->mNext->mHash) && (!typeInstance->mCeTypeInfo->mHash.IsZero()))
-							mContext->RebuildDependentTypes_MidCompile(typeInstance, "comptime hash changed");												
+							mContext->RebuildDependentTypes_MidCompile(typeInstance, "comptime hash changed");
+						typeInstance->mCeTypeInfo->mEmitSourceMap = typeInstance->mCeTypeInfo->mNext->mEmitSourceMap;
 						typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap;
 						typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap;
 						typeInstance->mCeTypeInfo->mTypeIFaceMap = typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap;
 						typeInstance->mCeTypeInfo->mTypeIFaceMap = typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap;
-						typeInstance->mCeTypeInfo->mHash = typeInstance->mCeTypeInfo->mNext->mHash;
+						typeInstance->mCeTypeInfo->mHash = typeInstance->mCeTypeInfo->mNext->mHash;						
 					}
 					}
 					
 					
 					delete typeInstance->mCeTypeInfo->mNext;
 					delete typeInstance->mCeTypeInfo->mNext;
 					typeInstance->mCeTypeInfo->mNext = NULL;
 					typeInstance->mCeTypeInfo->mNext = NULL;
 				}
 				}
+				else
+				{
+					// Removed emissions
+					if (!typeInstance->mCeTypeInfo->mHash.IsZero())
+						mContext->RebuildDependentTypes_MidCompile(typeInstance, "comptime hash changed");
+					typeInstance->mCeTypeInfo->mEmitSourceMap.Clear();
+					typeInstance->mCeTypeInfo->mOnCompileMap.Clear();
+					typeInstance->mCeTypeInfo->mTypeIFaceMap.Clear();
+					typeInstance->mCeTypeInfo->mHash = Val128();
+				}
 			}
 			}
 
 
 			if ((typeInstance->mCeTypeInfo != NULL) && (!typeInstance->mCeTypeInfo->mPendingInterfaces.IsEmpty()))
 			if ((typeInstance->mCeTypeInfo != NULL) && (!typeInstance->mCeTypeInfo->mPendingInterfaces.IsEmpty()))
@@ -5312,16 +5437,19 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 		if ((typeDeclaration != NULL) && (typeDeclaration->mNameNode != NULL))
 		if ((typeDeclaration != NULL) && (typeDeclaration->mNameNode != NULL))
 		{
 		{
 			auto typeRefSource = typeDeclaration->mNameNode->GetParserData();
 			auto typeRefSource = typeDeclaration->mNameNode->GetParserData();
-			if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mSourceClassifier != NULL) && (typeRefSource != NULL) && (typeRefSource == mCompiler->mResolvePassData->mParser->mSourceData))
+			if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mIsClassifying) && (typeRefSource != NULL))
 			{
 			{
-				BfSourceElementType elemType = BfSourceElementType_Type;
-				if (typeInstance->IsInterface())
-					elemType = BfSourceElementType_Interface;
-				else if (typeInstance->IsObject())
-					elemType = BfSourceElementType_RefType;
-				else if (typeInstance->IsStruct() || (typeInstance->IsTypedPrimitive() && !typeInstance->IsEnum()))
-					elemType = BfSourceElementType_Struct;
-				mCompiler->mResolvePassData->mSourceClassifier->SetElementType(typeDeclaration->mNameNode, elemType);
+				if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(typeDeclaration->mNameNode))
+				{
+					BfSourceElementType elemType = BfSourceElementType_Type;
+					if (typeInstance->IsInterface())
+						elemType = BfSourceElementType_Interface;
+					else if (typeInstance->IsObject())
+						elemType = BfSourceElementType_RefType;
+					else if (typeInstance->IsStruct() || (typeInstance->IsTypedPrimitive() && !typeInstance->IsEnum()))
+						elemType = BfSourceElementType_Struct;
+					sourceClassifier->SetElementType(typeDeclaration->mNameNode, elemType);
+				}
 			}
 			}
 		}
 		}
 	};
 	};
@@ -8775,11 +8903,17 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
 		else
 		else
 			typeRefSource = typeRef->GetSourceData();
 			typeRefSource = typeRef->GetSourceData();
 
 
-		bool wantsFileNamespaceInfo = (((mCompiler->mResolvePassData->mSourceClassifier != NULL) || (isGetDefinition) || (mCompiler->mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Namespace)) &&
-			(typeRefSource != NULL) && (mCompiler->mResolvePassData->mParser != NULL) &&
-			(typeRefSource == mCompiler->mResolvePassData->mParser->mSourceData));
+		BfSourceClassifier* sourceClassifier = NULL;
+		if ((mCompiler->mResolvePassData->mIsClassifying) && (typeRefSource != NULL))
+		{
+			auto parser = typeRefSource->ToParser();
+			if (parser != NULL)
+				sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(parser);
+		}
+
+		bool wantsFileNamespaceInfo = ((sourceClassifier != NULL) || (isGetDefinition) || (mCompiler->mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Namespace));
 
 
-		bool wantsAllNamespaceInfo = (mCompiler->mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Namespace) && (mCompiler->mResolvePassData->mParser == NULL);
+		bool wantsAllNamespaceInfo = (mCompiler->mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Namespace) && (mCompiler->mResolvePassData->mParsers.IsEmpty());
 
 
 		if (wantsFileNamespaceInfo || wantsAllNamespaceInfo)
 		if (wantsFileNamespaceInfo || wantsAllNamespaceInfo)
 		{
 		{
@@ -8841,14 +8975,14 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
 
 
 			while (auto qualifiedTypeRef = BfNodeDynCast<BfQualifiedTypeReference>(checkTypeRef))
 			while (auto qualifiedTypeRef = BfNodeDynCast<BfQualifiedTypeReference>(checkTypeRef))
 			{
 			{
-				if ((mCompiler->mResolvePassData->mSourceClassifier != NULL) && (checkTypeRef == headTypeRef) && (elemType != BfSourceElementType_Type))
-					mCompiler->mResolvePassData->mSourceClassifier->SetElementType(qualifiedTypeRef->mRight, elemType);
+				if ((sourceClassifier != NULL) && (checkTypeRef == headTypeRef) && (elemType != BfSourceElementType_Type))
+					sourceClassifier->SetElementType(qualifiedTypeRef->mRight, elemType);
 
 
 				StringView leftString = qualifiedTypeRef->mLeft->ToStringView();
 				StringView leftString = qualifiedTypeRef->mLeft->ToStringView();
 				BfSizedAtomComposite leftComposite;
 				BfSizedAtomComposite leftComposite;
 				bool isValid = mSystem->ParseAtomComposite(leftString, leftComposite);
 				bool isValid = mSystem->ParseAtomComposite(leftString, leftComposite);
-				if (mCompiler->mResolvePassData->mSourceClassifier != NULL)
-					mCompiler->mResolvePassData->mSourceClassifier->SetHighestElementType(qualifiedTypeRef->mRight, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
+				if (sourceClassifier != NULL)
+					sourceClassifier->SetHighestElementType(qualifiedTypeRef->mRight, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
 				if (resolvedTypeInstance == NULL)
 				if (resolvedTypeInstance == NULL)
 				{
 				{
 					if ((isValid) && (mCompiler->mSystem->ContainsNamespace(leftComposite, mCurTypeInstance->mTypeDef->mProject)))
 					if ((isValid) && (mCompiler->mSystem->ContainsNamespace(leftComposite, mCurTypeInstance->mTypeDef->mProject)))
@@ -8874,16 +9008,16 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
 				auto checkNameNode = namedTypeRef->mNameNode;
 				auto checkNameNode = namedTypeRef->mNameNode;
 				bool setType = false;
 				bool setType = false;
 
 
-				if ((mCompiler->mResolvePassData->mSourceClassifier != NULL) && (checkTypeRef == headTypeRef) && (elemType != BfSourceElementType_Type))
+				if ((sourceClassifier != NULL) && (checkTypeRef == headTypeRef) && (elemType != BfSourceElementType_Type))
 				{					
 				{					
 					if (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(checkNameNode))
 					if (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(checkNameNode))
 					{
 					{
-						mCompiler->mResolvePassData->mSourceClassifier->SetElementType(qualifiedNameNode->mRight, elemType);
+						sourceClassifier->SetElementType(qualifiedNameNode->mRight, elemType);
 					}
 					}
 					else
 					else
 					{
 					{
 						setType = true;
 						setType = true;
-						mCompiler->mResolvePassData->mSourceClassifier->SetElementType(checkNameNode, elemType);
+						sourceClassifier->SetElementType(checkNameNode, elemType);
 					}
 					}
 				}
 				}
 
 
@@ -8892,8 +9026,8 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
 					StringView leftString =  qualifiedNameNode->mLeft->ToStringView();
 					StringView leftString =  qualifiedNameNode->mLeft->ToStringView();
 					BfSizedAtomComposite leftComposite;
 					BfSizedAtomComposite leftComposite;
 					bool isValid = mSystem->ParseAtomComposite(leftString, leftComposite);
 					bool isValid = mSystem->ParseAtomComposite(leftString, leftComposite);
-					if (mCompiler->mResolvePassData->mSourceClassifier != NULL)
-						mCompiler->mResolvePassData->mSourceClassifier->SetHighestElementType(qualifiedNameNode->mRight, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
+					if (sourceClassifier != NULL)
+						sourceClassifier->SetHighestElementType(qualifiedNameNode->mRight, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
 					if (resolvedTypeInstance == NULL)
 					if (resolvedTypeInstance == NULL)
 					{
 					{
 						if ((isValid) && (mCompiler->mSystem->ContainsNamespace(leftComposite, mCurTypeInstance->mTypeDef->mProject)))
 						if ((isValid) && (mCompiler->mSystem->ContainsNamespace(leftComposite, mCurTypeInstance->mTypeDef->mProject)))
@@ -8913,9 +9047,9 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
 					}
 					}
 					checkNameNode = qualifiedNameNode->mLeft;
 					checkNameNode = qualifiedNameNode->mLeft;
 				}
 				}
-				if ((mCompiler->mResolvePassData->mSourceClassifier != NULL) && 
+				if ((sourceClassifier != NULL) &&
 					((!setType) || (checkNameNode != namedTypeRef->mNameNode)))
 					((!setType) || (checkNameNode != namedTypeRef->mNameNode)))
-					mCompiler->mResolvePassData->mSourceClassifier->SetHighestElementType(checkNameNode, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
+					sourceClassifier->SetHighestElementType(checkNameNode, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
 			}
 			}
 		}
 		}
 
 
@@ -8964,6 +9098,7 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
 								else
 								else
 									break;
 									break;
 							}
 							}
+
 							if ((baseNode != NULL) && (autoComplete->IsAutocompleteNode(baseNode)))
 							if ((baseNode != NULL) && (autoComplete->IsAutocompleteNode(baseNode)))
 							{
 							{
 								// We didn't have this mDefType check before - why? We always want to catch the FIRST definition, 
 								// We didn't have this mDefType check before - why? We always want to catch the FIRST definition, 
@@ -9348,8 +9483,10 @@ BfTypeDef* BfModule::FindTypeDef(const BfAtomComposite& findName, int numGeneric
 	if ((typeInstance == NULL) && (useTypeDef == NULL))
 	if ((typeInstance == NULL) && (useTypeDef == NULL))
 	{		
 	{		
 		BfProject* project = NULL;
 		BfProject* project = NULL;
-		if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mParser != NULL))
-			project = mCompiler->mResolvePassData->mParser->mProject;
+		if ((mContext->mCurTypeState != NULL) && (mContext->mCurTypeState->mActiveProject != NULL))
+			project = mContext->mCurTypeState->mActiveProject;
+		else if ((mCompiler->mResolvePassData != NULL) && (!mCompiler->mResolvePassData->mParsers.IsEmpty()))
+			project = mCompiler->mResolvePassData->mParsers[0]->mProject;
 
 
 		BP_ZONE("System.FindTypeDef_2");				
 		BP_ZONE("System.FindTypeDef_2");				
 		Array<BfAtomComposite> namespaceSearch;
 		Array<BfAtomComposite> namespaceSearch;
@@ -9535,7 +9672,7 @@ void BfModule::CheckTypeRefFixit(BfAstNode* typeRef, const char* appendName)
 		std::set<String> fixitNamespaces;
 		std::set<String> fixitNamespaces;
 
 
 		//TODO: Do proper value for numGenericArgs		
 		//TODO: Do proper value for numGenericArgs		
-		mSystem->FindFixitNamespaces(typeName, -1, mCompiler->mResolvePassData->mParser->mProject, fixitNamespaces);
+		mSystem->FindFixitNamespaces(typeName, -1, mCompiler->mResolvePassData->mParsers[0]->mProject, fixitNamespaces);
 
 
 		int insertLoc = 0;
 		int insertLoc = 0;
 
 
@@ -9810,8 +9947,11 @@ BfTypedValue BfModule::TryLookupGenericConstVaue(BfIdentifierNode* identifierNod
 		if (genericParamResult != NULL)
 		if (genericParamResult != NULL)
 		{			
 		{			
 			auto typeRefSource = identifierNode->GetSourceData();
 			auto typeRefSource = identifierNode->GetSourceData();
-			if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mSourceClassifier != NULL) && (typeRefSource != NULL) && (typeRefSource == mCompiler->mResolvePassData->mParser->mSourceData))
-				mCompiler->mResolvePassData->mSourceClassifier->SetElementType(identifierNode, BfSourceElementType_GenericParam);
+			if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mIsClassifying) && (typeRefSource != NULL))
+			{
+				if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(identifierNode))
+					sourceClassifier->SetElementType(identifierNode, BfSourceElementType_GenericParam);
+			}
 
 
 			if (genericParamResult->IsConstExprValue())
 			if (genericParamResult->IsConstExprValue())
 			{
 			{

+ 58 - 3
IDEHelper/Compiler/BfParser.cpp

@@ -345,6 +345,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem
 
 
 	gParserCount++;	
 	gParserCount++;	
 
 
+	mEmbedKind = BfSourceEmbedKind_None;
 	mUsingCache = false;
 	mUsingCache = false;
 	mParserData = NULL;
 	mParserData = NULL;
 	mAwaitingDelete = false;
 	mAwaitingDelete = false;
@@ -354,7 +355,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem
 	mJumpTable = NULL;
 	mJumpTable = NULL;
 	mProject = bfProject;
 	mProject = bfProject;
 	mPassInstance = NULL;
 	mPassInstance = NULL;
-	mPassInstance = NULL;
+	mSourceClassifier = NULL;
 	mPrevRevision = NULL;
 	mPrevRevision = NULL;
 	mNextRevision = NULL;
 	mNextRevision = NULL;
 	mOrigSrcLength = 0;
 	mOrigSrcLength = 0;
@@ -375,7 +376,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem
 	mCompatMode = false;
 	mCompatMode = false;
 	mQuickCompatMode = false;
 	mQuickCompatMode = false;
 	mLiteral.mWarnType = 0;
 	mLiteral.mWarnType = 0;
-	mDataId = -1;
+	mDataId = -1;	
 
 
 	mTriviaStart = 0;
 	mTriviaStart = 0;
 	mParsingFailed = false;
 	mParsingFailed = false;
@@ -3820,6 +3821,11 @@ BF_EXPORT void BF_CALLTYPE BfParser_SetIsClassifying(BfParser* bfParser)
 	bfParser->mParserFlags = (BfParserFlag)(bfParser->mParserFlags | ParserFlag_Classifying);
 	bfParser->mParserFlags = (BfParserFlag)(bfParser->mParserFlags | ParserFlag_Classifying);
 }
 }
 
 
+BF_EXPORT void BF_CALLTYPE BfParser_SetEmbedKind(BfParser* bfParser, BfSourceEmbedKind embedKind)
+{
+	bfParser->mEmbedKind = embedKind;
+}
+
 BF_EXPORT void BF_CALLTYPE BfParser_SetAutocomplete(BfParser* bfParser, int cursorIdx)
 BF_EXPORT void BF_CALLTYPE BfParser_SetAutocomplete(BfParser* bfParser, int cursorIdx)
 {
 {
 	BF_ASSERT(bfParser->mParserData->mRefCount == -1);
 	BF_ASSERT(bfParser->mParserData->mRefCount == -1);
@@ -3972,7 +3978,8 @@ BF_EXPORT BfResolvePassData* BF_CALLTYPE BfParser_CreateResolvePassData(BfParser
 {
 {
 	auto bfResolvePassData = new BfResolvePassData();
 	auto bfResolvePassData = new BfResolvePassData();
 	bfResolvePassData->mResolveType = resolveType;
 	bfResolvePassData->mResolveType = resolveType;
-	bfResolvePassData->mParser = bfParser;
+	if (bfParser != NULL)
+		bfResolvePassData->mParsers.Add(bfParser);
 	if ((bfParser != NULL) && ((bfParser->mParserFlags & ParserFlag_Autocomplete) != 0))
 	if ((bfParser != NULL) && ((bfParser->mParserFlags & ParserFlag_Autocomplete) != 0))
 		bfResolvePassData->mAutoComplete = new BfAutoComplete(resolveType, doFuzzyAutoComplete);
 		bfResolvePassData->mAutoComplete = new BfAutoComplete(resolveType, doFuzzyAutoComplete);
 	return bfResolvePassData;
 	return bfResolvePassData;
@@ -3980,6 +3987,9 @@ BF_EXPORT BfResolvePassData* BF_CALLTYPE BfParser_CreateResolvePassData(BfParser
 
 
 BF_EXPORT bool BF_CALLTYPE BfParser_BuildDefs(BfParser* bfParser, BfPassInstance* bfPassInstance, BfResolvePassData* resolvePassData, bool fullRefresh)
 BF_EXPORT bool BF_CALLTYPE BfParser_BuildDefs(BfParser* bfParser, BfPassInstance* bfPassInstance, BfResolvePassData* resolvePassData, bool fullRefresh)
 {	
 {	
+	if (bfParser->mCursorIdx != -1)
+		resolvePassData->mHasCursorIdx = true;
+
 	BP_ZONE("BfParser_BuildDefs");
 	BP_ZONE("BfParser_BuildDefs");
 	int startFailIdx = bfPassInstance->mFailedIdx;
 	int startFailIdx = bfPassInstance->mFailedIdx;
 	BfDefBuilder defBuilder(bfParser->mSystem);
 	BfDefBuilder defBuilder(bfParser->mSystem);
@@ -4007,6 +4017,51 @@ BF_EXPORT void BF_CALLTYPE BfParser_ClassifySource(BfParser* bfParser, BfSourceC
 	bfSourceClassifier.Visit(bfParser->mSidechannelRootNode);	
 	bfSourceClassifier.Visit(bfParser->mSidechannelRootNode);	
 }
 }
 
 
+BF_EXPORT void BF_CALLTYPE BfParser_CreateClassifier(BfParser* bfParser, BfPassInstance* bfPassInstance, BfResolvePassData* resolvePassData, BfSourceClassifier::CharData* charData)
+{
+	resolvePassData->mIsClassifying = true;
+	bfParser->mSourceClassifier = new BfSourceClassifier(bfParser, charData);	
+	bfParser->mSourceClassifier->mClassifierPassId = bfPassInstance->mClassifierPassId;
+
+	if ((resolvePassData->mParsers.IsEmpty()) || (bfParser != resolvePassData->mParsers[0]))
+		resolvePassData->mParsers.Add(bfParser);
+
+	bool doClassifyPass = (charData != NULL) && (resolvePassData->mResolveType <= BfResolveType_Autocomplete_HighPri);
+	bfParser->mSourceClassifier->mEnabled = doClassifyPass;
+
+	bfParser->mSourceClassifier->mSkipMethodInternals = true;
+	bfParser->mSourceClassifier->mSkipTypeDeclarations = true;
+	if (charData != NULL)
+	{		
+		if ((doClassifyPass) && (bfParser->mRootNode != NULL))
+			bfParser->mSourceClassifier->Visit(bfParser->mRootNode);
+	}
+	bfParser->mSourceClassifier->mSkipTypeDeclarations = false;
+	bfParser->mSourceClassifier->mSkipMethodInternals = false;
+}
+
+BF_EXPORT void BF_CALLTYPE BfParser_FinishClassifier(BfParser* bfParser, BfResolvePassData* resolvePassData)
+{
+	if (bfParser->mSourceClassifier == NULL)
+		return;
+
+	bool doClassifyPass = (bfParser->mSourceClassifier->mCharData != NULL) && (resolvePassData->mResolveType <= BfResolveType_Autocomplete_HighPri);
+
+	if (doClassifyPass)
+	{
+		bfParser->mSourceClassifier->mIsSideChannel = false;
+		if (bfParser->mErrorRootNode != NULL)
+			bfParser->mSourceClassifier->Visit(bfParser->mErrorRootNode);
+
+		bfParser->mSourceClassifier->mIsSideChannel = true;
+		if (bfParser->mSidechannelRootNode != NULL)
+			bfParser->mSourceClassifier->Visit(bfParser->mSidechannelRootNode);
+	}
+
+	delete bfParser->mSourceClassifier;
+	bfParser->mSourceClassifier = NULL;
+}
+
 BF_EXPORT void BF_CALLTYPE BfParser_GenerateAutoCompletionFrom(BfParser* bfParser, int srcPosition)
 BF_EXPORT void BF_CALLTYPE BfParser_GenerateAutoCompletionFrom(BfParser* bfParser, int srcPosition)
 {
 {
 	BP_ZONE("BfParser_GenerateAutoCompletionFrom");
 	BP_ZONE("BfParser_GenerateAutoCompletionFrom");

+ 11 - 1
IDEHelper/Compiler/BfParser.h

@@ -14,6 +14,7 @@ NS_BF_BEGIN
 
 
 class BfPassInstance;
 class BfPassInstance;
 class BfProject;
 class BfProject;
+class BfSourceClassifier;
 
 
 enum BfSyntaxToken
 enum BfSyntaxToken
 {
 {
@@ -136,13 +137,20 @@ public:
 	void ReportMemory(MemReporter* memReporter);
 	void ReportMemory(MemReporter* memReporter);
 };
 };
 
 
-enum BfDefineState
+enum BfDefineState : int8
 {
 {
 	BfDefineState_FromProject,
 	BfDefineState_FromProject,
 	BfDefineState_ManualSet,
 	BfDefineState_ManualSet,
 	BfDefineState_ManualUnset
 	BfDefineState_ManualUnset
 };
 };
 
 
+enum BfSourceEmbedKind : int8
+{
+	BfSourceEmbedKind_None,
+	BfSourceEmbedKind_Type,
+	BfSourceEmbedKind_Method
+};
+
 class BfParser : public BfSource
 class BfParser : public BfSource
 {
 {
 public:		
 public:		
@@ -150,7 +158,9 @@ public:
 	bool mUsingCache;
 	bool mUsingCache;
 
 
 	BfPassInstance* mPassInstance;
 	BfPassInstance* mPassInstance;
+	BfSourceClassifier* mSourceClassifier;
 	String mFileName;	
 	String mFileName;	
+	BfSourceEmbedKind mEmbedKind;
 	bool mAwaitingDelete;	
 	bool mAwaitingDelete;	
 	
 	
 	bool mCompatMode; // Does C++ compatible parsing
 	bool mCompatMode; // Does C++ compatible parsing

+ 55 - 2
IDEHelper/Compiler/BfReducer.cpp

@@ -6781,7 +6781,8 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept
 // 	if (depth == 0)
 // 	if (depth == 0)
 // 		prevTypeMemberNodeStart.Set();
 // 		prevTypeMemberNodeStart.Set();
 
 
-	AssertCurrentNode(node);
+	if (mCurTypeDecl != NULL)
+		AssertCurrentNode(node);
 
 
 	BfTokenNode* refToken = NULL;
 	BfTokenNode* refToken = NULL;
 
 
@@ -8239,6 +8240,58 @@ BfAstNode* BfReducer::HandleTopLevel(BfBlock* node)
 	bool hadPrevFail = false;
 	bool hadPrevFail = false;
 
 
 	bool isDone = !mVisitorPos.MoveNext();
 	bool isDone = !mVisitorPos.MoveNext();
+	
+	auto parser = mSource->ToParser();
+
+	if ((parser != NULL) && (parser->mEmbedKind == BfSourceEmbedKind_Type))
+	{		
+		while (!isDone)
+		{
+			auto node = mVisitorPos.GetCurrent();
+			if (node == prevNode)
+			{				
+				// If we're stuck on an error and can't process any more nodes
+				break;
+			}
+			prevNode = node;
+			BfAstNode* typeMember = BfNodeDynCast<BfMemberDeclaration>(node);
+			if (typeMember == NULL)
+			{
+				SetAndRestoreValue<BfAstNode*> prevTypeMemberNodeStart(mTypeMemberNodeStart, node);
+				typeMember = ReadTypeMember(node);
+			}
+
+			//methodDeclaration->mDocumentation = FindDocumentation(methodDeclaration);
+
+			isDone = !mVisitorPos.MoveNext();
+			if (typeMember != NULL)
+			{
+				mVisitorPos.Write(typeMember);
+			}
+		}
+	}
+
+	if ((parser != NULL) && (parser->mEmbedKind == BfSourceEmbedKind_Method))
+	{
+		bool allowEndingExpression = false;
+		BfAstNode* nextNode = NULL;
+		while (!isDone)
+		{
+			BfAstNode* node = mVisitorPos.GetCurrent();
+
+			CreateStmtFlags flags = (CreateStmtFlags)(CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_AllowLocalFunction);
+			if (allowEndingExpression)
+				flags = (CreateStmtFlags)(flags | CreateStmtFlags_AllowUnterminatedExpression);
+
+			auto statement = CreateStatement(node, flags);
+			if ((statement == NULL) && (mSource != NULL))
+				statement = mSource->CreateErrorNode(node);
+
+			isDone = !mVisitorPos.MoveNext();
+			if (statement != NULL)
+				mVisitorPos.Write(statement);
+		}
+	}
 
 
 	while (!isDone)
 	while (!isDone)
 	{
 	{
@@ -10246,7 +10299,7 @@ void BfReducer::HandleTypeDeclaration(BfTypeDeclaration* typeDecl, BfAttributeDi
 		MEMBER_SET(typeDecl, mAttributes, attributes);
 		MEMBER_SET(typeDecl, mAttributes, attributes);
 	}
 	}
 
 
-	if (!IsNodeRelevant(deferredHeadNode, typeDecl))
+	if ((!IsNodeRelevant(deferredHeadNode, typeDecl)) && (!typeDecl->IsTemporary()))
 	{
 	{
 		typeDecl->mIgnoreDeclaration = true;
 		typeDecl->mIgnoreDeclaration = true;
 		return;
 		return;

+ 34 - 2
IDEHelper/Compiler/BfResolvePass.cpp

@@ -18,9 +18,24 @@ BfResolvePassData::BfResolvePassData()
 	mSymbolTypeGenericParamIdx = -1;
 	mSymbolTypeGenericParamIdx = -1;
 
 
 	mAutoComplete = NULL;
 	mAutoComplete = NULL;
-	mSourceClassifier = NULL;
 	mResolveType = BfResolveType_None;
 	mResolveType = BfResolveType_None;
-	mParser = NULL;
+	mIsClassifying = false;
+	mHasCursorIdx = false;
+}
+
+BfResolvePassData::~BfResolvePassData()
+{
+	for (auto& emitEntryKV : mEmitEmbedEntries)
+	{
+		auto parser = emitEntryKV.mValue.mParser;
+		if (parser != NULL)
+		{
+			delete parser->mSourceClassifier;			
+			parser->mSourceClassifier = NULL;
+			parser->mParserFlags = ParserFlag_None;
+			parser->mCursorCheckIdx = -1;
+		}
+	}
 }
 }
 
 
 void BfResolvePassData::RecordReplaceNode(BfParserData* parser, int srcStart, int srcLen)
 void BfResolvePassData::RecordReplaceNode(BfParserData* parser, int srcStart, int srcLen)
@@ -179,3 +194,20 @@ void BfResolvePassData::HandleNamespaceReference(BfAstNode* node, const BfAtomCo
 			RecordReplaceNode(baseNode);
 			RecordReplaceNode(baseNode);
 	}
 	}
 }
 }
+
+BfSourceClassifier* BfResolvePassData::GetSourceClassifier(BfAstNode* astNode)
+{
+	if (!mIsClassifying)
+		return NULL;
+	auto parser = astNode->GetParser();
+	if (parser == NULL)
+		return NULL;
+	return parser->mSourceClassifier;
+}
+
+BfSourceClassifier* BfResolvePassData::GetSourceClassifier(BfParser* parser)
+{
+	if (!mIsClassifying)
+		return NULL;
+	return parser->mSourceClassifier;
+}

+ 27 - 3
IDEHelper/Compiler/BfResolvePass.h

@@ -2,6 +2,7 @@
 
 
 #include "BfSystem.h"
 #include "BfSystem.h"
 #include "BfResolvedTypeUtils.h"
 #include "BfResolvedTypeUtils.h"
+#include "BfSourceClassifier.h"
 
 
 NS_BF_BEGIN
 NS_BF_BEGIN
 
 
@@ -40,17 +41,33 @@ enum BfGetSymbolReferenceKind
 	BfGetSymbolReferenceKind_Namespace
 	BfGetSymbolReferenceKind_Namespace
 };
 };
 
 
+class BfEmitEmbedEntry
+{
+public:
+	int mCursorIdx;
+	int mRevision;
+	BfParser* mParser;
+	Array<BfSourceClassifier::CharData> mCharData;
+
+public:
+	BfEmitEmbedEntry()
+	{
+		mCursorIdx = -1;
+		mRevision = -1;
+		mParser = NULL;
+	}
+};
+
 class BfResolvePassData
 class BfResolvePassData
 {
 {
 public:
 public:
 	BfResolveType mResolveType;
 	BfResolveType mResolveType;
 
 
-	BfParser* mParser;
+	Array<BfParser*> mParsers;
 	BfAutoComplete* mAutoComplete;
 	BfAutoComplete* mAutoComplete;
 	Array<BfTypeDef*> mAutoCompleteTempTypes; // Contains multiple values when we have nested types
 	Array<BfTypeDef*> mAutoCompleteTempTypes; // Contains multiple values when we have nested types
 	Dictionary<BfTypeDef*, BfStaticSearch> mStaticSearchMap;
 	Dictionary<BfTypeDef*, BfStaticSearch> mStaticSearchMap;
-	Dictionary<BfTypeDef*, BfInternalAccessSet> mInternalAccessMap;
-	BfSourceClassifier* mSourceClassifier;
+	Dictionary<BfTypeDef*, BfInternalAccessSet> mInternalAccessMap;	
 	Array<BfAstNode*> mExteriorAutocompleteCheckNodes;
 	Array<BfAstNode*> mExteriorAutocompleteCheckNodes;
 
 
 	BfGetSymbolReferenceKind mGetSymbolReferenceKind;	
 	BfGetSymbolReferenceKind mGetSymbolReferenceKind;	
@@ -64,11 +81,15 @@ public:
 	int mSymbolReferencePropertyIdx;
 	int mSymbolReferencePropertyIdx;
 	int mSymbolMethodGenericParamIdx;
 	int mSymbolMethodGenericParamIdx;
 	int mSymbolTypeGenericParamIdx;
 	int mSymbolTypeGenericParamIdx;
+	bool mIsClassifying;
+	bool mHasCursorIdx;
 	
 	
 	typedef Dictionary<BfParserData*, String> FoundSymbolReferencesParserDataMap;
 	typedef Dictionary<BfParserData*, String> FoundSymbolReferencesParserDataMap;
 	FoundSymbolReferencesParserDataMap mFoundSymbolReferencesParserData;
 	FoundSymbolReferencesParserDataMap mFoundSymbolReferencesParserData;
 	//std::vector<BfIdentifierNode*> mSymbolReferenceIdentifiers;
 	//std::vector<BfIdentifierNode*> mSymbolReferenceIdentifiers;
 
 
+	Dictionary<String, BfEmitEmbedEntry> mEmitEmbedEntries;
+
 public:
 public:
 	void RecordReplaceNode(BfParserData* parser, int srcStart, int srcLen);
 	void RecordReplaceNode(BfParserData* parser, int srcStart, int srcLen);
 	void RecordReplaceNode(BfAstNode* node);	
 	void RecordReplaceNode(BfAstNode* node);	
@@ -76,6 +97,7 @@ public:
 
 
 public:
 public:
 	BfResolvePassData();
 	BfResolvePassData();
+	~BfResolvePassData();
 
 
 	void HandleLocalReference(BfIdentifierNode* identifier, BfTypeDef* typeDef, BfMethodDef* methodDef, int localVarIdx);
 	void HandleLocalReference(BfIdentifierNode* identifier, BfTypeDef* typeDef, BfMethodDef* methodDef, int localVarIdx);
 	void HandleLocalReference(BfIdentifierNode* identifier, BfIdentifierNode* origNameNode, BfTypeDef* typeDef, BfMethodDef* methodDef, int localVarIdx);
 	void HandleLocalReference(BfIdentifierNode* identifier, BfIdentifierNode* origNameNode, BfTypeDef* typeDef, BfMethodDef* methodDef, int localVarIdx);
@@ -87,6 +109,8 @@ public:
 	void HandleTypeReference(BfAstNode* node, BfTypeDef* typeDef);	
 	void HandleTypeReference(BfAstNode* node, BfTypeDef* typeDef);	
 	void HandleNamespaceReference(BfAstNode* node, const BfAtomComposite& namespaceName);
 	void HandleNamespaceReference(BfAstNode* node, const BfAtomComposite& namespaceName);
 
 
+	BfSourceClassifier* GetSourceClassifier(BfAstNode* astNode);
+	BfSourceClassifier* GetSourceClassifier(BfParser* parser);
 	//void ReplaceIdentifiers();
 	//void ReplaceIdentifiers();
 };
 };
 
 

+ 2 - 7
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -57,7 +57,7 @@ enum BfTypeNameFlags : uint16
 	BfTypeNameFlag_InternalName = 0x100, // Use special delimiters to remove ambiguities (ie: '+' for inner types)	
 	BfTypeNameFlag_InternalName = 0x100, // Use special delimiters to remove ambiguities (ie: '+' for inner types)	
 	BfTypeNameFlag_HideGlobalName = 0x200,
 	BfTypeNameFlag_HideGlobalName = 0x200,
 	BfTypeNameFlag_ExtendedInfo = 0x400,
 	BfTypeNameFlag_ExtendedInfo = 0x400,
-	BfTypeNameFlag_ShortConst = 0x800
+	BfTypeNameFlag_ShortConst = 0x800	
 };
 };
 
 
 enum BfMethodNameFlags : uint8
 enum BfMethodNameFlags : uint8
@@ -1886,12 +1886,6 @@ public:
 	void ReportMemory(MemReporter* memReporter);
 	void ReportMemory(MemReporter* memReporter);
 };
 };
 
 
-class BfCeTypeEmitEntry
-{
-public:
-	String mEmitData;
-};
-
 class BfCeTypeInfo;
 class BfCeTypeInfo;
 
 
 // Instance of struct or class
 // Instance of struct or class
@@ -2543,6 +2537,7 @@ class BfCustomAttribute
 {
 {
 public:
 public:
 	BfAttributeDirective* mRef;
 	BfAttributeDirective* mRef;
+	BfTypeDef* mDeclaringType;
 	BfTypeInstance* mType;
 	BfTypeInstance* mType;
 	BfMethodDef* mCtor;
 	BfMethodDef* mCtor;
 	Array<BfIRValue> mCtorArgs;
 	Array<BfIRValue> mCtorArgs;

+ 44 - 2
IDEHelper/Compiler/BfSystem.cpp

@@ -30,9 +30,19 @@ void Beefy::DoBfLog(int fileIdx, const char* fmt ...)
 
 
 	static BfpFile* fp[10] = { NULL };
 	static BfpFile* fp[10] = { NULL };
 	static bool openedLog[10] = { false };
 	static bool openedLog[10] = { false };
+	static int64 logSize[10] = { 0 };
+	static int logCount[10] = { 0 };
+
+	if (logSize[fileIdx] >= 1 * 1024 * 1024 * 1024)
+	{
+		BfpFile_Release(fp[fileIdx]);
+		openedLog[fileIdx] = false;
+	}
+
 	if (!openedLog[fileIdx])
 	if (!openedLog[fileIdx])
 	{
 	{
 		openedLog[fileIdx] = true;
 		openedLog[fileIdx] = true;
+		logSize[fileIdx] = 0;
 
 
 		char exeName[512];
 		char exeName[512];
 		int len = 512;
 		int len = 512;
@@ -42,10 +52,16 @@ void Beefy::DoBfLog(int fileIdx, const char* fmt ...)
 		int dotPos = (int)dbgName.IndexOf('.');
 		int dotPos = (int)dbgName.IndexOf('.');
 		if (dotPos != -1)
 		if (dotPos != -1)
 			dbgName.RemoveToEnd(dotPos);
 			dbgName.RemoveToEnd(dotPos);
-		dbgName += StrFormat("_%d.txt", fileIdx);
+		dbgName += StrFormat("_%d", fileIdx);
+
+		if (logCount[fileIdx] > 0)
+			dbgName += 'B';
+
+		dbgName += ".txt";
 		
 		
 		fp[fileIdx] = BfpFile_Create(dbgName.c_str(), BfpFileCreateKind_CreateAlways, (BfpFileCreateFlags)(BfpFileCreateFlag_Write | BfpFileCreateFlag_NoBuffering | BfpFileCreateFlag_ShareRead), BfpFileAttribute_Normal, NULL);
 		fp[fileIdx] = BfpFile_Create(dbgName.c_str(), BfpFileCreateKind_CreateAlways, (BfpFileCreateFlags)(BfpFileCreateFlag_Write | BfpFileCreateFlag_NoBuffering | BfpFileCreateFlag_ShareRead), BfpFileAttribute_Normal, NULL);
 		onNewLine[fileIdx] = true;
 		onNewLine[fileIdx] = true;
+		logCount[fileIdx]++;
 	}
 	}
 	if (fp[fileIdx] == NULL)
 	if (fp[fileIdx] == NULL)
 		return;	
 		return;	
@@ -74,6 +90,8 @@ void Beefy::DoBfLog(int fileIdx, const char* fmt ...)
 	{		
 	{		
 		if (strOfs + numChars > 0)
 		if (strOfs + numChars > 0)
 		{
 		{
+			logSize[fileIdx] += strOfs + numChars;
+
 			BfpFile_Write(fp[fileIdx], lineStr, strOfs + numChars, -1, NULL);
 			BfpFile_Write(fp[fileIdx], lineStr, strOfs + numChars, -1, NULL);
 			if (lineStr[strOfs + numChars - 1] == '\n')
 			if (lineStr[strOfs + numChars - 1] == '\n')
 				onNewLine[fileIdx] = true;
 				onNewLine[fileIdx] = true;
@@ -98,6 +116,7 @@ void Beefy::DoBfLog(int fileIdx, const char* fmt ...)
 	else
 	else
 		onNewLine[fileIdx] = false;
 		onNewLine[fileIdx] = false;
 	
 	
+	logSize[fileIdx] += aResult.length();
 	BfpFile_Write(fp[fileIdx], aResult.c_str(), aResult.length(), -1, NULL);	
 	BfpFile_Write(fp[fileIdx], aResult.c_str(), aResult.length(), -1, NULL);	
 }
 }
 
 
@@ -1137,8 +1156,9 @@ bool BfPassInstance::PopOutString(String* outString)
 
 
 bool BfPassInstance::WantsRangeRecorded(BfSourceData* bfSource, int srcIdx, int srcLen, bool isWarning, bool isDeferred)
 bool BfPassInstance::WantsRangeRecorded(BfSourceData* bfSource, int srcIdx, int srcLen, bool isWarning, bool isDeferred)
 {
 {
-	if ((mFilterErrorsTo != NULL) && (bfSource != mFilterErrorsTo->mSourceData))
+	if ((!mFilterErrorsTo.IsEmpty()) && (!mFilterErrorsTo.Contains(bfSource)))
 		return false;
 		return false;
+
 	if (bfSource == NULL)
 	if (bfSource == NULL)
 		return true;
 		return true;
 
 
@@ -3964,6 +3984,28 @@ BF_EXPORT void BfResolvePassData_SetDocumentationRequest(BfResolvePassData* reso
 	resolvePassData->mAutoComplete->mDocumentationEntryName = entryName;
 	resolvePassData->mAutoComplete->mDocumentationEntryName = entryName;
 }
 }
 
 
+BF_EXPORT void BfResolvePassData_AddEmitEmbed(BfResolvePassData* resolvePassData, char* typeName, int32 cursorIdx)
+{
+	BfEmitEmbedEntry emitEmbedEntry;
+	emitEmbedEntry.mCursorIdx = cursorIdx;
+	resolvePassData->mEmitEmbedEntries[typeName] = emitEmbedEntry;
+}
+
+BF_EXPORT void* BfResolvePassData_GetEmitEmbedData(BfResolvePassData* resolvePassData, char* typeName, int* charCount, int* revision)
+{
+	*charCount = -1;
+	*revision = 0;
+
+	BfEmitEmbedEntry* emitEmbedEntry = NULL;
+	if (!resolvePassData->mEmitEmbedEntries.TryGetValue(typeName, &emitEmbedEntry))
+		return NULL;
+	if (emitEmbedEntry->mParser == NULL)
+		return NULL;
+	*revision = emitEmbedEntry->mRevision;
+	*charCount = emitEmbedEntry->mParser->mSrcLength;
+	return emitEmbedEntry->mParser->mSourceClassifier->mCharData;
+}
+
 BF_EXPORT BfParser* BF_CALLTYPE BfSystem_CreateParser(BfSystem* bfSystem, BfProject* bfProject)
 BF_EXPORT BfParser* BF_CALLTYPE BfSystem_CreateParser(BfSystem* bfSystem, BfProject* bfProject)
 {	
 {	
 	return bfSystem->CreateParser(bfProject);
 	return bfSystem->CreateParser(bfProject);

+ 6 - 5
IDEHelper/Compiler/BfSystem.h

@@ -38,8 +38,8 @@ namespace llvm
 NS_BF_BEGIN
 NS_BF_BEGIN
 
 
 class BfSystem;
 class BfSystem;
-class BfTypeReference;
 class BfCompiler;
 class BfCompiler;
+class BfTypeReference;
 class BfProject;
 class BfProject;
 class BfTypeDef;
 class BfTypeDef;
 
 
@@ -157,7 +157,7 @@ enum BfCompilerOptionFlags
 	BfCompilerOptionFlag_EnableSideStack    = 0x1000,
 	BfCompilerOptionFlag_EnableSideStack    = 0x1000,
 	BfCompilerOptionFlag_EnableHotSwapping  = 0x2000,
 	BfCompilerOptionFlag_EnableHotSwapping  = 0x2000,
 	BfCompilerOptionFlag_IncrementalBuild   = 0x4000,
 	BfCompilerOptionFlag_IncrementalBuild   = 0x4000,
-	BfCompilerOptionFlag_DebugAlloc         = 0x8000,
+	BfCompilerOptionFlag_DebugAlloc         = 0x8000, 
 	BfCompilerOptionFlag_OmitDebugHelpers   = 0x10000,
 	BfCompilerOptionFlag_OmitDebugHelpers   = 0x10000,
 	BfCompilerOptionFlag_NoFramePointerElim = 0x20000,
 	BfCompilerOptionFlag_NoFramePointerElim = 0x20000,
 	BfCompilerOptionFlag_ArithmeticChecks = 0x40000,
 	BfCompilerOptionFlag_ArithmeticChecks = 0x40000,
@@ -1412,6 +1412,7 @@ public:
 	const int sMaxErrors = 1000;
 	const int sMaxErrors = 1000;
 
 
 	BfSystem* mSystem;
 	BfSystem* mSystem;
+	BfCompiler* mCompiler;
 	bool mTrimMessagesToCursor;
 	bool mTrimMessagesToCursor;
 	int mFailedIdx;	
 	int mFailedIdx;	
 	int mWarnIdx;
 	int mWarnIdx;
@@ -1426,7 +1427,7 @@ public:
 	bool mLastWasDisplayed;
 	bool mLastWasDisplayed;
 	bool mLastWasAdded;
 	bool mLastWasAdded;
 	uint8 mClassifierPassId;
 	uint8 mClassifierPassId;
-	BfParser* mFilterErrorsTo;
+	HashSet<BfSourceData*> mFilterErrorsTo;
 	bool mHadSignatureChanges;
 	bool mHadSignatureChanges;
 
 
 public:
 public:
@@ -1436,13 +1437,13 @@ public:
 		mFailedIdx = 0;
 		mFailedIdx = 0;
 		mWarnIdx = 0;
 		mWarnIdx = 0;
 		mSystem = bfSystem;
 		mSystem = bfSystem;
+		mCompiler = NULL;
 		mLastWasDisplayed = false;
 		mLastWasDisplayed = false;
 		mLastWasAdded = false;
 		mLastWasAdded = false;
 		mClassifierPassId = 0;
 		mClassifierPassId = 0;
 		mWarningCount = 0;		
 		mWarningCount = 0;		
 		mDeferredErrorCount = 0;
 		mDeferredErrorCount = 0;
-		mIgnoreCount = 0;
-		mFilterErrorsTo = NULL;
+		mIgnoreCount = 0;		
 		mHadSignatureChanges = false;
 		mHadSignatureChanges = false;
 	}
 	}
 
 

+ 21 - 0
IDEHelper/Compiler/BfUtil.cpp

@@ -1,4 +1,5 @@
 #include "BfUtil.h"
 #include "BfUtil.h"
+#include "BeefySysLib/util/Hash.h"
 
 
 USING_NS_BF;
 USING_NS_BF;
 
 
@@ -52,6 +53,26 @@ void* Beefy::ZeroedAlloc(int size)
 	return data;
 	return data;
 }
 }
 
 
+String Beefy::EncodeFileName(const StringImpl& fromStr)
+{
+	String path;
+	if (fromStr.mLength > 80)
+		path.Insert(0, fromStr.mPtr, 80);
+	else
+		path += fromStr;
+	
+	path.Replace("$", "\\");
+	for (auto& c : path)
+	{
+		if ((!::isalnum((uint8)c)) && (c != '_'))
+			c = '-';
+	}
+
+	path += "_";
+	path += HashEncode128(Hash128(fromStr.c_str(), (int)fromStr.length()));
+	return path;
+}
+
 uint64 stouln(const char* str, int len)
 uint64 stouln(const char* str, int len)
 {
 {
 	uint64 val = 0;
 	uint64 val = 0;

+ 2 - 0
IDEHelper/Compiler/BfUtil.h

@@ -283,6 +283,8 @@ String EncodeDataPtr(uint32 addr, bool doPrefix);
 String EncodeDataPtr(uint64 addr, bool doPrefix);
 String EncodeDataPtr(uint64 addr, bool doPrefix);
 String EncodeDataPtr(int addr, bool doPrefix);
 String EncodeDataPtr(int addr, bool doPrefix);
 void* ZeroedAlloc(int size);
 void* ZeroedAlloc(int size);
+String EncodeFileName(const StringImpl& fromStr); // Make short, only legal chars, with a hash at end
+
 /*template <typename T>
 /*template <typename T>
 T* ZeroedAlloc()
 T* ZeroedAlloc()
 {
 {

+ 6 - 1
IDEHelper/Compiler/CeDebugger.cpp

@@ -938,7 +938,7 @@ String CeDebugger::DoEvaluate(CePendingExpr* pendingExpr, bool inCompilerThread)
 	autoComplete.mSystem = module->mSystem;
 	autoComplete.mSystem = module->mSystem;
 	
 	
 	BfResolvePassData resolvePass;
 	BfResolvePassData resolvePass;
-	resolvePass.mParser = pendingExpr->mParser;
+	resolvePass.mParsers.Add(pendingExpr->mParser);
 	resolvePass.mAutoComplete = &autoComplete;
 	resolvePass.mAutoComplete = &autoComplete;
 
 
 	SetAndRestoreValue<BfResolvePassData*> prevResolvePass;
 	SetAndRestoreValue<BfResolvePassData*> prevResolvePass;
@@ -4925,3 +4925,8 @@ bool CeDebugger::IsOnDemandDebugger()
 {
 {
 	return true;
 	return true;
 }
 }
+
+bool CeDebugger::GetEmitSource(const StringImpl& filePath, String& outText)
+{
+	return false;
+}

+ 1 - 0
IDEHelper/Compiler/CeDebugger.h

@@ -402,6 +402,7 @@ public:
 	virtual Profiler* PopProfiler() override; // Profiler requested by target program
 	virtual Profiler* PopProfiler() override; // Profiler requested by target program
 	virtual void ReportMemory(MemReporter* memReporter) override;
 	virtual void ReportMemory(MemReporter* memReporter) override;
 	virtual bool IsOnDemandDebugger() override;
 	virtual bool IsOnDemandDebugger() override;
+	virtual bool GetEmitSource(const StringImpl& filePath, String& outText) override;
 };
 };
 
 
 NS_BF_END
 NS_BF_END

+ 31 - 0
IDEHelper/Compiler/CeMachine.h

@@ -972,11 +972,42 @@ public:
 	}
 	}
 };
 };
 
 
+enum BfCeTypeEmitSourceKind
+{
+	BfCeTypeEmitSourceKind_Unknown,
+	BfCeTypeEmitSourceKind_Type,
+	BfCeTypeEmitSourceKind_Method
+};
+
+class BfCeTypeEmitSource
+{
+public:
+	BfCeTypeEmitSourceKind mKind;
+	int mSrcStart;
+	int mSrcEnd;
+
+public:
+	BfCeTypeEmitSource()
+	{
+		mKind = BfCeTypeEmitSourceKind_Unknown;
+		mSrcStart = -1;
+		mSrcEnd = -1;
+	}
+};
+
+class BfCeTypeEmitEntry
+{
+public:
+	String mEmitData;
+};
+
 class BfCeTypeInfo
 class BfCeTypeInfo
 {
 {
 public:
 public:
 	Dictionary<int, BfCeTypeEmitEntry> mOnCompileMap;
 	Dictionary<int, BfCeTypeEmitEntry> mOnCompileMap;
 	Dictionary<int, BfCeTypeEmitEntry> mTypeIFaceMap;
 	Dictionary<int, BfCeTypeEmitEntry> mTypeIFaceMap;
+	Dictionary<int64, BfCeTypeEmitSource> mEmitSourceMap; // key is (extension<<32)|charId
+
 	Array<int> mPendingInterfaces;
 	Array<int> mPendingInterfaces;
 	Dictionary<CeRebuildKey, CeRebuildValue> mRebuildMap;
 	Dictionary<CeRebuildKey, CeRebuildValue> mRebuildMap;
 	Val128 mHash;
 	Val128 mHash;

+ 4 - 0
IDEHelper/DbgModule.cpp

@@ -2190,6 +2190,7 @@ DbgModule::DbgModule(DebugTarget* debugTarget) : mDefaultCompileUnit(this)
 	mStartTypeIdx = 0;
 	mStartTypeIdx = 0;
 	mEndTypeIdx = 0;
 	mEndTypeIdx = 0;
 	mHotIdx = 0;
 	mHotIdx = 0;
+	mId = 0;
 	mStartSubprogramIdx = 0;
 	mStartSubprogramIdx = 0;
 	mEndSubprogramIdx = 0;	
 	mEndSubprogramIdx = 0;	
 	mCodeAddress = NULL;
 	mCodeAddress = NULL;
@@ -7139,6 +7140,9 @@ DbgFileExistKind DbgModule::CheckSourceFileExist(const StringImpl& path)
 {
 {
 	DbgFileExistKind existsKind = DbgFileExistKind_NotFound;
 	DbgFileExistKind existsKind = DbgFileExistKind_NotFound;
 
 
+	if (path.StartsWith("$Emit"))
+		return DbgFileExistKind_Found;
+
 	if (FileExists(path))
 	if (FileExists(path))
 		existsKind = DbgFileExistKind_Found;
 		existsKind = DbgFileExistKind_Found;
 
 

+ 2 - 0
IDEHelper/DbgModule.h

@@ -1146,6 +1146,7 @@ public:
 	bool mMayBeOld; // If we had to load debug info from the SymCache or a SymServer then it may be old	
 	bool mMayBeOld; // If we had to load debug info from the SymCache or a SymServer then it may be old	
 	bool mDeleting;
 	bool mDeleting;
 	bool mFailed;
 	bool mFailed;
+	int mId;
 	int mHotIdx;
 	int mHotIdx;
 	String mFilePath;
 	String mFilePath;
 	String mDisplayName;
 	String mDisplayName;
@@ -1226,6 +1227,7 @@ public:
 	virtual void ProcessDebugInfo();
 	virtual void ProcessDebugInfo();
 	virtual bool CanGetOldSource() { return false; }
 	virtual bool CanGetOldSource() { return false; }
 	virtual String GetOldSourceCommand(const StringImpl& path) { return ""; }
 	virtual String GetOldSourceCommand(const StringImpl& path) { return ""; }
+	virtual bool GetEmitSource(const StringImpl& filePath, String& outText) { return false; }
 	virtual bool DbgIsStrMutable(const char* str) { return true; } // Always assume its a copy
 	virtual bool DbgIsStrMutable(const char* str) { return true; } // Always assume its a copy
 	virtual addr_target LocateSymbol(const StringImpl& name) { return 0; }
 	virtual addr_target LocateSymbol(const StringImpl& name) { return 0; }
 	virtual DbgSubprogram* FindSubprogram(DbgType* dbgType, const char* methodName);
 	virtual DbgSubprogram* FindSubprogram(DbgType* dbgType, const char* methodName);

+ 13 - 0
IDEHelper/DebugManager.cpp

@@ -1609,6 +1609,19 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetHotResolveData(uint8* outTypeData,
 	return outString.c_str();
 	return outString.c_str();
 }
 }
 
 
+BF_EXPORT const char* BF_CALLTYPE Debugger_GetEmitSource(char* inFilePath)
+{
+	AutoCrit autoCrit(gDebugManager->mCritSect);
+
+	String& outString = *gTLStrReturn.Get();
+	outString.Clear();
+
+	if (!gDebugger->GetEmitSource(inFilePath, outString))
+		return NULL;
+
+	return outString.c_str();
+}
+
 BF_EXPORT NetResult* HTTP_GetFile(char* url, char* destPath)
 BF_EXPORT NetResult* HTTP_GetFile(char* url, char* destPath)
 {
 {
 	AutoCrit autoCrit(gDebugManager->mNetManager->mThreadPool.mCritSect);
 	AutoCrit autoCrit(gDebugManager->mNetManager->mThreadPool.mCritSect);

+ 10 - 4
IDEHelper/DebugTarget.cpp

@@ -162,14 +162,14 @@ DbgModule* DebugTarget::Init(const StringImpl& launchPath, const StringImpl& tar
 	}
 	}
 	CheckTargetBinary(dwarf);
 	CheckTargetBinary(dwarf);
 
 
-	mDbgModules.push_back(dwarf);	
+	AddDbgModule(dwarf);
 	return dwarf;
 	return dwarf;
 }
 }
 
 
 void DebugTarget::CreateEmptyTarget()
 void DebugTarget::CreateEmptyTarget()
 {
 {
 	auto emptyTarget = new DbgModule(this);
 	auto emptyTarget = new DbgModule(this);
-	mDbgModules.push_back(emptyTarget);
+	AddDbgModule(emptyTarget);
 	mTargetBinary = emptyTarget;
 	mTargetBinary = emptyTarget;
 	mLaunchBinary = emptyTarget;
 	mLaunchBinary = emptyTarget;
 }
 }
@@ -198,7 +198,7 @@ DbgModule* DebugTarget::HotLoad(const StringImpl& fileName, int hotIdx)
 		delete dwarf;		
 		delete dwarf;		
 		return NULL;
 		return NULL;
 	}	
 	}	
-	mDbgModules.push_back(dwarf);
+	AddDbgModule(dwarf);
 	return dwarf;
 	return dwarf;
 }
 }
 
 
@@ -217,7 +217,7 @@ DbgModule* DebugTarget::SetupDyn(const StringImpl& filePath, DataStream* stream,
 		delete dwarf;
 		delete dwarf;
 		return NULL;
 		return NULL;
 	}
 	}
-	mDbgModules.push_back(dwarf);
+	AddDbgModule(dwarf);
 
 
 	dwarf->mDisplayName = GetFileName(filePath);
 	dwarf->mDisplayName = GetFileName(filePath);
 	dwarf->mOrigImageData = new DbgModuleMemoryCache(dwarf->mImageBase, dwarf->mImageSize);
 	dwarf->mOrigImageData = new DbgModuleMemoryCache(dwarf->mImageBase, dwarf->mImageSize);
@@ -905,6 +905,12 @@ void DebugTarget::GetCompilerSettings()
 	}
 	}
 }
 }
 
 
+void DebugTarget::AddDbgModule(DbgModule* dbgModule)
+{
+	static int id = 0;	
+	dbgModule->mId = ++id;
+	mDbgModules.Add(dbgModule);
+}
 
 
 #if 1
 #if 1
 bool DebugTarget::RollBackStackFrame_ExceptionDirectory(addr_target findPC, CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC)
 bool DebugTarget::RollBackStackFrame_ExceptionDirectory(addr_target findPC, CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC)

+ 5 - 7
IDEHelper/DebugTarget.h

@@ -37,10 +37,8 @@ public:
 	int mLastHotHeapCleanIdx;
 	int mLastHotHeapCleanIdx;
 	String mTargetPath;
 	String mTargetPath;
 	DbgModule* mLaunchBinary;
 	DbgModule* mLaunchBinary;
-	DbgModule* mTargetBinary;
-	//DbgModule* m
-	Array<DbgModule*> mDbgModules;
-	//DbgModule* mLastDWARF;
+	DbgModule* mTargetBinary;	
+	Array<DbgModule*> mDbgModules;	
 	HashSet<DbgSrcFile*> mPendingSrcFileRehup; // Waiting to remove old/invalid line info
 	HashSet<DbgSrcFile*> mPendingSrcFileRehup; // Waiting to remove old/invalid line info
 	
 	
 	BumpAllocator mAlloc;	
 	BumpAllocator mAlloc;	
@@ -57,12 +55,11 @@ public:
 	Array<DwCommonFrameDescriptor*> mCommonFrameDescriptors;
 	Array<DwCommonFrameDescriptor*> mCommonFrameDescriptors;
 	std::map<addr_target, DwFrameDescriptor> mDwFrameDescriptorMap;
 	std::map<addr_target, DwFrameDescriptor> mDwFrameDescriptorMap;
 	std::map<addr_target, COFFFrameDescriptorEntry> mCOFFFrameDescriptorMap;
 	std::map<addr_target, COFFFrameDescriptorEntry> mCOFFFrameDescriptorMap;
-	
-	//Array<DbgSrcFile*> mSrcFiles;	
+		
 	Dictionary<String, DbgSrcFile*> mSrcFiles;
 	Dictionary<String, DbgSrcFile*> mSrcFiles;
 	Dictionary<String, String> mLocalToOrigSrcMap;
 	Dictionary<String, String> mLocalToOrigSrcMap;
 
 
-protected:
+protected:	
 	bool RollBackStackFrame_ExceptionDirectory(addr_target findPC, CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC);
 	bool RollBackStackFrame_ExceptionDirectory(addr_target findPC, CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC);
 	bool RollBackStackFrame_ExceptionDirectory(CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC);
 	bool RollBackStackFrame_ExceptionDirectory(CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC);
 	bool RollBackStackFrame_DwFrameDescriptor(CPURegisters* registers, addr_target* outReturnAddressLoc);
 	bool RollBackStackFrame_DwFrameDescriptor(CPURegisters* registers, addr_target* outReturnAddressLoc);
@@ -76,6 +73,7 @@ public:
 	DebugTarget(WinDebugger* debugger);
 	DebugTarget(WinDebugger* debugger);
 	~DebugTarget();
 	~DebugTarget();
 	
 	
+	void AddDbgModule(DbgModule* dbgModule);
 	DbgModule* Init(const StringImpl& launchPath, const StringImpl& targetPath, intptr imageBase = 0);
 	DbgModule* Init(const StringImpl& launchPath, const StringImpl& targetPath, intptr imageBase = 0);
 	void SetupTargetBinary();
 	void SetupTargetBinary();
 	void CheckTargetBinary(DbgModule* module);
 	void CheckTargetBinary(DbgModule* module);

+ 2 - 1
IDEHelper/Debugger.h

@@ -351,7 +351,8 @@ public:
 	virtual Profiler* StartProfiling() = 0;
 	virtual Profiler* StartProfiling() = 0;
 	virtual Profiler* PopProfiler() = 0; // Profiler requested by target program
 	virtual Profiler* PopProfiler() = 0; // Profiler requested by target program
 	virtual void ReportMemory(MemReporter* memReporter) = 0;
 	virtual void ReportMemory(MemReporter* memReporter) = 0;
-	virtual bool IsOnDemandDebugger() = 0;			
+	virtual bool IsOnDemandDebugger() = 0;
+	virtual bool GetEmitSource(const StringImpl& filePath, String& outText) = 0;
 };
 };
 
 
 class Profiler
 class Profiler

+ 1 - 1
IDEHelper/MiniDumpDebugger.cpp

@@ -76,7 +76,7 @@ MiniDumpDebugger::MiniDumpDebugger(DebugManager* debugManager, DbgMiniDump* mini
 
 
 				auto miscEntry = &mMiniDump->GetData<char>(module.MiscRecord.Rva);				
 				auto miscEntry = &mMiniDump->GetData<char>(module.MiscRecord.Rva);				
 				
 				
-				mDebugTarget->mDbgModules.Add(dbgModule);
+				mDebugTarget->AddDbgModule(dbgModule);
 
 
 				//TESTING
 				//TESTING
 				/*{
 				/*{

+ 41 - 2
IDEHelper/WinDebugger.cpp

@@ -1531,6 +1531,24 @@ void WinDebugger::ReportMemory(MemReporter* memReporter)
 		mDebugTarget->ReportMemory(memReporter);
 		mDebugTarget->ReportMemory(memReporter);
 }
 }
 
 
+bool WinDebugger::GetEmitSource(const StringImpl& filePath, String& outText)
+{
+	if (!filePath.StartsWith("$Emit"))
+		return false;
+
+	int dollarPos = filePath.IndexOf('$', 1);
+	String numStr = filePath.Substring(5, dollarPos - 5);
+	int id = atoi(numStr.c_str());
+
+	for (auto dbgModule : mDebugTarget->mDbgModules)
+	{
+		if (dbgModule->mId == id)
+			return dbgModule->GetEmitSource(filePath, outText);
+	}
+
+	return false;
+}
+
 void WinDebugger::ModuleChanged(DbgModule* dbgModule)
 void WinDebugger::ModuleChanged(DbgModule* dbgModule)
 {
 {
 	mDebugManager->mOutMessages.push_back(String("dbgInfoLoaded ") + dbgModule->mFilePath);	
 	mDebugManager->mOutMessages.push_back(String("dbgInfoLoaded ") + dbgModule->mFilePath);	
@@ -11092,6 +11110,21 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
 			*outFlags |= FrameFlags_WasHotReplaced;
 			*outFlags |= FrameFlags_WasHotReplaced;
 	};
 	};
 
 
+	auto _FixFilePath = [&](DbgModule* dbgModule)
+	{
+		if (outFile == NULL)
+			return;
+
+		if (outFile->StartsWith("$Emit"))
+		{
+			int dollarPos = outFile->IndexOf('$', 1);
+			if (dollarPos == -1)
+				return;
+
+			outFile->Insert(dollarPos, StrFormat("%d", dbgModule->mId));
+		}
+	};
+
 	if (wdStackFrame->mInInlineMethod)
 	if (wdStackFrame->mInInlineMethod)
 	{		
 	{		
 		WdStackFrame* nextStackFrame = mCallStack[actualStackFrameIdx - 1];
 		WdStackFrame* nextStackFrame = mCallStack[actualStackFrameIdx - 1];
@@ -11122,6 +11155,7 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
 			*outLanguage = callingSubProgram->mCompileUnit->mLanguage;
 			*outLanguage = callingSubProgram->mCompileUnit->mLanguage;
 			auto srcFile = callingSrcFile;
 			auto srcFile = callingSrcFile;
 			*outFile = srcFile->GetLocalPath();
 			*outFile = srcFile->GetLocalPath();
+
 			_CheckHashSrcFile(*outFile, subProgram->mCompileUnit->mDbgModule, srcFile);
 			_CheckHashSrcFile(*outFile, subProgram->mCompileUnit->mDbgModule, srcFile);
 			if (*outLine == callingLineData->mLine)
 			if (*outLine == callingLineData->mLine)
 				*outColumn = callingLineData->mColumn;
 				*outColumn = callingLineData->mColumn;
@@ -11131,7 +11165,8 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
 		DbgModule* dbgModule = wdStackFrame->mSubProgram->mCompileUnit->mDbgModule;
 		DbgModule* dbgModule = wdStackFrame->mSubProgram->mCompileUnit->mDbgModule;
 		DbgModule* linkedModule = dbgModule->GetLinkedModule();
 		DbgModule* linkedModule = dbgModule->GetLinkedModule();
 		if (!linkedModule->mDisplayName.empty())
 		if (!linkedModule->mDisplayName.empty())
-			name = linkedModule->mDisplayName + "!" + name;
+			name = linkedModule->mDisplayName + "!" + name;		
+		_FixFilePath(dbgModule);
 		return name;
 		return name;
 	}
 	}
 	
 	
@@ -11211,10 +11246,12 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
 				*outDefLineEnd = dwEndLineData->mLine;
 				*outDefLineEnd = dwEndLineData->mLine;
 			}
 			}
 
 
+			_FixFilePath(dbgModule);
 			return demangledName;
 			return demangledName;
 		}
 		}
 		else
 		else
 		{
 		{
+			_FixFilePath(dbgModule);
 			return demangledName + StrFormat("+0x%X", pcAddress - dwSubprogram->mBlock.mLowPC);
 			return demangledName + StrFormat("+0x%X", pcAddress - dwSubprogram->mBlock.mLowPC);
 		}
 		}
 	}
 	}
@@ -11222,7 +11259,7 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
 	{
 	{
 		String symbolName;
 		String symbolName;
 		addr_target offset;
 		addr_target offset;
-		DbgModule* dbgModule;
+		DbgModule* dbgModule = NULL;
 		if (mDebugTarget->FindSymbolAt(pcAddress, &symbolName, &offset, &dbgModule))
 		if (mDebugTarget->FindSymbolAt(pcAddress, &symbolName, &offset, &dbgModule))
 		{			
 		{			
 			if (dbgModule->HasPendingDebugInfo())
 			if (dbgModule->HasPendingDebugInfo())
@@ -11242,6 +11279,7 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
 			String demangledName = BfDemangler::Demangle(symbolName, DbgLanguage_Unknown);
 			String demangledName = BfDemangler::Demangle(symbolName, DbgLanguage_Unknown);
 			if (!linkedModule->mDisplayName.empty())
 			if (!linkedModule->mDisplayName.empty())
 				demangledName = linkedModule->mDisplayName + "!" + demangledName;
 				demangledName = linkedModule->mDisplayName + "!" + demangledName;
+			_FixFilePath(dbgModule);
 			return demangledName + StrFormat("+0x%X", offset);			
 			return demangledName + StrFormat("+0x%X", offset);			
 		}		
 		}		
 	}
 	}
@@ -11257,6 +11295,7 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
 	String outName = EncodeDataPtr(pcAddress, true);	
 	String outName = EncodeDataPtr(pcAddress, true);	
 	if ((linkedModule != NULL) && (!linkedModule->mDisplayName.empty()))
 	if ((linkedModule != NULL) && (!linkedModule->mDisplayName.empty()))
 		outName = linkedModule->mDisplayName + "!" + outName;
 		outName = linkedModule->mDisplayName + "!" + outName;
+	_FixFilePath(dbgModule);
 	return outName;
 	return outName;
 }
 }
 
 

+ 2 - 1
IDEHelper/WinDebugger.h

@@ -657,10 +657,11 @@ public:
 	void AddProfiler(DbgProfiler* profiler);
 	void AddProfiler(DbgProfiler* profiler);
 	void RemoveProfiler(DbgProfiler* profiler);
 	void RemoveProfiler(DbgProfiler* profiler);
 
 
-	virtual void ReportMemory(MemReporter* memReporter) override;	
+	virtual void ReportMemory(MemReporter* memReporter) override;
 
 
 	virtual bool IsOnDemandDebugger() override { return false; }
 	virtual bool IsOnDemandDebugger() override { return false; }
 	virtual bool IsMiniDumpDebugger() { return false; }
 	virtual bool IsMiniDumpDebugger() { return false; }
+	virtual bool GetEmitSource(const StringImpl& filePath, String& outText);
 };
 };
 
 
 template<typename T> bool WinDebugger::WriteMemory(intptr addr, T val)
 template<typename T> bool WinDebugger::WriteMemory(intptr addr, T val)

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels