浏览代码

Improve emit views where compile and resolve emissions differ

Brian Fiete 3 年之前
父节点
当前提交
ab494ad8d4

+ 2 - 1
BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf

@@ -33,7 +33,7 @@ namespace Beefy.theme.dark
 
 			}
 
-			public virtual void MouseDown(float x, float y, int btn, int btnCount)
+			public virtual void MouseDown(Rect rect, float x, float y, int btn, int btnCount)
 			{
 
 			}
@@ -63,6 +63,7 @@ namespace Beefy.theme.dark
 		public bool mScrollToStartOnLostFocus;
 		public bool mHiliteCurrentLine;
 		public Dictionary<int32, Embed> mEmbeds = new .() ~ DeleteDictionaryAndValues!(_);
+		public Embed mEmbedSelected;
 		public Range? mLineRange;
 
 		protected static uint32[] sDefaultColors = new uint32[] ( Color.White ) ~ delete _;

+ 5 - 3
IDE/src/Compiler/BfCompiler.bf

@@ -156,7 +156,7 @@ namespace IDE.Compiler
 		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);
+		static extern char8* BfCompiler_GetEmitLocation(void* bfCompiler, char8* typeName, int32 line, out int32 embedLine, out int32 embedLineChar, out uint64 hash);
 
 		[CallingConvention(.Stdcall), CLink]
 		static extern void BfCompiler_WriteEmitData(void* bfCompiler, char8* filePath, void* bfProject);
@@ -362,11 +362,11 @@ namespace IDE.Compiler
 			return BfCompiler_GetEmitSourceVersion(mNativeBfCompiler, fileName.ToScopeCStr!());
 		}
 
-		public void GetEmitLocation(StringView typeName, int line, String outFilePath, out int embedLine, out int embedLineChar)
+		public void GetEmitLocation(StringView typeName, int line, String outFilePath, out int embedLine, out int embedLineChar, out uint64 hash)
 		{
 			int32 embedLine32;
 			int32 embedLineChar32;
-			outFilePath.Append(BfCompiler_GetEmitLocation(mNativeBfCompiler, typeName.ToScopeCStr!(), (.)line, out embedLine32, out embedLineChar32));
+			outFilePath.Append(BfCompiler_GetEmitLocation(mNativeBfCompiler, typeName.ToScopeCStr!(), (.)line, out embedLine32, out embedLineChar32, out hash));
 			embedLine = embedLine32;
 			embedLineChar = embedLineChar32;
 		}
@@ -603,6 +603,8 @@ namespace IDE.Compiler
 					UpdateRebuildFileWatches();
                     mBfSystem.RemoveOldParsers();
                     mBfSystem.RemoveOldData();
+					if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build)
+						QueueRefreshViewCommand(.Collapse);
                 }
 
                 if (command is ResolveAllCommand)

+ 10 - 0
IDE/src/Compiler/BfSystem.bf

@@ -239,6 +239,16 @@ namespace IDE.Compiler
             }
         }
 
+		public BfParser GetParser(ProjectSource projectSource)
+		{
+		    using (mMonitor.Enter())
+		    {
+				BfParser parser;
+				mParserMap.TryGetValue(projectSource, out parser);
+				return parser;
+			}
+		}
+
         public BfParser CreateNewParserRevision(BfParser prevParser)
         {
             using (mMonitor.Enter())

+ 55 - 16
IDE/src/IDEApp.bf

@@ -1472,6 +1472,14 @@ namespace IDE
 			return true;
 		}
 
