From 6ded6a37cce7a1631ddf465edab1a4c5cff5b5c8 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 2 Jul 2022 10:32:19 -0700 Subject: [PATCH] Improved emit marker resolve/build selection, emitted Go To Definition --- .../Beefy2D/src/theme/dark/DarkEditWidget.bf | 6 ++ IDE/src/IDEApp.bf | 84 +++++++++++++++---- IDE/src/ui/RenameSymbolDialog.bf | 7 +- IDE/src/ui/SourceEditWidgetContent.bf | 16 +++- IDE/src/ui/SourceViewPanel.bf | 60 +++++++++---- IDEHelper/Compiler/BfAutoComplete.cpp | 2 + IDEHelper/Compiler/BfContext.cpp | 42 +++++++++- IDEHelper/Compiler/BfExprEvaluator.cpp | 9 ++ IDEHelper/Compiler/BfModule.cpp | 9 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 4 +- IDEHelper/Compiler/BfResolvePass.h | 1 + IDEHelper/Compiler/BfSourceClassifier.cpp | 13 +++ IDEHelper/Compiler/BfSourceClassifier.h | 3 + IDEHelper/Compiler/BfSystem.cpp | 4 + 14 files changed, 216 insertions(+), 44 deletions(-) diff --git a/BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf b/BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf index 27794ea6..0e2dc3d8 100644 --- a/BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf +++ b/BeefLibs/Beefy2D/src/theme/dark/DarkEditWidget.bf @@ -458,6 +458,12 @@ namespace Beefy.theme.dark LineStartsChanged(); } + public override void ClearText() + { + mLineRange = null; + base.ClearText(); + } + public virtual float DrawText(Graphics g, String str, float x, float y, uint16 typeIdAndFlags) { using (g.PushColor(mTextColors[typeIdAndFlags & 0xFF])) diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 380fd0d1..945dc50e 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -1504,6 +1504,11 @@ namespace IDE useFileName = scope:: $"$Emit${useFileName.Substring("$Emit$Build$".Length)}"; compiler = mBfBuildCompiler; } + else if (useFileName.StartsWith("$Emit$Resolve$")) + { + useFileName = scope:: $"$Emit${useFileName.Substring("$Emit$Resolve$".Length)}"; + compiler = mBfResolveCompiler; + } if (!compiler.IsPerformingBackgroundOperation()) compiler.GetEmitSource(useFileName, outBuffer); @@ -7153,31 +7158,76 @@ namespace IDE return null; } - var itr = filePath.Split('$'); - itr.GetNext(); - itr.GetNext(); - var typeName = itr.GetNext().Value; - - mBfBuildCompiler.mBfSystem.Lock(0); - var embedFilePath = mBfBuildCompiler.GetEmitLocation(typeName, line, .. scope .(), var embedLine, var embedLineChar, var embedHash); - mBfBuildCompiler.mBfSystem.Unlock(); - + String embedFilePath; bool isViewValid = true; + StringView typeName; + int embedLine; + int embedLineChar; - if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve) + if (filePath.StartsWith("$Emit$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)) + if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve) { + var itr = filePath.Split('$'); + itr.GetNext(); + itr.GetNext(); + itr.GetNext(); + typeName = itr.GetNext().Value; + + mBfResolveCompiler.mBfSystem.Lock(0); + embedFilePath = mBfResolveCompiler.GetEmitLocation(typeName, line, .. scope:: .(), out embedLine, out embedLineChar, var embedHash); + mBfResolveCompiler.mBfSystem.Unlock(); + + useFilePath = scope:: $"$Emit${useFilePath.Substring("$Emit$Resolve$".Length)}"; + } + else isViewValid = false; - useFilePath = scope:: $"$Emit$Build${useFilePath.Substring("$Emit$".Length)}"; + } + else if (filePath.StartsWith("$Emit$Build$")) + { + if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build) + { + var itr = filePath.Split('$'); + itr.GetNext(); + itr.GetNext(); + itr.GetNext(); + typeName = itr.GetNext().Value; + + mBfBuildCompiler.mBfSystem.Lock(0); + embedFilePath = mBfBuildCompiler.GetEmitLocation(typeName, line, .. scope:: .(), out embedLine, out embedLineChar, var embedHash); + mBfBuildCompiler.mBfSystem.Unlock(); + + useFilePath = scope:: $"$Emit${useFilePath.Substring("$Emit$Build$".Length)}"; + } + else + isViewValid = false; + } + else + { + var itr = filePath.Split('$'); + itr.GetNext(); + itr.GetNext(); + typeName = itr.GetNext().Value; + + mBfBuildCompiler.mBfSystem.Lock(0); + embedFilePath = mBfBuildCompiler.GetEmitLocation(typeName, line, .. scope:: .(), out embedLine, out embedLineChar, var embedHash); + mBfBuildCompiler.mBfSystem.Unlock(); + + 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)) + if ((isViewValid) && (!embedFilePath.IsEmpty)) { var sourceViewPanel = ShowSourceFile(scope .(embedFilePath), null, showTemp ? SourceShowType.Temp : SourceShowType.ShowExisting).panel; if (sourceViewPanel == null) diff --git a/IDE/src/ui/RenameSymbolDialog.bf b/IDE/src/ui/RenameSymbolDialog.bf index 3ff90b37..ab19e118 100644 --- a/IDE/src/ui/RenameSymbolDialog.bf +++ b/IDE/src/ui/RenameSymbolDialog.bf @@ -244,7 +244,12 @@ namespace IDE.ui if (mKind == .GoToDefinition) { mSourceViewPanel.RecordHistoryLocation(); - var sourceViewPanel = gApp.ShowSourceFileLocation(scope .(filePath), -1, -1, line, lineChar, LocatorType.Smart, true); + + var usePath = scope String(filePath); + if (usePath.StartsWith("$Emit$")) + usePath.Insert("$Emit$".Length, "Resolve$"); + + var sourceViewPanel = gApp.ShowSourceFileLocation(usePath, -1, -1, line, lineChar, LocatorType.Smart, true); sourceViewPanel.RecordHistoryLocation(true); Close(); return; diff --git a/IDE/src/ui/SourceEditWidgetContent.bf b/IDE/src/ui/SourceEditWidgetContent.bf index a64f91ae..5bc1987d 100644 --- a/IDE/src/ui/SourceEditWidgetContent.bf +++ b/IDE/src/ui/SourceEditWidgetContent.bf @@ -1839,7 +1839,19 @@ namespace IDE.ui int line; int lineChar; GetCursorLineChar(out line, out lineChar); - return IDEApp.sApp.mHistoryManager.CreateHistory(mSourceViewPanel, mSourceViewPanel.mFilePath, line, lineChar, ignoreIfClose); + + String useFilePath = mSourceViewPanel.mFilePath; + if ((mSourceViewPanel.mFilePath.StartsWith("$Emit$")) && + (!mSourceViewPanel.mFilePath.StartsWith("$Emit$Build$")) && + (!mSourceViewPanel.mFilePath.StartsWith("$Emit$Resolve$"))) + { + if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve) + useFilePath = scope:: String("$Emit$Resolve$")..Append(mSourceViewPanel.mFilePath.Substring("$Emit$".Length)); + else + useFilePath = scope:: String("$Emit$Build$")..Append(mSourceViewPanel.mFilePath.Substring("$Emit$".Length)); + } + + return IDEApp.sApp.mHistoryManager.CreateHistory(mSourceViewPanel, useFilePath, line, lineChar, ignoreIfClose); } return null; } @@ -6505,7 +6517,7 @@ namespace IDE.ui var data = PreparedData; - if (resolveType != .None) + if ((resolveType != null) && (resolveType != .None)) { data.ClearCollapse(); } diff --git a/IDE/src/ui/SourceViewPanel.bf b/IDE/src/ui/SourceViewPanel.bf index 11d7f685..3ac3e577 100644 --- a/IDE/src/ui/SourceViewPanel.bf +++ b/IDE/src/ui/SourceViewPanel.bf @@ -1493,6 +1493,10 @@ namespace IDE.ui defer delete buildResolvePassData; buildCollapseData = gApp.mBfBuildCompiler.GetCollapseRegions(buildParser, buildResolvePassData, explicitEmitTypeNames, .. scope:: .()); } + else + { + buildCollapseData = ""; + } gApp.mBfBuildSystem.Unlock(); } @@ -2504,7 +2508,10 @@ namespace IDE.ui int32 prevLine = mEditWidget.Content.CursorLineAndColumn.mLine; mEditWidget.Content.mSelection = null; - mEditWidget.Content.CursorTextPos = cursorIdx; + + int wantCursorPos = Math.Min(mEditWidget.Content.mData.mTextLength - 1, cursorIdx); + if (wantCursorPos >= 0) + mEditWidget.Content.CursorTextPos = wantCursorPos; mEditWidget.Content.CursorMoved(); mEditWidget.Content.EnsureCursorVisible(true, true); mEditWidget.Content.mCursorImplicitlyMoved = true; @@ -6288,15 +6295,15 @@ namespace IDE.ui emitEmbedView.mGenericMethodCombo?.mEditWidget.SetFocus(); } - var sourceViewPanel = emitEmbedView.mSourceViewPanel; + var firstSourceViewPanel = emitEmbedView.mSourceViewPanel; - var embedEWC = sourceViewPanel.mEditWidget.mEditWidgetContent; + var firstEmbedEWC = firstSourceViewPanel.mEditWidget.mEditWidgetContent; - var prevCursorLineAndColumn = embedEWC.CursorLineAndColumn; + var prevCursorLineAndColumn = firstEmbedEWC.CursorLineAndColumn; - var editData = sourceViewPanel.mEditWidget.mEditWidgetContent.mData; + var editData = firstSourceViewPanel.mEditWidget.mEditWidgetContent.mData; if (editData.mTextLength == 0) - DeleteAndNullify!(sourceViewPanel.mTrackedTextElementViewList); + DeleteAndNullify!(firstSourceViewPanel.mTrackedTextElementViewList); delete editData.mText; editData.mText = embed.mCharData; @@ -6307,15 +6314,23 @@ namespace IDE.ui editData.mNextCharId = 0; editData.mTextIdData.Insert(0, editData.mTextLength, ref editData.mNextCharId); - sourceViewPanel.mEditWidget.mEditWidgetContent.ContentChanged(); - // We have a full classify now, FastClassify will just mess it up - sourceViewPanel.mSkipFastClassify = true; + firstSourceViewPanel.mEmitRevision = embed.mRevision; + firstSourceViewPanel.InjectErrors(resolveResult.mPassInstance, editData.mText, editData.mTextIdData, false, true); - if (prevCursorLineAndColumn.mLine >= embedEWC.GetLineCount()) - embedEWC.CursorLineAndColumn = .(embedEWC.GetLineCount() - 1, prevCursorLineAndColumn.mColumn); - - sourceViewPanel.mEmitRevision = embed.mRevision; - sourceViewPanel.InjectErrors(resolveResult.mPassInstance, editData.mText, editData.mTextIdData, false, true); + for (var user in editData.mUsers) + { + if (var embedEWC = user as SourceEditWidgetContent) + { + var sourceViewPanel = embedEWC.mSourceViewPanel; + + sourceViewPanel.mEditWidget.mEditWidgetContent.ContentChanged(); + // We have a full classify now, FastClassify will just mess it up + sourceViewPanel.mSkipFastClassify = true; + + if (prevCursorLineAndColumn.mLine >= firstEmbedEWC.GetLineCount()) + embedEWC.CursorLineAndColumn = .(firstEmbedEWC.GetLineCount() - 1, prevCursorLineAndColumn.mColumn); + } + } } } } @@ -6868,11 +6883,14 @@ namespace IDE.ui { if (mQueuedCollapseData.mBuildData != null) { + bool foundData = false; + using (gApp.mMonitor.Enter()) { var projectSourceCompileInstance = gApp.mWorkspace.GetProjectSourceCompileInstance(projectSource, gApp.mWorkspace.HotCompileIdx); if (projectSourceCompileInstance != null) { + foundData = true; ewc.ParseCollapseRegions(mQueuedCollapseData.mBuildData, mQueuedCollapseData.mTextVersion, ref projectSourceCompileInstance.mSourceCharIdData, null); HashSet dataLoaded = scope .(); @@ -6894,6 +6912,20 @@ namespace IDE.ui } } } + + if (!foundData) + { + for (var embed in ewc.mEmbeds.Values) + { + if (var emitEmbed = embed as SourceEditWidgetContent.EmitEmbed) + { + if (emitEmbed.mView != null) + { + emitEmbed.mView.mSourceViewPanel.mEditWidget.mEditWidgetContent.ClearText(); + } + } + } + } } } diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 13844a9f..e12e253f 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -3155,6 +3155,8 @@ bool BfAutoComplete::CheckFixit(BfAstNode* node) { if (mIgnoreFixits) return false; + if (mModule == NULL) + return false; if (mCompiler->mResolvePassData->mResolveType != BfResolveType_GetFixits) return false; if (!IsAutocompleteLineNode(node)) diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 76af668a..c2be9a8e 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -592,6 +592,8 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods) auto owner = methodInstance->mMethodInstanceGroup->mOwner; + auto autoComplete = mCompiler->GetAutoComplete(); + BF_ASSERT(!module->mAwaitingFinish); if ((resolveParser != NULL) && (methodInstance->mMethodDef->mDeclaringType != NULL) && (methodInstance->mMethodDef->mDeclaringType->GetDefinition()->mSource != resolveParser)) { @@ -599,6 +601,39 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods) if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mHasCursorIdx)) { auto parser = methodInstance->mMethodDef->mDeclaringType->GetLastSource()->ToParser(); + + if ((parser != NULL) && (autoComplete != NULL) && (autoComplete->mModule == NULL)) + { + bool emitHasCursor = false; + for (auto& checkEntry : mCompiler->mResolvePassData->mEmitEmbedEntries) + { + if (checkEntry.mValue.mCursorIdx >= 0) + emitHasCursor = true; + } + + if (emitHasCursor) + { + // Go To Definition in an emit mixin? + BfParser** foundParserPtr = NULL; + if (mCompiler->mResolvePassData->mCompatParserMap.TryAdd(parser, NULL, &foundParserPtr)) + { + *foundParserPtr = NULL; + for (auto checkParser : mCompiler->mResolvePassData->mParsers) + { + if ((checkParser->mFileName == parser->mFileName) && (checkParser->mOrigSrcLength == parser->mOrigSrcLength) && + (memcmp(checkParser->mSrc, parser->mSrc, checkParser->mOrigSrcLength) == 0)) + { + *foundParserPtr = checkParser; + } + } + } + + auto* compatParser = *foundParserPtr; + if (compatParser != NULL) + allow = true; + } + } + if ((parser != NULL) && (parser->mCursorIdx >= 0)) allow = true; } @@ -616,13 +651,12 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods) { if (!mCompiler->mIsResolveOnly) BF_ASSERT(!methodInstance->mIsReified || methodInstance->mDeclModule->mIsModuleMutable); - - auto autoComplete = mCompiler->GetAutoComplete(); + if ((autoComplete != NULL) && (autoComplete->mModule == NULL)) { - autoComplete->mModule = methodInstance->mDeclModule; + autoComplete->SetModule(methodInstance->mDeclModule); ProcessMethod(methodInstance); - autoComplete->mModule = NULL; + autoComplete->SetModule(NULL); } else ProcessMethod(methodInstance); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index ccb9aaad..636040d7 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -6232,6 +6232,15 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* ((autoComplete->mResolveType != BfResolveType_Autocomplete) && (autoComplete->mResolveType != BfResolveType_Autocomplete_HighPri) && (autoComplete->mResolveType != BfResolveType_GetResultString)); + + for (auto& entry : mModule->mCompiler->mResolvePassData->mEmitEmbedEntries) + { + if (entry.mValue.mCursorIdx >= 0) + { + // Needed for Go To Definition in Compiler.Mixin + wantQuickEval = false; + } + } } if (wantQuickEval) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 702f4345..b2c9eb71 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -11509,6 +11509,7 @@ void BfModule::ClearConstData() mStringCharPtrPool.Clear(); mStringPoolRefs.Clear(); mUnreifiedStringPoolRefs.Clear(); + mStaticFieldRefs.Clear(); } BfTypedValue BfModule::GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType) @@ -14860,11 +14861,11 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance) } } - if ((mIsScratchModule) && (mCompiler->mIsResolveOnly)) - { + if ((mIsScratchModule) && (mCompiler->mIsResolveOnly) && (!fieldInstance->mOwner->IsInstanceOf(mCompiler->mCompilerTypeDef))) + { // Just fake it for the extern and unspecialized modules - // We can't do this for compilation because unreified methods with default params need to get acutal global variable refs - return BfTypedValue(mBfIRBuilder->CreateConstNull(), fieldInstance->GetResolvedType(), true); + // We can't do this for compilation because unreified methods with default params need to get actual global variable refs + return BfTypedValue(mBfIRBuilder->CreateConstNull(), fieldInstance->GetResolvedType(), true); } BfIRValue* globalValuePtr = NULL; diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 80506bb1..b19c72e2 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2378,8 +2378,8 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn if (emitParser->mSourceClassifier != NULL) { emitParser->mSourceClassifier->VisitChild(emitParser->mRootNode); - emitParser->mSourceClassifier->VisitChild(emitParser->mSidechannelRootNode); - emitParser->mSourceClassifier->VisitChild(emitParser->mErrorRootNode); + emitParser->mSourceClassifier->DeferNodes(emitParser->mSidechannelRootNode); + emitParser->mSourceClassifier->DeferNodes(emitParser->mErrorRootNode); } if (typeInstance->mTypeDef->mEmitParent != NULL) diff --git a/IDEHelper/Compiler/BfResolvePass.h b/IDEHelper/Compiler/BfResolvePass.h index 66dc4639..be12ddd1 100644 --- a/IDEHelper/Compiler/BfResolvePass.h +++ b/IDEHelper/Compiler/BfResolvePass.h @@ -64,6 +64,7 @@ public: BfResolveType mResolveType; Array mParsers; + Dictionary mCompatParserMap; BfAutoComplete* mAutoComplete; Array mAutoCompleteTempTypes; // Contains multiple values when we have nested types Dictionary mStaticSearchMap; diff --git a/IDEHelper/Compiler/BfSourceClassifier.cpp b/IDEHelper/Compiler/BfSourceClassifier.cpp index 983c227d..c69033db 100644 --- a/IDEHelper/Compiler/BfSourceClassifier.cpp +++ b/IDEHelper/Compiler/BfSourceClassifier.cpp @@ -694,6 +694,19 @@ void BfSourceClassifier::MarkSkipped(BfAstNode* node) MarkSkipped(node->GetSrcStart(), node->GetSrcEnd()); } +void BfSourceClassifier::DeferNodes(BfBlock* block) +{ + for (auto child : *block) + mDeferredNodes.Add(child); +} + +void BfSourceClassifier::FlushDeferredNodes() +{ + for (auto node : mDeferredNodes) + VisitChild(node); + mDeferredNodes.Clear(); +} + void BfSourceClassifier::Visit(BfTypeAliasDeclaration* typeDeclaration) { if (typeDeclaration->mIgnoreDeclaration) diff --git a/IDEHelper/Compiler/BfSourceClassifier.h b/IDEHelper/Compiler/BfSourceClassifier.h index fc15edd0..3a956ffd 100644 --- a/IDEHelper/Compiler/BfSourceClassifier.h +++ b/IDEHelper/Compiler/BfSourceClassifier.h @@ -70,6 +70,7 @@ public: BfAstNode* mPrevNode; BfAstNode* mCurMember; BfLocalMethodDeclaration* mCurLocalMethodDeclaration; + Array mDeferredNodes; public: void HandleLeafNode(BfAstNode* node); @@ -86,6 +87,8 @@ public: void Handle(BfTypeDeclaration* typeDeclaration); void MarkSkipped(int startPos, int endPos); void MarkSkipped(BfAstNode* node); + void DeferNodes(BfBlock* block); + void FlushDeferredNodes(); public: BfSourceClassifier(BfParser* bfParser, CharData* charData); diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index 28bd3b48..bc0b88c1 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -4075,6 +4075,10 @@ BF_EXPORT void* BfResolvePassData_GetEmitEmbedData(BfResolvePassData* resolvePas return NULL; *revision = emitEmbedEntry->mRevision; *charCount = emitEmbedEntry->mParser->mSrcLength; + + auto emitParser = emitEmbedEntry->mParser; + emitParser->mSourceClassifier->FlushDeferredNodes(); + return emitEmbedEntry->mParser->mSourceClassifier->mCharData; }