diff --git a/BeefLibs/Beefy2D/src/utils/IdSpan.bf b/BeefLibs/Beefy2D/src/utils/IdSpan.bf index a66497a8..df3197bf 100644 --- a/BeefLibs/Beefy2D/src/utils/IdSpan.bf +++ b/BeefLibs/Beefy2D/src/utils/IdSpan.bf @@ -3,6 +3,7 @@ using System.Collections; using System.Diagnostics; using System.Text; using System.Threading.Tasks; +using System.Security.Cryptography; namespace Beefy.utils { @@ -1061,7 +1062,7 @@ namespace Beefy.utils if (cmd == 0) { - outString.Append("}"); + outString.AppendF($"}} EndIdx:{charIdx}"); return; } @@ -1070,5 +1071,12 @@ namespace Beefy.utils } } } + + public int GetHashCode() mut + { + Prepare(); + var hash = MD5.Hash(.(mData, 0, mLength)); + return *(int*)&hash; + } } } diff --git a/IDE/src/Compiler/BfCompiler.bf b/IDE/src/Compiler/BfCompiler.bf index 84dfe824..2576b903 100644 --- a/IDE/src/Compiler/BfCompiler.bf +++ b/IDE/src/Compiler/BfCompiler.bf @@ -555,9 +555,9 @@ namespace IDE.Compiler var bfParser = mBfSystem.CreateParser(projectSourceCommand.mProjectSource); if (data != null) - bfParser.SetSource(data, sourceFilePath); + bfParser.SetSource(data, sourceFilePath, -1); else - bfParser.SetSource("", sourceFilePath); + bfParser.SetSource("", sourceFilePath, -1); bfParser.SetCharIdData(ref char8IdData); if (hash case .MD5(let md5Hash)) diff --git a/IDE/src/Compiler/BfParser.bf b/IDE/src/Compiler/BfParser.bf index 2101d0c3..e16a024a 100644 --- a/IDE/src/Compiler/BfParser.bf +++ b/IDE/src/Compiler/BfParser.bf @@ -115,7 +115,7 @@ namespace IDE.Compiler static extern void BfSystem_DeleteParser(void* bfSystem, void* bfParser); [CallingConvention(.Stdcall), CLink] - static extern void BfParser_SetSource(void* bfParser, char8* data, int32 length, char8* fileName); + static extern void BfParser_SetSource(void* bfParser, char8* data, int32 length, char8* fileName, int32 textVersion); [CallingConvention(.Stdcall), CLink] static extern void BfParser_SetCharIdData(void* bfParser, uint8* data, int32 length); @@ -197,11 +197,11 @@ namespace IDE.Compiler mNativeBfParser = null; } - public void SetSource(StringView data, String fileName) + public void SetSource(StringView data, String fileName, int textVersion) { Debug.Assert(!mIsUsed); mIsUsed = true; - BfParser_SetSource(mNativeBfParser, data.Ptr, (int32)data.Length, fileName); + BfParser_SetSource(mNativeBfParser, data.Ptr, (int32)data.Length, fileName, (.)textVersion); } public void SetCharIdData(ref IdSpan char8IdData) diff --git a/IDE/src/Compiler/BfPassInstance.bf b/IDE/src/Compiler/BfPassInstance.bf index def1f60d..52283db7 100644 --- a/IDE/src/Compiler/BfPassInstance.bf +++ b/IDE/src/Compiler/BfPassInstance.bf @@ -31,7 +31,7 @@ namespace IDE.Compiler [CallingConvention(.Stdcall), CLink] static extern char8* BfPassInstance_GetErrorData(void* mNativeResolvePassData, int32 errorIdx, out int32 code, out bool isWarning, - out bool isAfter, out bool isDeferred, out bool isWhileSpecializing, out bool isPersistent, out char8* projectName, + out bool isAfter, out bool isDeferred, out int8 isWhileSpecializing, out bool isPersistent, out char8* projectName, out char8* fileName, out int32 srcStart, out int32 srcEnd, int32* srcLine, int32* srcColumn, out int32 moreInfoCount); [CallingConvention(.Stdcall), CLink] @@ -42,11 +42,18 @@ namespace IDE.Compiler public class BfError { + public enum SpecializingKind + { + None, + Type, + Method + } + public bool mIsWarning; public int32 mCode; public bool mIsAfter; public bool mIsDeferred; - public bool mIsWhileSpecializing; + public SpecializingKind mWhileSpecializing; public bool mIsPersistent; public String mProject ~ delete _; public String mError ~ delete _; @@ -127,7 +134,7 @@ namespace IDE.Compiler char8* projectName = null; char8* fileName = null; bfError.mError = new String(BfPassInstance_GetErrorData(mNativeBfPassInstance, errorIdx, out bfError.mCode, out bfError.mIsWarning, out bfError.mIsAfter, out bfError.mIsDeferred, - out bfError.mIsWhileSpecializing, out bfError.mIsPersistent, out projectName, out fileName, out bfError.mSrcStart, out bfError.mSrcEnd, + out *(int8*)&bfError.mWhileSpecializing, out bfError.mIsPersistent, out projectName, out fileName, out bfError.mSrcStart, out bfError.mSrcEnd, getLine ? &bfError.mLine : null, getLine ? &bfError.mColumn : null, out bfError.mMoreInfoCount)); if (projectName != null) diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 70c8425c..be821696 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -5725,7 +5725,7 @@ namespace IDE internalDebugMenu.AddMenuItem("Error Test", null, new (menu) => { DoErrorTest(); } ); internalDebugMenu.AddMenuItem("Reconnect BeefPerf", null, new (menu) => { BeefPerf.RetryConnect(); } ); AddMenuItem(internalDebugMenu, "Report Memory", "Report Memory"); - internalDebugMenu.AddMenuItem("Crash", null, new (menu) => { Runtime.FatalError("Bad"); }); + internalDebugMenu.AddMenuItem("Crash", null, new (menu) => { int* ptr = null; *ptr = 123; }); internalDebugMenu.AddMenuItem("Show Welcome", null, new (menu) => { ShowWelcome(); }); internalDebugMenu.AddMenuItem("Exit Test", null, new (menu) => { ExitTest(); }); internalDebugMenu.AddMenuItem("Run Test", null, new (menu) => { mRunTest = !mRunTest; }); @@ -8969,7 +8969,7 @@ namespace IDE mFileWatcher.FileIsValid(fullPath); var bfParser = bfSystem.CreateParser(projectSource); - bfParser.SetSource(data, fullPath); + bfParser.SetSource(data, fullPath, -1); worked &= bfParser.Parse(passInstance, false); worked &= bfParser.Reduce(passInstance); worked &= bfParser.BuildDefs(passInstance, null, false); diff --git a/IDE/src/ui/DisassemblyPanel.bf b/IDE/src/ui/DisassemblyPanel.bf index cd3802cd..183b0255 100644 --- a/IDE/src/ui/DisassemblyPanel.bf +++ b/IDE/src/ui/DisassemblyPanel.bf @@ -331,7 +331,7 @@ namespace IDE.ui var passInstance = bfSystem.CreatePassInstance(); parser.SetIsClassifying(); - parser.SetSource(text, useFileName); + parser.SetSource(text, useFileName, -1); parser.Parse(passInstance, !isBeefSource); if (isBeefSource) parser.Reduce(passInstance); diff --git a/IDE/src/ui/SourceEditWidgetContent.bf b/IDE/src/ui/SourceEditWidgetContent.bf index 90e6ef96..d3e0a5a9 100644 --- a/IDE/src/ui/SourceEditWidgetContent.bf +++ b/IDE/src/ui/SourceEditWidgetContent.bf @@ -217,6 +217,7 @@ namespace IDE.ui public Monitor mMonitor = new .() ~ delete _; public WorkState mTypeWorkState; public bool mAwaitingLoad; + public bool mEmitRemoved; bool mIgnoreChange = false; public this(EmitEmbed emitEmbed) @@ -263,6 +264,11 @@ namespace IDE.ui } } + public ~this() + { + + } + private void GenericTypeEditChanged(EditEvent theEvent) { if (mIgnoreChange) @@ -376,16 +382,19 @@ namespace IDE.ui } mAwaitingLoad = false; - for (var explicitTypeName in mEmitEmbed.mEditWidgetContent.mSourceViewPanel.[Friend]mExplicitEmitTypes) + if (!mEmitRemoved) { - if ((IDEUtils.GenericEquals(mTypeName, explicitTypeName)) && (mTypeName != explicitTypeName)) + for (var explicitTypeName in mEmitEmbed.mEditWidgetContent.mSourceViewPanel.[Friend]mExplicitEmitTypes) + { + if ((IDEUtils.GenericEquals(mTypeName, explicitTypeName)) && (mTypeName != explicitTypeName)) + mAwaitingLoad = true; + } + + var ewc = (SourceEditWidgetContent)mSourceViewPanel.mEditWidget.mEditWidgetContent; + if ((ewc.mLineRange.GetValueOrDefault().Length != 0) && (mSourceViewPanel.mEditWidget.mEditWidgetContent.mData.mTextLength == 0)) mAwaitingLoad = true; } - var ewc = (SourceEditWidgetContent)mSourceViewPanel.mEditWidget.mEditWidgetContent; - if ((ewc.mLineRange.GetValueOrDefault().Length != 0) && (mSourceViewPanel.mEditWidget.mEditWidgetContent.mData.mTextLength == 0)) - mAwaitingLoad = true; - if ((mAwaitingLoad) && (gApp.mUpdateCnt % 4 == 0)) MarkDirty(); } @@ -415,7 +424,7 @@ namespace IDE.ui { base.DrawAll(g); - if (mAwaitingLoad) + if (mAwaitingLoad || mEmitRemoved) { var rect = mSourceViewPanel.mEditWidget.GetRect(); mSourceViewPanel.mEditWidget.SelfToOtherTranslate(this, 0, 0, out rect.mX, out rect.mY); @@ -424,7 +433,9 @@ namespace IDE.ui { g.FillRect(rect.mX, rect.mY, rect.mWidth, rect.mHeight); } - IDEUtils.DrawWait(g, rect.mX + rect.mWidth / 2, rect.mY + rect.mHeight / 2, mUpdateCnt); + + if (mAwaitingLoad) + IDEUtils.DrawWait(g, rect.mX + rect.mWidth / 2, rect.mY + rect.mHeight / 2, mUpdateCnt); } } @@ -615,6 +626,7 @@ namespace IDE.ui public int32 mCollapseTextVersionId; public List mCollapseData = new .() ~ delete _; public List mEmitData = new .() ~ delete _; + public Dictionary mHasFailedEmitSet = new .() ~ delete _; public List mTypeNames = new .() ~ DeleteContainerAndItems!(_); public void Clear() @@ -625,7 +637,6 @@ namespace IDE.ui public void ClearCollapse() { - mCollapseData.Clear(); } @@ -633,6 +644,7 @@ namespace IDE.ui { mEmitData.Clear(); ClearAndDeleteItems(mTypeNames); + mHasFailedEmitSet.Clear(); } public ~this() @@ -4763,7 +4775,7 @@ namespace IDE.ui defer:: delete parser; var text = scope String(); mEditWidget.GetText(text); - parser.SetSource(text, mSourceViewPanel.mFilePath); + parser.SetSource(text, mSourceViewPanel.mFilePath, -1); parser.SetAutocomplete(textIdx); passInstance = bfSystem.CreatePassInstance(); parser.Parse(passInstance, !mSourceViewPanel.mIsBeefSource); @@ -5631,9 +5643,24 @@ namespace IDE.ui emitEmbed.mView.MinHeight, emitEmbed.mView.MaxAutoHeight); } + //float prevPhysHeight = emitEmbed.mView.mHeight; + float height = emitEmbed.mView.mWantHeight * emitEmbed.mOpenPct; emitEmbed.mView.SizeTo(GS!(0), (float)curY + lineHeight, mParent.mWidth, height); lineHeight += height; + + /*float physHeightChange = emitEmbed.mView.mHeight - prevPhysHeight; + if (physHeightChange != 0) + { + bool isCursorAfter = false; + if (mVirtualCursorPos != null) + isCursorAfter = mVirtualCursorPos.Value.mLine > line; + else + isCursorAfter = mCursorTextPos >= data.mLineStarts[line + 1]; + + if (isCursorAfter) + mEditWidget.VertScrollTo(mEditWidget.mVertPos.mDest + physHeightChange); + }*/ } } @@ -5706,9 +5733,14 @@ namespace IDE.ui if (data.mCollapseParseRevision != mCollapseParseRevision) { + //Debug.WriteLine($"GetTextData NewCollapseParseRevision:{data.mCollapseParseRevision} OldCollapseParseRevision:{mCollapseParseRevision}"); + mCollapseParseRevision = data.mCollapseParseRevision; mCollapseTextVersionId = data.mCollapseTextVersionId; - mCollapseTypeNames.ClearAndDeleteItems(); + List prevTypeNames = scope .()..AddRange(mCollapseTypeNames); + defer prevTypeNames.ClearAndDeleteItems(); + + mCollapseTypeNames.Clear(); for (var name in data.mTypeNames) mCollapseTypeNames.Add(new .(name)); @@ -5718,6 +5750,8 @@ namespace IDE.ui if (var emitEmbed = embed as SourceEditWidgetContent.EmitEmbed) { emitEmbedMap[emitEmbed.mAnchorId] = emitEmbed; + + //Debug.WriteLine($" mEmbed {embed} AnchorId:{emitEmbed.mAnchorId}"); } } @@ -5730,9 +5764,21 @@ namespace IDE.ui { if (line != emitEmbed.mLine) { - mEmbeds.Remove(emitEmbed.mLine); + //Debug.WriteLine($" Moving {emitEmbed} from {emitEmbed.mLine} to {line}"); + + mEmbeds.Remove(emitEmbed.mLine); emitEmbed.mLine = (.)line; - mEmbeds[(.)line] = emitEmbed; + + if (mEmbeds.TryAdd((.)line, var keyPtr, var valuePtr)) + { + *valuePtr = emitEmbed; + } + else + { + //Debug.WriteLine($" Occupied- deleting {emitEmbed}"); + delete emitEmbed; + emitEmbed = null; + } } } else if (mEmbeds.TryAdd((.)line, var keyPtr, var valuePtr)) @@ -5755,6 +5801,7 @@ namespace IDE.ui if (emitEmbed.mView != null) { + emitEmbed.mView.mEmitRemoved = false; Range range = .(emitData.mStartLine, emitData.mEndLine); var ew = emitEmbed.mView.mSourceViewPanel.mEditWidget; var ewc = ew.mEditWidgetContent as DarkEditWidgetContent; @@ -5774,9 +5821,24 @@ namespace IDE.ui for (var emitEmbed in emitEmbedMap.Values) { - mCollapseNeedsUpdate = true; - mEmbeds.Remove(emitEmbed.mLine); - delete emitEmbed; + //Debug.WriteLine($" Deleting(1) {emitEmbed}"); + + int32 typeNameIdx = -1; + if (emitEmbed.mView != null) + if (!data.mHasFailedEmitSet.TryGet(emitEmbed.mTypeName, ?, out typeNameIdx)) + typeNameIdx = -1; + + if (typeNameIdx != -1) + { + emitEmbed.mTypeName = mCollapseTypeNames[typeNameIdx]; + emitEmbed.mView.mEmitRemoved = true; + } + else + { + mCollapseNeedsUpdate = true; + mEmbeds.Remove(emitEmbed.mLine); + delete emitEmbed; + } } for (var collapseData in ref data.mCollapseData) @@ -5798,6 +5860,7 @@ namespace IDE.ui { if (mEmbeds.GetAndRemove(entry.mAnchorLine) case .Ok(let val)) { + //Debug.WriteLine($" Deleting(2) {val.value}"); delete val.value; } @entry.Remove(); @@ -5820,6 +5883,7 @@ namespace IDE.ui { if (mEmbeds.GetAndRemove(entry.mAnchorIdx) case .Ok(let val)) { + //Debug.WriteLine($" Removing {val.value}"); if (val.value is CollapseSummary) delete val.value; } @@ -5837,13 +5901,18 @@ namespace IDE.ui if (mEmbeds.TryAdd(entry.mAnchorLine, var keyPtr, var valuePtr)) { + //Debug.WriteLine($" Moving {val} to line {entry.mAnchorLine}"); + if (var collapseSummary = val as SourceEditWidgetContent.CollapseSummary) collapseSummary.mCollapseIndex = (.)@entry.Index; val.mLine = entry.mAnchorLine; *valuePtr = val; } else + { + //Debug.WriteLine($" Deleting(3) {val}"); delete val; + } } } @@ -6202,6 +6271,8 @@ namespace IDE.ui public void RefreshCollapseRegion(SourceEditWidgetContent.CollapseEntry* entry, int32 prevAnchorLine, bool failed) { + //Debug.WriteLine($"RefreshCollapseRegion PrevLine:{prevAnchorLine} NewLine:{entry.mAnchorLine}"); + if (failed) { if (mEmbeds.GetAndRemove(prevAnchorLine) case .Ok(let val)) @@ -6213,13 +6284,18 @@ namespace IDE.ui { if (mEmbeds.GetAndRemove(prevAnchorLine) case .Ok(let val)) { + //Debug.WriteLine($" Moving {val.value} from line {prevAnchorLine} to line {entry.mAnchorLine}"); + if (mEmbeds.TryAdd(entry.mAnchorLine, var keyPtr, var valuePtr)) { val.value.mLine = entry.mAnchorLine; *valuePtr = val.value; } else + { + //Debug.WriteLine($" Occupied- deleting {val}"); delete val.value; + } } } } @@ -6329,6 +6405,8 @@ namespace IDE.ui data.ClearCollapse(); } + //Debug.WriteLine($"ParseCollapseRegions {resolveType} CollapseRevision:{data.mCollapseParseRevision+1} TextVersion:{textVersion} IdSpan:{idSpan:D}"); + List typeNameIdxMap = scope .(); Dictionary typeNameMap = scope .(); Dictionary emitAnchorIds = scope .(); @@ -6399,12 +6477,21 @@ namespace IDE.ui emitData.mStartLine = int32.Parse(itr.GetNext().Value); emitData.mEndLine = int32.Parse(itr.GetNext().Value); emitData.mAnchorId = lookupCtx.GetIdAtIndex(emitData.mAnchorIdx); + //var foundTextVersion = int32.Parse(itr.GetNext().Value).Value; emitData.mOnlyInResolveAll = resolveType == .None; emitData.mIncludedInClassify = resolveType != .None; emitData.mIncludedInResolveAll = resolveType == .None; + if (emitData.mAnchorIdx == -1) + { + data.mHasFailedEmitSet[data.mTypeNames[emitData.mTypeNameIdx]] = emitData.mTypeNameIdx; + continue; + } + if (emitAnchorIds.TryGetValue(emitData.mAnchorId, var idx)) { + //Debug.WriteLine($" Found emit AnchorIdx:{emitData.mAnchorIdx} AnchorId:{emitData.mAnchorId} CurTextVersion:{textVersion} FoundTextVersion:{foundTextVersion}"); + var curEmitData = ref data.mEmitData[idx]; if (resolveType == .None) @@ -6420,6 +6507,7 @@ namespace IDE.ui continue; } + //Debug.WriteLine($" New emit AnchorIdx:{emitData.mAnchorIdx} AnchorId:{emitData.mAnchorId} CurTextVersion:{textVersion} FoundTextVersion:{foundTextVersion}"); data.mEmitData.Add(emitData); continue; } diff --git a/IDE/src/ui/SourceViewPanel.bf b/IDE/src/ui/SourceViewPanel.bf index c179b491..d8323d75 100644 --- a/IDE/src/ui/SourceViewPanel.bf +++ b/IDE/src/ui/SourceViewPanel.bf @@ -392,6 +392,17 @@ namespace IDE.ui SkipResult } + struct ParsedState + { + public IdSpan mIdSpan; + public int32 mTextVersion = -1; + + public void Dispose() mut + { + mIdSpan.Dispose(); + } + } + public bool mAsyncAutocomplete = true; public SourceEditWidget mEditWidget; @@ -426,6 +437,7 @@ namespace IDE.ui bool mWantsFullClassify; // This triggers a classify bool mWantsFullRefresh; // If mWantsFullClassify is set, mWantsFullRefresh makes the whole thing refresh bool mWantsCollapseRefresh; + ParsedState mParsedState ~ _.Dispose(); // The current data the resolver is using from this file bool mRefireMouseOverAfterRefresh; bool mWantsBackgroundAutocomplete; bool mSkipFastClassify; @@ -1463,14 +1475,18 @@ namespace IDE.ui defer delete resolvePassData; bfSystem.Lock(0); + var collapseData = bfCompiler.GetCollapseRegions(parser, resolvePassData, explicitEmitTypeNames, .. scope .()); + using (mMonitor.Enter()) { DeleteAndNullify!(mQueuedCollapseData); mQueuedCollapseData = new .(); mQueuedCollapseData.mData.Set(collapseData); mQueuedCollapseData.mTextVersion = textVersion; - mQueuedCollapseData.mCharIdSpan = charIdSpan; + mQueuedCollapseData.mCharIdSpan = charIdSpan.Duplicate(); + + //Debug.WriteLine($"DoRefreshCollapse finished TextVersion:{textVersion} IdSpan:{charIdSpan:D}"); } bfSystem.Unlock(); } @@ -1530,7 +1546,7 @@ namespace IDE.ui defer delete resolvePassData; var passInstance = bfSystem.CreatePassInstance("DoFastClassify"); defer delete passInstance; - parser.SetSource(text, mFilePath); + parser.SetSource(text, mFilePath, -1); parser.SetIsClassifying(); parser.Parse(passInstance, !mIsBeefSource); if (mIsBeefSource) @@ -1582,7 +1598,7 @@ namespace IDE.ui defer delete resolvePassData; var passInstance = bfSystem.CreatePassInstance("DoFastClassify"); defer delete passInstance; - parser.SetSource(text, mFilePath); + parser.SetSource(text, mFilePath, -1); parser.SetIsClassifying(); parser.Parse(passInstance, !mIsBeefSource); if (mIsBeefSource) @@ -1929,6 +1945,14 @@ namespace IDE.ui if ((resolveType == .Classify) || (resolveType == .ClassifyFullRefresh)) gApp.mErrorsPanel.SetNeedsResolveAll(); + if ((resolveType.IsClassify) && (!resolveParams.mCharIdSpan.IsEmpty)) + { + //Debug.WriteLine($"DoClassify {resolveType} TextVersion:{resolveParams.mTextVersion} IdSpan:{resolveParams.mCharIdSpan:D}"); + + mParsedState.mIdSpan.DuplicateFrom(ref resolveParams.mCharIdSpan); + mParsedState.mTextVersion = resolveParams.mTextVersion; + } + /*if (resolveType == .Autocomplete) { Thread.Sleep(250); @@ -2050,14 +2074,18 @@ namespace IDE.ui charData[i].mDisplayPassId = (int32)SourceDisplayId.Cleared; chars[i] = (char8)charData[i].mChar; } - + + int textVersion = -1; + if (resolveParams != null) + textVersion = resolveParams.mTextVersion; + if (!isBackground) { bfSystem.PerfZoneEnd(); bfSystem.PerfZoneStart("SetSource"); } parser.SetIsClassifying(); - parser.SetSource(.(chars, charLen), mFilePath); + parser.SetSource(.(chars, charLen), mFilePath, textVersion); if (!isBackground) { bfSystem.PerfZoneEnd(); @@ -5045,7 +5073,7 @@ namespace IDE.ui defer delete parser; var text = scope String(); mEditWidget.GetText(text); - parser.SetSource(text, mFilePath); + parser.SetSource(text, mFilePath, -1); var passInstance = bfSystem.CreatePassInstance(); defer delete passInstance; parser.Parse(passInstance, false); @@ -5252,7 +5280,7 @@ namespace IDE.ui var text = scope String(); mEditWidget.GetText(text); - parser.SetSource(text, mFilePath); + parser.SetSource(text, mFilePath, -1); parser.SetAutocomplete(textIdx); let passInstance = bfSystem.CreatePassInstance("Mouseover"); parser.SetCompleteParse(); @@ -5321,7 +5349,7 @@ namespace IDE.ui var text = scope String(); mEditWidget.GetText(text); - parser.SetSource(text, mFilePath); + parser.SetSource(text, mFilePath, -1); parser.SetAutocomplete(textIdx); passInstance = bfSystem.CreatePassInstance("Mouseover"); parser.SetCompleteParse(); @@ -5643,8 +5671,10 @@ namespace IDE.ui for (var bfError in mErrorList) { - if (bfError.mIsWhileSpecializing) + if ((bfError.mWhileSpecializing.HasFlag(.Type)) && (mEmbedKind == .None)) continue; + if ((bfError.mWhileSpecializing.HasFlag(.Method)) && (mEmbedKind != .Method)) + continue; if ((textIdx >= bfError.mSrcStart) && (textIdx < bfError.mSrcEnd)) { @@ -6515,9 +6545,16 @@ namespace IDE.ui break; var data = mEditWidget.mEditWidgetContent.mData; + if (mParsedState.mTextVersion == -1) + { + mParsedState.mIdSpan.DuplicateFrom(ref data.mTextIdData); + mParsedState.mTextVersion = data.mCurTextVersionId; + } + + //Debug.WriteLine($"Queueing DoRefreshCollapse TextVersion:{mParsedState.mTextVersion} IdSpan:{mParsedState.mIdSpan:D}"); compiler.DoBackground(new () => { - DoRefreshCollapse(bfParser, data.mCurTextVersionId, data.mTextIdData.Duplicate()); + DoRefreshCollapse(bfParser, mParsedState.mTextVersion, mParsedState.mIdSpan); }); } } @@ -6959,8 +6996,10 @@ namespace IDE.ui int srcStart = bfError.mSrcStart; int srcEnd = bfError.mSrcEnd; - if (bfError.mIsWhileSpecializing) - continue; + if ((bfError.mWhileSpecializing.HasFlag(.Type)) && (mEmbedKind == .None)) + continue; + if ((bfError.mWhileSpecializing.HasFlag(.Method)) && (mEmbedKind != .Method)) + continue; if ((bfError.mIsDeferred) && (hadNonDeferredErrors)) continue; diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 0a00f353..498a0e85 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -9919,7 +9919,7 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCo *valuePtr = foundTypeIds.mCount - 1; outString += "+"; - if (emitParser == NULL) + if ((emitParser == NULL) || (!emitParser->mIsEmitted)) { String typeName; outString += typeInst->mTypeDef->mProject->mName; @@ -9989,7 +9989,8 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCo int startLine = 0; int startLineChar = 0; - emitParser->GetLineCharAtIdx(kv.mValue.mSrcStart, startLine, startLineChar); + if (kv.mValue.mSrcStart >= 0) + emitParser->GetLineCharAtIdx(kv.mValue.mSrcStart, startLine, startLineChar); int srcEnd = kv.mValue.mSrcEnd - 1; while (srcEnd >= kv.mValue.mSrcStart) @@ -10006,8 +10007,9 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCo int endLine = 0; int endLineChar = 0; - emitParser->GetLineCharAtIdx(srcEnd, endLine, endLineChar); - outString += StrFormat("e%d,%d,%d,%d\n", embedId, charIdx, startLine, endLine + 1); + if (srcEnd >= 0) + emitParser->GetLineCharAtIdx(srcEnd, endLine, endLineChar); + outString += StrFormat("e%d,%d,%d,%d,%d\n", embedId, charIdx, startLine, endLine + 1, typeInst->mTypeDef->mTypeDeclaration->GetParser()->mTextVersion); } } @@ -10036,7 +10038,7 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCo if (embedId == -1) continue; - outString += StrFormat("e%d,%d,%d,%d\n", embedId, kv.mKey, 0, 0); + outString += StrFormat("e%d,%d,%d,%d,%d\n", embedId, kv.mKey, 0, 0, -1); } } }; diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 65f62737..9a773843 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -2955,7 +2955,7 @@ bool BfModule::IsSkippingExtraResolveChecks() return mCompiler->IsSkippingExtraResolveChecks(); } -bool BfModule::AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool& isWhileSpecializing, bool isWarning) +bool BfModule::AddErrorContext(StringImpl& errorString, BfAstNode* refNode, BfWhileSpecializingFlags& isWhileSpecializing, bool isWarning) { bool isWhileSpecializingMethod = false; if ((mIsSpecialModule) && (mModuleName == "vdata")) @@ -3011,19 +3011,20 @@ bool BfModule::AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool if (isSpecializedMethod) { errorString += StrFormat("\n while specializing method '%s'", MethodToString(methodInstance).c_str()); - isWhileSpecializing = true; + isWhileSpecializing = (BfWhileSpecializingFlags)(isWhileSpecializing | BfWhileSpecializingFlag_Method); isWhileSpecializingMethod = true; } else if ((methodInstance != NULL) && (methodInstance->mIsForeignMethodDef)) { errorString += StrFormat("\n while implementing default interface method '%s'", MethodToString(methodInstance).c_str()); - isWhileSpecializing = true; + isWhileSpecializing = (BfWhileSpecializingFlags)(isWhileSpecializing | BfWhileSpecializingFlag_Method); isWhileSpecializingMethod = true; } - else if ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType())) + + if ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType())) { errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str()); - isWhileSpecializing = true; + isWhileSpecializing = (BfWhileSpecializingFlags)(isWhileSpecializing | BfWhileSpecializingFlag_Type); } return true; @@ -3059,7 +3060,7 @@ bool BfModule::AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool if ((!isWhileSpecializing) && (mCurTypeInstance != NULL) && ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType()))) { errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str()); - isWhileSpecializing = true; + isWhileSpecializing = (BfWhileSpecializingFlags)(isWhileSpecializing | BfWhileSpecializingFlag_Type); } return true; @@ -3131,7 +3132,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers BfLogSysM("BfModule::Fail module %p type %p %s\n", this, mCurTypeInstance, error.c_str()); String errorString = error; - bool isWhileSpecializing = false; + BfWhileSpecializingFlags isWhileSpecializing = BfWhileSpecializingFlag_None; if (!AddErrorContext(errorString, refNode, isWhileSpecializing, false)) return NULL; @@ -3276,10 +3277,10 @@ BfError* BfModule::Warn(int warningNum, const StringImpl& warning, BfAstNode* re refNode = BfNodeToNonTemporary(refNode); String warningString = warning; - bool isWhileSpecializing = false; + BfWhileSpecializingFlags isWhileSpecializing = BfWhileSpecializingFlag_None; if (!AddErrorContext(warningString, refNode, isWhileSpecializing, true)) return NULL; - bool deferWarning = isWhileSpecializing; + bool deferWarning = isWhileSpecializing != BfWhileSpecializingFlag_None; if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL)) { diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 28c99eff..a2a1c9f0 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1558,7 +1558,7 @@ public: void SetFail(); void VerifyOnDemandMethods(); bool IsSkippingExtraResolveChecks(); - bool AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool& isWhileSpecializing, bool isWarning); + bool AddErrorContext(StringImpl& errorString, BfAstNode* refNode, BfWhileSpecializingFlags& isWhileSpecializing, bool isWarning); CeDbgState* GetCeDbgState(); BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false, bool deferError = false); BfError* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index f13a3290..a45d8430 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2507,7 +2507,7 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext == NULL)) typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext != NULL)) - typeInstance->mCeTypeInfo->mNext->mFailed = true; + typeInstance->mCeTypeInfo->mNext->mFastFinished = true; if (typeInstance->mCeTypeInfo != NULL) { BfCeTypeEmitEntry* entry = NULL; @@ -2528,6 +2528,8 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* entry.mEmitData = ceEmitContext->mEmitData; typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap[typeId] = entry; } + else if ((ceEmitContext->mFailed) && (typeInstance->mCeTypeInfo != NULL)) + typeInstance->mCeTypeInfo->mFailed = true; if ((ceEmitContext->HasEmissions()) && (!mCompiler->mFastFinish)) { @@ -2787,7 +2789,7 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext == NULL)) typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext != NULL)) - typeInstance->mCeTypeInfo->mNext->mFailed = true; + typeInstance->mCeTypeInfo->mNext->mFastFinished = true; if (typeInstance->mCeTypeInfo != NULL) { BfCeTypeEmitEntry* entry = NULL; @@ -2808,6 +2810,8 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* entry.mEmitData = ceEmitContext->mEmitData; typeInstance->mCeTypeInfo->mNext->mOnCompileMap[methodDef->mIdx] = entry; } + else if ((ceEmitContext->mFailed) && (typeInstance->mCeTypeInfo != NULL)) + typeInstance->mCeTypeInfo->mFailed = true; if (!ceEmitContext->mEmitData.IsEmpty()) { @@ -4798,6 +4802,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (typeInstance->mCeTypeInfo != NULL) { + bool prevHadEmissions = !typeInstance->mCeTypeInfo->mEmitSourceMap.IsEmpty(); + if (typeInstance->mCeTypeInfo->mNext != NULL) { BfLogSysM("Type %p injecting next ceTypeInfo %p into ceTypeInfo %p\n", typeInstance, typeInstance->mCeTypeInfo->mNext, typeInstance->mCeTypeInfo); @@ -4828,16 +4834,16 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy typeInstance->mCeTypeInfo->mNext->mHash = hashCtx.Finish128(); - if (!typeInstance->mCeTypeInfo->mNext->mFailed) + if (!typeInstance->mCeTypeInfo->mNext->mFastFinished) { if ((typeInstance->mCeTypeInfo->mHash != typeInstance->mCeTypeInfo->mNext->mHash) && (!typeInstance->mCeTypeInfo->mHash.IsZero())) mContext->QueueMidCompileRebuildDependentTypes(typeInstance, "comptime hash changed"); typeInstance->mCeTypeInfo->mEmitSourceMap = typeInstance->mCeTypeInfo->mNext->mEmitSourceMap; typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap; 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; typeInstance->mCeTypeInfo->mNext = NULL; } @@ -4851,6 +4857,15 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy typeInstance->mCeTypeInfo->mTypeIFaceMap.Clear(); typeInstance->mCeTypeInfo->mHash = Val128(); } + + if ((typeInstance->mCeTypeInfo->mFailed) && + (prevHadEmissions) && + (typeInstance->mCeTypeInfo->mEmitSourceMap.IsEmpty())) + { + // Just add a marker to retain the previous open emits + typeInstance->mCeTypeInfo->mEmitSourceMap[-1] = BfCeTypeEmitSource(); + } + typeInstance->mCeTypeInfo->mFailed = false; } if ((typeInstance->mCeTypeInfo != NULL) && (!typeInstance->mCeTypeInfo->mPendingInterfaces.IsEmpty())) diff --git a/IDEHelper/Compiler/BfParser.cpp b/IDEHelper/Compiler/BfParser.cpp index 5309f63e..eb16bb4b 100644 --- a/IDEHelper/Compiler/BfParser.cpp +++ b/IDEHelper/Compiler/BfParser.cpp @@ -345,6 +345,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem gParserCount++; + mTextVersion = -1; mEmbedKind = BfSourceEmbedKind_None; mUsingCache = false; mParserData = NULL; @@ -3850,9 +3851,10 @@ static BfAstNode* FindDebugExpressionNode(BfAstNode* checkNode, int cursorIdx) ////////////////////////////////////////////////////////////////////////// -BF_EXPORT void BF_CALLTYPE BfParser_SetSource(BfParser* bfParser, const char* data, int length, const char* fileName) +BF_EXPORT void BF_CALLTYPE BfParser_SetSource(BfParser* bfParser, const char* data, int length, const char* fileName, int textVersion) { bfParser->mFileName = fileName; + bfParser->mTextVersion = textVersion; bfParser->SetSource(data, length); } diff --git a/IDEHelper/Compiler/BfParser.h b/IDEHelper/Compiler/BfParser.h index ae1637e8..b146dfc7 100644 --- a/IDEHelper/Compiler/BfParser.h +++ b/IDEHelper/Compiler/BfParser.h @@ -160,6 +160,7 @@ public: BfPassInstance* mPassInstance; BfSourceClassifier* mSourceClassifier; String mFileName; + int mTextVersion; BfSourceEmbedKind mEmbedKind; bool mAwaitingDelete; diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index fd041a0d..35235b06 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -4102,7 +4102,7 @@ BF_EXPORT int BF_CALLTYPE BfPassInstance_GetErrorCount(BfPassInstance* bfPassIns return (int)bfPassInstance->mErrors.size(); } -BF_EXPORT const char* BF_CALLTYPE BfPassInstance_GetErrorData(BfPassInstance* bfPassInstance, int errorIdx, int& outCode, bool& outIsWarning, bool& outIsAfter, bool& outIsDeferred, bool& outIsWhileSpecializing, bool& outIsPersistent, +BF_EXPORT const char* BF_CALLTYPE BfPassInstance_GetErrorData(BfPassInstance* bfPassInstance, int errorIdx, int& outCode, bool& outIsWarning, bool& outIsAfter, bool& outIsDeferred, BfWhileSpecializingFlags& outIsWhileSpecializing, bool& outIsPersistent, char*& projectName, char*& fileName, int& outSrcStart, int& outSrcEnd, int* outLine, int* outColumn, int& outMoreInfoCount) { BfError* bfError = bfPassInstance->mErrors[errorIdx]; diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index d38d0932..d9c4ab7c 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -166,6 +166,13 @@ struct BfAtomCompositeEquals } }; +enum BfWhileSpecializingFlags : int8 +{ + BfWhileSpecializingFlag_None = 0, + BfWhileSpecializingFlag_Type = 1, + BfWhileSpecializingFlag_Method = 2 +}; + enum BfCompilerOptionFlags { BfCompilerOptionFlag_EmitDebugInfo = 1, @@ -1480,7 +1487,7 @@ class BfError : public BfErrorBase public: bool mIsAfter; bool mIsPersistent; - bool mIsWhileSpecializing; + BfWhileSpecializingFlags mIsWhileSpecializing; bool mIgnore; BfProject* mProject; String mError; @@ -1489,10 +1496,10 @@ public: public: BfError() - { + { mIsAfter = false; mIsPersistent = false; - mIsWhileSpecializing = false; + mIsWhileSpecializing = BfWhileSpecializingFlag_None; mIgnore = false; mProject = NULL; mWarningNumber = 0; diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index eb106bea..377e881e 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -1011,6 +1011,7 @@ public: Array mPendingInterfaces; Dictionary mRebuildMap; Val128 mHash; + bool mFastFinished; bool mFailed; bool mMayHaveUniqueEmitLocations; BfCeTypeInfo* mNext; @@ -1018,6 +1019,7 @@ public: public: BfCeTypeInfo() { + mFastFinished = false; mFailed = false; mMayHaveUniqueEmitLocations = false; mNext = NULL;