+		public void SetEmbedCompiler(Settings.EditorSettings.CompilerKind emitCompiler)
+		{
+			gApp.mSettings.mEditorSettings.mEmitCompiler = emitCompiler;
+			mBfResolveCompiler?.QueueRefreshViewCommand(.Collapse);
+			if (emitCompiler == .Resolve)
+				mBfResolveCompiler?.QueueRefreshViewCommand(.FullRefresh);
+		}
+
 		public Result<void, FileError> LoadTextFile(String fileName, String outBuffer, bool autoRetry = true, delegate void() onPreFilter = null)
 		{
 			if (mWorkspace.IsSingleFileWorkspace)
@@ -1487,9 +1495,18 @@ namespace IDE
 
 			if (fileName.StartsWith("$Emit$"))
 			{
-				BfCompiler compiler = mBfResolveCompiler;
+				String useFileName = fileName;
+
+				BfCompiler compiler = (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve) ? mBfResolveCompiler : mBfBuildCompiler;
+
+				if (useFileName.StartsWith("$Emit$Build$"))
+				{
+					useFileName = scope:: $"$Emit${useFileName.Substring("$Emit$Build$".Length)}";
+					compiler = mBfBuildCompiler;
+				}
+
 				if (!compiler.IsPerformingBackgroundOperation())
-					compiler.GetEmitSource(fileName, outBuffer);
+					compiler.GetEmitSource(useFileName, outBuffer);
 				
 				if (onPreFilter != null)
 					onPreFilter();
@@ -5624,6 +5641,17 @@ namespace IDE
 			AddMenuItem(bookmarkMenu, "&Previous Bookmark", "Bookmark Prev");
 			AddMenuItem(bookmarkMenu, "&Clear Bookmarks", "Bookmark Clear");
 
+			var comptimeMenu = subMenu.AddMenuItem("Comptime");
+			var emitViewCompiler = comptimeMenu.AddMenuItem("Emit View Compiler");
+			var subItem = emitViewCompiler.AddMenuItem("Resolve", null,
+				new (menu) => { SetEmbedCompiler(.Resolve); } ,
+				new (menu) => { menu.SetCheckState((mSettings.mEditorSettings.mEmitCompiler == .Resolve) ? 1 : 0); },
+				null, true, (mSettings.mEditorSettings.mEmitCompiler == .Resolve) ? 1 : 0);
+			subItem = emitViewCompiler.AddMenuItem("Build", null,
+				new (menu) => { SetEmbedCompiler(.Build); } ,
+				new (menu) => { menu.SetCheckState((mSettings.mEditorSettings.mEmitCompiler == .Build) ? 1 : 0); },
+				null, true, (mSettings.mEditorSettings.mEmitCompiler == .Build) ? 1 : 0);
+			
 			var advancedEditMenu = subMenu.AddMenuItem("Advanced");
 			AddMenuItem(advancedEditMenu, "Duplicate Line", "Duplicate Line");
 			AddMenuItem(advancedEditMenu, "Move Line Up", "Move Line Up");
@@ -7095,10 +7123,11 @@ namespace IDE
 
         public SourceViewPanel ShowSourceFileLocation(String filePath, int showHotIdx, int refHotIdx, int line, int column, LocatorType hilitePosition, bool showTemp = false)
         {
+			var useFilePath = filePath;
+
 			if (filePath.StartsWith("$Emit$"))
 			{
-				var compiler = mBfResolveCompiler;
-				if (compiler.IsPerformingBackgroundOperation())
+				if ((mBfBuildCompiler.IsPerformingBackgroundOperation()) || (mBfResolveCompiler.IsPerformingBackgroundOperation()))
 				{
 					DeleteAndNullify!(mDeferredShowSource);
 					mDeferredShowSource = new DeferredShowSource()
@@ -7119,13 +7148,26 @@ namespace IDE
 				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();
+				mBfBuildCompiler.mBfSystem.Lock(0);
+				var embedFilePath = mBfBuildCompiler.GetEmitLocation(typeName, line, .. scope .(), var embedLine, var embedLineChar, var embedHash);
+				mBfBuildCompiler.mBfSystem.Unlock();
+
+				bool isViewValid = true;
 
-				if (!embedFilePath.IsEmpty)
+				if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve)
+				{
+					mBfResolveCompiler.mBfSystem.Lock(0);
+					mBfResolveCompiler.GetEmitLocation(typeName, line, .. scope .(), var resolveLine, var resolveLineChar, var resolveHash);
+					mBfResolveCompiler.mBfSystem.Unlock();
+
+					if ((resolveLine != embedLine) || (resolveLineChar != embedLineChar) || (embedHash != resolveHash))
+					{
+						isViewValid = false;
+						useFilePath = scope:: $"$Emit$Build${useFilePath.Substring("$Emit$".Length)}";
+					}
+				}
+
+				if ((!embedFilePath.IsEmpty) && (isViewValid))
 				{
 					var sourceViewPanel = ShowSourceFile(scope .(embedFilePath), null, showTemp ? SourceShowType.Temp : SourceShowType.ShowExisting).panel;
 					if (sourceViewPanel == null)
@@ -7141,11 +7183,7 @@ namespace IDE
 					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('<'))
 					{
@@ -7160,7 +7198,7 @@ namespace IDE
 				}
 			}
 
-            var (sourceViewPanel, tabButton) = ShowSourceFile(filePath, null, showTemp ? SourceShowType.Temp : SourceShowType.ShowExisting);
+            var (sourceViewPanel, tabButton) = ShowSourceFile(useFilePath, null, showTemp ? SourceShowType.Temp : SourceShowType.ShowExisting);
             if (sourceViewPanel == null)
                 return null;
 			if (((filePath.StartsWith("$")) && (var svTabButton = tabButton as SourceViewTabButton)))
@@ -14197,7 +14235,8 @@ namespace IDE
 			if (IDEApp.sApp.mSpellChecker != null)
 				IDEApp.sApp.mSpellChecker.CheckThreadDone();
 
-			if ((mDeferredShowSource != null) && (mBfResolveCompiler?.IsPerformingBackgroundOperation() == false))
+			if ((mDeferredShowSource != null) && (!mBfBuildCompiler.IsPerformingBackgroundOperation()) &&
+				(mBfResolveCompiler?.IsPerformingBackgroundOperation() != true))
 			{
 				var deferredShowSource = mDeferredShowSource;
 				mDeferredShowSource = null;

+ 9 - 0
IDE/src/Settings.bf

@@ -628,6 +628,12 @@ namespace IDE
 				Spaces
 			}
 
+			public enum CompilerKind
+			{
+				Resolve,
+				Build
+			}
+
 			public List<String> mFonts = new .() ~ DeleteContainerAndItems!(_);
 			public float mFontSize = 12;
 			public AutoCompleteShowKind mAutoCompleteShowKind = .PanelIfVisible;
@@ -641,6 +647,7 @@ namespace IDE
 			public bool mHiliteCurrentLine = false;
 			public bool mLockEditing;
 			public LockWhileDebuggingKind mLockEditingWhenDebugging = .WhenNotHotSwappable;// Only applicable for
+			public CompilerKind mEmitCompiler;
 			// non-Beef sources
 			public bool mPerforceAutoCheckout = true;
 			public bool mSpellCheckEnabled = true;
@@ -674,6 +681,7 @@ namespace IDE
 				sd.Add("HiliteCurrentLine", mHiliteCurrentLine);
 				sd.Add("LockEditing", mLockEditing);
 				sd.Add("LockEditingWhenDebugging", mLockEditingWhenDebugging);
+				sd.Add("EmitCompiler", mEmitCompiler);
 				sd.Add("PerforceAutoCheckout", mPerforceAutoCheckout);
 				sd.Add("SpellCheckEnabled", mSpellCheckEnabled);
 				sd.Add("ShowLineNumbers", mShowLineNumbers);
@@ -710,6 +718,7 @@ namespace IDE
 				sd.Get("HiliteCurrentLine", ref mHiliteCurrentLine);
 				sd.Get("LockEditing", ref mLockEditing);
 				sd.Get("LockEditingWhenDebugging", ref mLockEditingWhenDebugging);
+				sd.Get("EmitCompiler", ref mEmitCompiler);
 				sd.Get("PerforceAutoCheckout", ref mPerforceAutoCheckout);
 				sd.Get("SpellCheckEnabled", ref mSpellCheckEnabled);
 				sd.Get("ShowLineNumbers", ref mShowLineNumbers);

+ 143 - 28
IDE/src/ui/SourceEditWidgetContent.bf

@@ -224,7 +224,7 @@ namespace IDE.ui
 				{
 					mTypeName = new .(emitEmbed.mTypeName);
 					mEmitEmbed = emitEmbed;
-					mSourceViewPanel = new SourceViewPanel((emitEmbed.mEmitKind == .Method) ? .Method : .Type);
+					mSourceViewPanel = new SourceViewPanel((emitEmbed.mEmitKind == .Emit_Method) ? .Method : .Type);
 					mSourceViewPanel.mEmbedParent = mEmitEmbed.mEditWidgetContent.mSourceViewPanel;
 					var emitPath = scope $"$Emit${emitEmbed.mTypeName}";
 
@@ -382,7 +382,7 @@ namespace IDE.ui
 					}
 
 					mAwaitingLoad = false;
-					if (!mEmitRemoved)
+					if ((!mEmitRemoved) && (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve))
 					{
 						for (var explicitTypeName in mEmitEmbed.mEditWidgetContent.mSourceViewPanel.[Friend]mExplicitEmitTypes)
 						{
@@ -397,6 +397,9 @@ namespace IDE.ui
 
 					if ((mAwaitingLoad) && (gApp.mUpdateCnt % 4 == 0))
 						MarkDirty();
+
+					if (mSourceViewPanel.HasFocus())
+						mEmitEmbed.mEditWidgetContent.mEmbedSelected = mEmitEmbed;
 				}
 
 				public void GetGenericTypes()
@@ -516,6 +519,10 @@ namespace IDE.ui
 			public int32 mEndLine;
 			public View mView;
 
+			public this()
+			{
+			}
+
 			public ~this()
 			{
 				if (mView != null)
@@ -525,17 +532,29 @@ namespace IDE.ui
 				}
 			}
 
+			public bool IsSelected => mEditWidgetContent.mEmbedSelected == this;
+			public float LabelWidth = GS!(42);
+			
 			public override float GetWidth(bool hideLine)
 			{
-				return GS!(42);
+				return IsSelected ? GS!(60) : LabelWidth;
 			}
 
 			public override void Draw(Graphics g, Rect rect, bool hideLine)
 			{
+				var rect;
+				rect.mWidth = LabelWidth;
+
 				if (rect.mHeight >= DarkTheme.sDarkTheme.mSmallBoldFont.GetLineSpacing())
 					g.SetFont(DarkTheme.sDarkTheme.mSmallBoldFont);
 
-				using (g.PushColor(0x80707070))
+				uint32 fillColor = 0x80707070;
+				if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build)
+				{
+					fillColor = 0x805050E0;
+				}
+
+				using (g.PushColor(fillColor))
 				{
 					g.FillRect(rect.mX + 1, rect.mY + 1, rect.mWidth - 2, rect.mHeight - 2);
 				}
@@ -558,6 +577,40 @@ namespace IDE.ui
 
 				var summaryString = "Emit";
 				g.DrawString(summaryString, rect.mX, rect.mY + (int)((rect.mHeight - g.mFont.GetLineSpacing()) * 0.5f), .Centered, rect.mWidth);
+
+				if (IsSelected)
+				{
+					g.Draw(DarkTheme.sDarkTheme.GetImage(.DropMenuButton), rect.Right, rect.Top);
+				}
+			}
+
+			public override void MouseDown(Rect rect, float x, float y, int btn, int btnCount)
+			{
+				base.MouseDown(rect, x, y, btn, btnCount);
+				if (x >= rect.mX + LabelWidth)
+					ShowMenu(x, y);
+			}
+
+			public void ShowMenu(float x, float y)
+			{
+				Menu menuItem;
+
+				Menu menu = new Menu();
+				menuItem = menu.AddItem("Compiler");
+
+				var subItem = menuItem.AddItem("Resolve");
+				if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve)
+					subItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
+				subItem.mOnMenuItemSelected.Add(new (menu) => { gApp.SetEmbedCompiler(.Resolve); });
+
+				subItem = menuItem.AddItem("Build");
+				if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build)
+					subItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
+				subItem.mOnMenuItemSelected.Add(new (menu) => { gApp.SetEmbedCompiler(.Build); });
+
+				MenuWidget menuWidget = DarkTheme.sDarkTheme.CreateMenuWidget(menu);
+
+				menuWidget.Init(mEditWidgetContent, x, y);
 			}
 		}
 
@@ -575,10 +628,11 @@ namespace IDE.ui
 				case UsingNamespaces = 'U';
 				case Unknown = '?';
 				case HasUncertainEmits = '~';
-				case Emit = 'e';
+				case Emit_Type = 't';
+				case Emit_Method = 'm';
 				case EmitAddType = '+';
 
-				public bool IsEmit => (this == .Emit);
+				public bool IsEmit => (this == .Emit_Type) || (this == .Emit_Method);
 			}
 
 			public Kind mKind;
@@ -614,6 +668,7 @@ namespace IDE.ui
 			public bool mOnlyInResolveAll;
 			public bool mIncludedInClassify;
 			public bool mIncludedInResolveAll;
+			public bool mIncludedInBuild;
 
 			public int32 mAnchorId;
 		}
@@ -4408,6 +4463,7 @@ namespace IDE.ui
         public override void KeyDown(KeyCode keyCode, bool isRepeat)
         {
 			mIgnoreKeyChar = false;
+			mEmbedSelected = null;
 
 			bool autoCompleteRequireControl = (gApp.mSettings.mEditorSettings.mAutoCompleteRequireControl) && (mIsMultiline);
 
@@ -4463,7 +4519,6 @@ namespace IDE.ui
             {
                 return;
             }
-                       
 
             if ((keyCode == KeyCode.Escape) && (mSelection != null) && (mSelection.Value.HasSelection))
             {
@@ -4696,6 +4751,23 @@ namespace IDE.ui
         {
             base.MouseClicked(x, y, origX, origY, btn);
 
+			if (btn == 1)
+			{
+				int line = GetLineAt(y);
+				if (mEmbeds.GetValue((.)line) case .Ok(let embed))
+				{
+					Rect embedRect = GetEmbedRect(line, embed);
+					if (embedRect.Contains(x, y))
+					{
+						if (var emitEmbed = embed as EmitEmbed)
+						{
+							emitEmbed.ShowMenu(x, y);
+						}
+						return;
+					}
+				}
+			}
+
 			var useX = x;
 			var useY = y;
 
@@ -5019,20 +5091,26 @@ namespace IDE.ui
 				Rect embedRect = GetEmbedRect(line, embed);
 				if (embedRect.Contains(x, y))
 				{
-					if ((btn == 0) && (btnCount % 2 == 0))
+					mEmbedSelected = embed;
+					embed.MouseDown(GetEmbedRect(line, embed), x, y, btn, btnCount);
+					if (btn == 0)
 					{
-						if (var collapseSummary = embed as SourceEditWidgetContent.CollapseSummary)
-							SetCollapseOpen(collapseSummary.mCollapseIndex, true);
-						else if (var emitEmbed = embed as EmitEmbed)
+						if (btnCount % 2 == 0)
 						{
-							emitEmbed.mIsOpen = !emitEmbed.mIsOpen;
-							mCollapseNeedsUpdate = true;
+							if (var collapseSummary = embed as SourceEditWidgetContent.CollapseSummary)
+								SetCollapseOpen(collapseSummary.mCollapseIndex, true);
+							else if (var emitEmbed = embed as EmitEmbed)
+							{
+								emitEmbed.mIsOpen = !emitEmbed.mIsOpen;
+								mCollapseNeedsUpdate = true;
+							}
 						}
 					}
 					return;
 				}
 			}
 
+			mEmbedSelected = null;
 			base.MouseDown(x, y, btn, btnCount);
 		}
 
@@ -5727,6 +5805,13 @@ namespace IDE.ui
 			}
 		}
 
+		void DeleteEmbed(Embed embed)
+		{
+			if (mEmbedSelected == embed)
+				mEmbedSelected = null;
+			delete embed;
+		}
+
 		public override void GetTextData()
 		{
 			var data = Data;
@@ -5755,8 +5840,14 @@ namespace IDE.ui
 					}
 				}
 
+				IdSpan.LookupContext lookupCtx = null;
+
 				for (var emitData in ref data.mEmitData)
 				{
+					if (lookupCtx == null)
+						lookupCtx = scope:: .(mData.mTextIdData);
+					emitData.mAnchorIdx = (.)lookupCtx.GetIndexFromId(emitData.mAnchorId);
+
 					GetLineCharAtIdx(emitData.mAnchorIdx, var line, var lineChar);
 
 					SourceEditWidgetContent.EmitEmbed emitEmbed = null;
@@ -5776,7 +5867,7 @@ namespace IDE.ui
 							else
 							{
 								//Debug.WriteLine($"  Occupied- deleting {emitEmbed}");
-								delete emitEmbed;
+								DeleteEmbed(emitEmbed);
 								emitEmbed = null;
 							}
 						}
@@ -5837,7 +5928,7 @@ namespace IDE.ui
 					{
 						mCollapseNeedsUpdate = true;
 						mEmbeds.Remove(emitEmbed.mLine);
-						delete emitEmbed;
+						DeleteEmbed(emitEmbed);
 					}
 				}
 
@@ -5863,7 +5954,7 @@ namespace IDE.ui
 							if (!(value is EmitEmbed))
 							{
 								mEmbeds.Remove(entry.mAnchorLine);
-								delete value;
+								DeleteEmbed(value);
 							}
 						}
 						@entry.Remove();
@@ -5888,7 +5979,7 @@ namespace IDE.ui
 						{
 							//Debug.WriteLine($" Removing {val.value}");
 							if (val.value is CollapseSummary)
-								delete val.value;
+								DeleteEmbed(val.value);
 						}
 						continue;
 					}
@@ -5914,7 +6005,7 @@ namespace IDE.ui
 						else
 						{
 							//Debug.WriteLine($" Deleting(3) {val}");
-							delete val;
+							DeleteEmbed(val);
 						}
 					}
 				}
@@ -6241,7 +6332,7 @@ namespace IDE.ui
 					{
 						if ((embed.mKind == .HideLine) || (embed.mKind == .LineEnd))
 						{
-							delete embed;
+							DeleteEmbed(embed);
 							mEmbeds.Remove(entry.mAnchorLine);
 						}
 					}
@@ -6283,7 +6374,7 @@ namespace IDE.ui
 					if (!(value is EmitEmbed))
 					{
 						mEmbeds.Remove(prevAnchorLine);
-						delete value;
+						DeleteEmbed(value);
 					}
 				}
 
@@ -6304,7 +6395,7 @@ namespace IDE.ui
 					else
 					{
 						//Debug.WriteLine($"  Occupied- deleting {val}");
-						delete val.value;
+						DeleteEmbed(val.value);
 					}
 				}
 			}
@@ -6360,7 +6451,7 @@ namespace IDE.ui
 				if (entry.mDeleted)
 				{
 					if (mEmbeds.GetAndRemove(entry.mAnchorIdx) case .Ok(let val))
-						delete val.value;
+						DeleteEmbed(val.value);
 					continue;
 				}
 
@@ -6388,7 +6479,7 @@ namespace IDE.ui
 								*valuePtr = val.value;
 							}
 							else
-								delete val.value;
+								DeleteEmbed(val.value);
 						}
 					}
 				}
@@ -6401,7 +6492,7 @@ namespace IDE.ui
 				RehupLineCoords();
 		}
 
-		public void ParseCollapseRegions(String collapseText, int32 textVersion, ref IdSpan idSpan, ResolveType resolveType)
+		public void ParseCollapseRegions(String collapseText, int32 textVersion, ref IdSpan idSpan, ResolveType? resolveType)
 		{
 			/*if (resolveType == .None)
 				return;*/
@@ -6415,6 +6506,8 @@ namespace IDE.ui
 				data.ClearCollapse();
 			}
 
+			bool wantsBuildEmits = gApp.mSettings.mEditorSettings.mEmitCompiler == .Build;
+
 			//Debug.WriteLine($"ParseCollapseRegions {resolveType} CollapseRevision:{data.mCollapseParseRevision+1} TextVersion:{textVersion} IdSpan:{idSpan:D}");
 
 			List<int32> typeNameIdxMap = scope .();
@@ -6429,7 +6522,7 @@ namespace IDE.ui
 				if (emitInitialized)
 					return;
 				emitInitialized = true;
-				if ((hasUncertainEmits) || (resolveType == .None))
+				if ((hasUncertainEmits) || (wantsBuildEmits) || (resolveType == .None))
 				{
 					// Leave emits alone
 					for (var typeName in data.mTypeNames)
@@ -6437,7 +6530,11 @@ namespace IDE.ui
 					for (var emitData in ref data.mEmitData)
 					{
 						emitAnchorIds[emitData.mAnchorId] = (.)@emitData.Index;
-						if (resolveType == .None)
+						if (resolveType == null)
+						{
+							// Do nothing
+						}
+						else if (resolveType == .None)
 							emitData.mIncludedInResolveAll = false;
 						else
 							emitData.mIncludedInClassify = false;
@@ -6491,6 +6588,7 @@ namespace IDE.ui
 					emitData.mOnlyInResolveAll = resolveType == .None;
 					emitData.mIncludedInClassify = resolveType != .None;
 					emitData.mIncludedInResolveAll = resolveType == .None;
+					emitData.mIncludedInBuild = resolveType == null;
 
 					if (emitData.mAnchorIdx == -1)
 					{
@@ -6508,8 +6606,14 @@ namespace IDE.ui
 						{
 							curEmitData.mIncludedInResolveAll = true;
 						}
+						else if ((wantsBuildEmits) && (resolveType != null))
+						{
+							curEmitData.mIncludedInBuild |= emitData.mIncludedInBuild;
+							curEmitData.mIncludedInClassify |= emitData.mIncludedInClassify;
+						}
 						else
 						{
+							emitData.mIncludedInBuild |= curEmitData.mIncludedInBuild;
 							emitData.mIncludedInClassify |= curEmitData.mIncludedInClassify;
 							curEmitData = emitData;
 						}
@@ -6517,12 +6621,19 @@ namespace IDE.ui
 						continue;
 					}
 
+					if ((wantsBuildEmits) && (resolveType != null))
+					{
+						// Not included in the build emit data - just show as a marker
+						emitData.mStartLine = 0;
+						emitData.mEndLine = 0;
+					}
+
 					//Debug.WriteLine($" New emit AnchorIdx:{emitData.mAnchorIdx} AnchorId:{emitData.mAnchorId} CurTextVersion:{textVersion} FoundTextVersion:{foundTextVersion}");
 					data.mEmitData.Add(emitData);
 					continue;
 				}
 
-				if (resolveType == .None)
+				if ((resolveType == null) || (resolveType == .None))
 					continue;
 
 				CollapseData collapseData;
@@ -6554,7 +6665,11 @@ namespace IDE.ui
 
 			for (var emitData in ref data.mEmitData)
 			{
-				if (((emitData.mOnlyInResolveAll) && (!emitData.mIncludedInResolveAll)) ||
+				if ((emitData.mIncludedInBuild) && (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build))
+				{
+					// Allow build-only markers to survive
+				}
+				else if (((emitData.mOnlyInResolveAll) && (!emitData.mIncludedInResolveAll)) ||
 					((!emitData.mOnlyInResolveAll) && (!emitData.mIncludedInClassify)))
 				{
 					@emitData.RemoveFast();

+ 64 - 9
IDE/src/ui/SourceViewPanel.bf

@@ -367,6 +367,7 @@ namespace IDE.ui
 	class QueuedCollapseData
 	{
 		public String mData = new .() ~ delete _;
+		public String mBuildData ~ delete _;
 		public int32 mTextVersion;
 		public IdSpan mCharIdSpan ~ _.Dispose();
 		public ResolveType mResolveType;
@@ -1262,6 +1263,9 @@ namespace IDE.ui
 
 			void FindEmbeds(ResolveParams resolveParams)
 			{
+				if (gApp.mSettings.mEditorSettings.mEmitCompiler != .Resolve)
+					return;
+
 				HashSet<FileEditData> foundEditData = scope .();
 				Dictionary<String, String> remappedTypeNames = scope .();
 
@@ -1478,11 +1482,27 @@ namespace IDE.ui
 
 			var collapseData = bfCompiler.GetCollapseRegions(parser, resolvePassData, explicitEmitTypeNames, .. scope .());
 
+			String buildCollapseData = null;
+			if ((gApp.mSettings.mEditorSettings.mEmitCompiler == .Build) && (!gApp.mBfBuildCompiler.IsPerformingBackgroundOperation()))
+			{
+				gApp.mBfBuildSystem.Lock(0);
+				var buildParser = gApp.mBfBuildSystem.GetParser(mProjectSource);
+				if (buildParser != null)
+				{
+					var buildResolvePassData = buildParser.CreateResolvePassData(.None);
+					defer delete buildResolvePassData;
+					buildCollapseData = gApp.mBfBuildCompiler.GetCollapseRegions(buildParser, buildResolvePassData, explicitEmitTypeNames, .. scope:: .());
+				}
+				gApp.mBfBuildSystem.Unlock();
+			}
+
 			using (mMonitor.Enter())
 			{
 				DeleteAndNullify!(mQueuedCollapseData);
 				mQueuedCollapseData = new .();
 				mQueuedCollapseData.mData.Set(collapseData);
+				if (buildCollapseData != null)
+					mQueuedCollapseData.mBuildData = new String(buildCollapseData);
 				mQueuedCollapseData.mTextVersion = textVersion;
 				mQueuedCollapseData.mCharIdSpan = charIdSpan.Duplicate();
 
@@ -1524,13 +1544,13 @@ namespace IDE.ui
 				return;
             //var compiler = ResolveCompiler;
 
-            var char8Data = mEditWidget.Content.mData.mText;
-            int char8Len = Math.Min(char8Data.Count, mEditWidget.Content.mData.mTextLength);
+            var charData = mEditWidget.Content.mData.mText;
+            int charLen = Math.Min(charData.Count, mEditWidget.Content.mData.mTextLength);
 
-            char8[] chars = new char8[char8Len];
+            char8[] chars = new char8[charLen];
 			defer delete chars;
-            for (int32 i = 0; i < char8Len; i++)
-                chars[i] = (char8)char8Data[i].mChar;
+            for (int32 i = 0; i < charLen; i++)
+                chars[i] = (char8)charData[i].mChar;
 
             String text = scope String();
             text.Append(chars, 0, chars.Count);
@@ -1554,7 +1574,7 @@ namespace IDE.ui
 				parser.SetEmbedKind(mEmbedKind);
                 parser.Reduce(passInstance);
 			}
-            parser.ClassifySource(char8Data, !mIsBeefSource);
+            parser.ClassifySource(charData, !mIsBeefSource);
 			mWantsParserCleanup = true;
         }
 
@@ -2208,7 +2228,7 @@ namespace IDE.ui
             {
 				parser.CreateClassifier(passInstance, resolvePassData, charData);
 
-				if (resolveParams != null)
+				if ((resolveParams != null) && (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve))
 				{
 					for (var emitEmbedData in resolveParams.mEmitEmbeds)
 					{
@@ -6588,7 +6608,7 @@ namespace IDE.ui
 				}
                 if ((mTicksSinceTextChanged >= 60) && (mWantsSpellCheck))
                 {
-					if (IsControllingEditData())
+					if ((IsControllingEditData()) && (mEmbedKind == .None))
                     	StartSpellCheck();
                     mWantsSpellCheck = false;
                 }
@@ -6843,7 +6863,42 @@ namespace IDE.ui
 			using (mMonitor.Enter())
 			{
 				if (mQueuedCollapseData != null)
+				{
+					if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build)
+					{
+						if (mQueuedCollapseData.mBuildData != null)
+						{
+							using (gApp.mMonitor.Enter())
+							{                
+							    var projectSourceCompileInstance = gApp.mWorkspace.GetProjectSourceCompileInstance(projectSource, gApp.mWorkspace.HotCompileIdx);
+								if (projectSourceCompileInstance != null)
+								{
+									ewc.ParseCollapseRegions(mQueuedCollapseData.mBuildData, mQueuedCollapseData.mTextVersion, ref projectSourceCompileInstance.mSourceCharIdData, null);
+
+									HashSet<EditWidgetContent.Data> dataLoaded = scope .();
+
+									for (var embed in ewc.mEmbeds.Values)
+									{
+										if (var emitEmbed = embed as SourceEditWidgetContent.EmitEmbed)
+										{
+											if (emitEmbed.mView != null)
+											{
+												if (dataLoaded.Add(emitEmbed.mView.mSourceViewPanel.mEditWidget.mEditWidgetContent.mData))
+												{
+													emitEmbed.mView.mSourceViewPanel.mSkipFastClassify = false;
+													emitEmbed.mView.mSourceViewPanel.Reload();
+													emitEmbed.mView.mSourceViewPanel.mWantsFastClassify = true;
+												}
+											}
+										}
+									}
+								}
+							}
+						}
+					}
+					
 					ewc.ParseCollapseRegions(mQueuedCollapseData.mData, mQueuedCollapseData.mTextVersion, ref mQueuedCollapseData.mCharIdSpan, mQueuedCollapseData.mResolveType);
+				}
 				DeleteAndNullify!(mQueuedCollapseData);
 			}
 
@@ -7063,7 +7118,7 @@ namespace IDE.ui
 
         float GetEditX()
         {
-			if (!gApp.mSettings.mEditorSettings.mShowLineNumbers && (mEmbedKind == .None))
+			if ((!gApp.mSettings.mEditorSettings.mShowLineNumbers) || (mEmbedKind != .None))
 				return GS!(24);
 
             var font = IDEApp.sApp.mTinyCodeFont;

+ 11 - 6
IDEHelper/Compiler/BfCompiler.cpp

@@ -9399,7 +9399,7 @@ int BfCompiler::GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer)
 	return typeInst->mRevision;
 }
 
-String BfCompiler::GetEmitLocation(const StringImpl& typeName, int emitLine, int& outEmbedLine, int& outEmbedLineChar)
+String BfCompiler::GetEmitLocation(const StringImpl& typeName, int emitLine, int& outEmbedLine, int& outEmbedLineChar, uint64& outHash)
 {
 	outEmbedLine = 0;
 
@@ -9443,6 +9443,8 @@ String BfCompiler::GetEmitLocation(const StringImpl& typeName, int emitLine, int
 		int endLineChar = 0;
 		emitParser->GetLineCharAtIdx(kv.mValue.mSrcEnd - 1, endLine, endLineChar);
 
+		outHash = Hash64(emitParser->mSrc + kv.mValue.mSrcStart, kv.mValue.mSrcEnd - kv.mValue.mSrcStart);
+
 		if ((emitLine >= startLine) && (emitLine <= endLine))
 		{			
 			origParser->GetLineCharAtIdx(charIdx, outEmbedLine, outEmbedLineChar);
@@ -10071,7 +10073,9 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCo
 					auto declParser = typeInst->mTypeDef->mTypeDeclaration->GetParser();
 					if (declParser != NULL)
 						textVersion = declParser->mTextVersion;
-					outString += StrFormat("e%d,%d,%d,%d,%d\n", embedId, charIdx, startLine, endLine + 1, textVersion);
+
+					char emitChar = (kv.mValue.mKind == BfCeTypeEmitSourceKind_Type) ? 't' : 'm';
+					outString += StrFormat("%c%d,%d,%d,%d,%d\n", emitChar, embedId, charIdx, startLine, endLine + 1, textVersion);
 				}
 			}
 
@@ -10091,7 +10095,7 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCo
 					Dictionary<int, _EmitSource>* map = NULL;
 					if (emitLocMap.TryGetValue(typeDef, &map))
 					{
-						for (auto kv : *map)
+						for (auto& kv : *map)
 						{
 							if (kv.mValue.mIsPrimary)
 								continue;
@@ -10100,7 +10104,8 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCo
 							if (embedId == -1)
 								continue;
 
-							outString += StrFormat("e%d,%d,%d,%d,%d\n", embedId, kv.mKey, 0, 0, -1);
+							char emitChar = 't';
+							outString += StrFormat("%c%d,%d,%d,%d,%d\n", emitChar, embedId, kv.mKey, 0, 0, -1);
 						}
 					}
 				};
@@ -10909,11 +10914,11 @@ BF_EXPORT int32 BF_CALLTYPE BfCompiler_GetEmitSourceVersion(BfCompiler* bfCompil
 	return bfCompiler->GetEmitSource(fileName, NULL);
 }
 
-BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetEmitLocation(BfCompiler* bfCompiler, char* typeName, int line, int& outEmbedLine, int& outEmbedLineChar)
+BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetEmitLocation(BfCompiler* bfCompiler, char* typeName, int line, int& outEmbedLine, int& outEmbedLineChar, uint64& outHash)
 {
 	String& outString = *gTLStrReturn.Get();
 	outString.clear();
-	outString = bfCompiler->GetEmitLocation(typeName, line, outEmbedLine, outEmbedLineChar);
+	outString = bfCompiler->GetEmitLocation(typeName, line, outEmbedLine, outEmbedLineChar, outHash);
 	return outString.c_str();
 }
 

+ 1 - 1
IDEHelper/Compiler/BfCompiler.h

@@ -552,7 +552,7 @@ public:
 	int GetTypeId(const StringImpl& typeName);
 	BfType* GetType(const StringImpl& typeName);
 	int GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer);
-	String GetEmitLocation(const StringImpl& typeName, int line, int& outEmbedLine, int& outEmbedLineChar);
+	String GetEmitLocation(const StringImpl& typeName, int line, int& outEmbedLine, int& outEmbedLineChar, uint64& outHash);
 	bool WriteEmitData(const StringImpl& filePath, BfProject* project);
 
 	void CompileLog(const char* fmt ...);