diff --git a/IDE/src/Commands.bf b/IDE/src/Commands.bf index 55dc7c77..b72d37c8 100644 --- a/IDE/src/Commands.bf +++ b/IDE/src/Commands.bf @@ -215,7 +215,6 @@ namespace IDE Add("New File", new => gApp.Cmd_NewFile); Add("New Project", new => gApp.Cmd_NewProject); Add("New Workspace", new => gApp.Cmd_NewWorkspace); - Add("New View Into File", new => gApp.Cmd_NewFileView); Add("Next Document Panel", new => gApp.[Friend]DoShowNextDocumentPanel); Add("Open Corresponding", new => gApp.[Friend]OpenCorresponding); Add("Open Crash Dump", new => gApp.OpenCrashDump); @@ -264,7 +263,6 @@ namespace IDE Add("Show Threads", new => gApp.ShowThreads); Add("Show Watches", new => gApp.ShowWatches); Add("Show Workspace Explorer", new => gApp.ShowWorkspacePanel); - Add("Split View", new => gApp.[Friend]SplitView); Add("Start Debugging", new => gApp.[Friend]RunWithCompiling); Add("Start Without Debugging", new => gApp.[Friend]RunWithoutCompiling); Add("Step Into", new => gApp.[Friend]StepInto); @@ -275,6 +273,8 @@ namespace IDE Add("Tab Last", new => gApp.[Friend]TabLast); Add("Tab Next", new => gApp.[Friend]TabNext); Add("Tab Prev", new => gApp.[Friend]TabPrev); + Add("View New", new => gApp.Cmd_ViewNew); + Add("View Split", new => gApp.[Friend]ViewSplit); Add("View White Space", new => gApp.Cmd_ViewWhiteSpace); Add("Zoom In", new => gApp.Cmd_ZoomIn); Add("Zoom Out", new => gApp.Cmd_ZoomOut); diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 472f44e5..c7b76799 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -751,7 +751,7 @@ namespace IDE base.Run(); } - public void Cmd_NewFileView() + public void Cmd_ViewNew() { var sourceViewPanel = GetActiveSourceViewPanel(); if (sourceViewPanel != null) @@ -4824,7 +4824,6 @@ namespace IDE AddMenuItem(subMenu, "&Save File","Save File"); AddMenuItem(subMenu, "Save &As...", "Save As"); AddMenuItem(subMenu, "Save A&ll", "Save All"); - AddMenuItem(subMenu, "N&ew View into File", "New View Into File"); let prefMenu = subMenu.AddMenuItem("&Preferences"); //prefMenu.AddMenuItem("&Keyboard Shortcuts", null, new (evt) => { ShowKeyboardShortcuts(); }); AddMenuItem(prefMenu, "&Settings", "Settings"); @@ -5028,7 +5027,8 @@ namespace IDE mWindowMenu = root.AddMenuItem("&Window"); AddMenuItem(mWindowMenu, "&Close", "Close Window"); AddMenuItem(mWindowMenu, "&Close All", "Close All Windows"); - AddMenuItem(mWindowMenu, "&Split View", "Split View"); + AddMenuItem(mWindowMenu, "&New View into File", "View New"); + AddMenuItem(mWindowMenu, "&Split View", "View Split"); subMenu = root.AddMenuItem("&Help"); AddMenuItem(subMenu, "&About", "About"); @@ -6155,7 +6155,7 @@ namespace IDE DocumentCloseClicked(docPanel); } - void SplitView() + void ViewSplit() { var sourceViewPanel = GetActiveSourceViewPanel(); if (sourceViewPanel != null) diff --git a/IDE/src/ui/AutoComplete.bf b/IDE/src/ui/AutoComplete.bf index a41d7d59..39697851 100644 --- a/IDE/src/ui/AutoComplete.bf +++ b/IDE/src/ui/AutoComplete.bf @@ -2126,35 +2126,47 @@ namespace IDE.ui return mInsertStartIdx == mInsertEndIdx; } - /*void ApplyFixit(String fixitType, String fileName, String fixitParam) - { - var projectSource = IDEApp.sApp.FindProjectSourceItem(fileName); - - var editData = IDEApp.sApp.GetEditData(projectSource); - var sourceEditWidgetContent = (SourceEditWidgetContent)editData.mEditWidget.Content; - //cursorPositions.Add(sourceEditWidgetContent.CursorTextPos); - - var bfSystem = IDEApp.sApp.mBfResolveSystem; - var parser = bfSystem.CreateEmptyParser(null); - defer:: delete parser; - var text = scope String(); - editData.mEditWidget.GetText(text); - parser.SetSource(text, fileName); - var passInstance = bfSystem.CreatePassInstance(); - defer:: delete passInstance; - parser.Parse(passInstance, false); - parser.Reduce(passInstance); - - parser.Ref - }*/ - void ApplyFixit(String data) { - var parts = String.StackSplit!(data, '|'); - //String fixitType = parts[0]; - String fixitFileName = parts[1]; - int32 fixitIdx = int32.Parse(parts[2]).GetValueOrDefault(); + UndoBatchStart undoBatchStart = null; + var parts = String.StackSplit!(data, '|'); + String fixitFileName = parts[1]; + SourceViewPanel sourceViewPanel = IDEApp.sApp.ShowSourceFile(fixitFileName); + + var targetSourceEditWidgetContent = mTargetEditWidget.Content as SourceEditWidgetContent; + var historyEntry = targetSourceEditWidgetContent.RecordHistoryLocation(); + historyEntry.mNoMerge = true; + + var sourceEditWidgetContent = targetSourceEditWidgetContent; + if (sourceEditWidgetContent.mSourceViewPanel != sourceViewPanel) + { + sourceEditWidgetContent = (SourceEditWidgetContent)sourceViewPanel.GetActivePanel().EditWidget.mEditWidgetContent; + undoBatchStart = new UndoBatchStart("autocomplete"); + sourceEditWidgetContent.mData.mUndoManager.Add(undoBatchStart); + } + + int32 fixitIdx = 0; + int32 fixitLen = 0; + StringView fixitLocStr = parts[2]; + int dashPos = fixitLocStr.IndexOf('-'); + if (dashPos != -1) + { + fixitLen = int32.Parse(fixitLocStr.Substring(dashPos + 1)); + fixitLocStr.RemoveToEnd(dashPos); + } + + if (fixitLocStr.Contains(':')) + { + var splitItr = fixitLocStr.Split(':'); + int32 line = int32.Parse(splitItr.GetNext().Value).Value; + int32 col = int32.Parse(splitItr.GetNext().Value).Value; + fixitIdx = (.)sourceEditWidgetContent.GetTextIdx(line, col); + } + else + fixitIdx = int32.Parse(fixitLocStr).GetValueOrDefault(); + + int insertCount = 0; int dataIdx = 3; while (dataIdx < parts.Count) @@ -2178,7 +2190,6 @@ namespace IDE.ui #unwarn bool hasMore = dataIdx < parts.Count; - SourceViewPanel sourceViewPanel = IDEApp.sApp.ShowSourceFile(fixitFileName); if (sourceViewPanel != null) { if (sourceViewPanel.IsReadOnly) @@ -2186,50 +2197,48 @@ namespace IDE.ui gApp.Fail(scope String()..AppendF("The selected fixit cannot be applied to locked file '{}'", sourceViewPanel.mFilePath)); return; } - - var targetSourceEditWidgetContent = mTargetEditWidget.Content as SourceEditWidgetContent; - var history = targetSourceEditWidgetContent.RecordHistoryLocation(); - history.mNoMerge = true; - var editWidgetContent = (SourceEditWidgetContent)sourceViewPanel.mEditWidget.mEditWidgetContent; - editWidgetContent.CursorTextPos = fixitIdx; - editWidgetContent.EnsureCursorVisible(true, true); + sourceEditWidgetContent.CursorTextPos = fixitIdx; + sourceEditWidgetContent.EnsureCursorVisible(true, true); + + if (fixitLen > 0) + { + sourceEditWidgetContent.mSelection = EditSelection(fixitIdx, fixitIdx + fixitLen); + sourceEditWidgetContent.DeleteSelection(); + fixitLen = 0; + } if (fixitInsert.StartsWith('\n')) - editWidgetContent.PasteText(fixitInsert, fixitInsert.StartsWith("\n")); + sourceEditWidgetContent.PasteText(fixitInsert, fixitInsert.StartsWith("\n")); else - InsertImplText(fixitInsert); + InsertImplText(sourceEditWidgetContent, fixitInsert); - fixitIdx = (.)editWidgetContent.CursorTextPos; + fixitIdx = (.)sourceEditWidgetContent.CursorTextPos; + insertCount++; } } - /*switch (parts[0]) + if (historyEntry != null) { - case "using": - //ApplyFixit(parts[0], parts[1], parts[2]); - - break; - case "addMethod": - break; - }*/ + // Make sure when we go back that we'll go back to the insert position + int idx = gApp.mHistoryManager.mHistoryList.LastIndexOf(historyEntry); + if (idx != -1) + gApp.mHistoryManager.mHistoryIdx = (.)idx; + } + + if (undoBatchStart != null) + sourceEditWidgetContent.mData.mUndoManager.Add(undoBatchStart.mBatchEnd); } - void InsertImplText(String implText) + void InsertImplText(SourceEditWidgetContent sourceEditWidgetContent, String implText) { - - var sourceEditWidgetContent = mTargetEditWidget.Content as SourceEditWidgetContent; - /*sourceEditWidgetContent.ClearLine(); - sourceEditWidgetContent.InsertAtCursor("ABC\nDEF\nGHI"); - return;*/ - String implSect = scope .(); int startIdx = 0; for (int i < implText.Length) { char8 c = implText[i]; - if ((c == '\t') || (c == '\b') || (c == '\r') || (c == '\f')) + if ((c == '\a') || (c == '\t') || (c == '\b') || (c == '\r') || (c == '\f')) { implSect.Clear(); implSect.Append(implText, startIdx, i - startIdx); @@ -2238,7 +2247,30 @@ namespace IDE.ui sourceEditWidgetContent.InsertAtCursor(implSect); } - if (c == '\f') + if (c == '\a') // Ensure we have spacing or an open brace on the previous line + { + int lineNum = sourceEditWidgetContent.CursorLineAndColumn.mLine; + if (lineNum > 0) + { + sourceEditWidgetContent.GetLinePosition(lineNum - 1, var lineStart, var lineEnd); + for (int idx = lineEnd; idx >= lineStart; idx--) + { + let charData = sourceEditWidgetContent.mData.mText[idx]; + if (charData.mDisplayTypeId == (.)SourceElementType.Comment) + continue; + if (charData.mChar.IsWhiteSpace) + continue; + if (charData.mChar == '{') + break; + + // Add new line + sourceEditWidgetContent.InsertAtCursor("\n"); + sourceEditWidgetContent.CursorToLineEnd(); + break; + } + } + } + else if (c == '\f') // Make sure we're on an empty line { if (!sourceEditWidgetContent.IsLineWhiteSpace(sourceEditWidgetContent.CursorLineAndColumn.mLine)) { @@ -2251,29 +2283,19 @@ namespace IDE.ui sourceEditWidgetContent.CursorTextPos = prevPos; } sourceEditWidgetContent.CursorToLineEnd(); - /*if (!sourceEditWidgetContent.IsLineWhiteSpace(sourceEditWidgetContent.CursorLineAndColumn.mLine)) - { - sourceEditWidgetContent.InsertText(sourceEditWidgetContent.CursorTextPos + 1, "\n"); - sourceEditWidgetContent.ContentChanged(); - }*/ - //return; - - //sourceEditWidgetContent.GetLineText(sourceEditWidgetContent.CursorLineAndColumn.mLine, ) - - //sourceEditWidgetContent.InsertAtCursor("ABC\n"); } - else if (c == '\t') + else if (c == '\t') // Open block { sourceEditWidgetContent.InsertAtCursor("\n"); sourceEditWidgetContent.CursorToLineEnd(); sourceEditWidgetContent.OpenCodeBlock(); } - else if (c == '\r') + else if (c == '\r') // Newline { sourceEditWidgetContent.InsertAtCursor("\n"); sourceEditWidgetContent.CursorToLineEnd(); } - else if (c == '\b') + else if (c == '\b') // Close block { int cursorPos = sourceEditWidgetContent.CursorTextPos; while (cursorPos < sourceEditWidgetContent.mData.mTextLength) @@ -2406,7 +2428,7 @@ namespace IDE.ui UpdateAsyncInfo();*/ if (implText != null) - InsertImplText(implText); + InsertImplText(sourceEditWidgetContent, implText); if (persistentInvokeSrcPositons != null) { diff --git a/IDE/src/ui/SourceEditWidgetContent.bf b/IDE/src/ui/SourceEditWidgetContent.bf index 4655a905..40d9f6ec 100644 --- a/IDE/src/ui/SourceEditWidgetContent.bf +++ b/IDE/src/ui/SourceEditWidgetContent.bf @@ -1489,7 +1489,7 @@ namespace IDE.ui base.InsertAtCursor(theString, insertFlags); mInsertDisplayFlags = 0; - if ((!mIgnoreSetHistory) && (!insertFlags.HasFlag(.NoMoveCursor))) + if ((!mIgnoreSetHistory) && (!insertFlags.HasFlag(.NoMoveCursor)) && (!insertFlags.HasFlag(.NoRecordHistory))) RecordHistoryLocation(); } diff --git a/IDE/src/ui/StatusBar.bf b/IDE/src/ui/StatusBar.bf index 38937dbe..97936dbf 100644 --- a/IDE/src/ui/StatusBar.bf +++ b/IDE/src/ui/StatusBar.bf @@ -236,22 +236,12 @@ namespace IDE.ui if (activeDocument is SourceViewPanel) { var sourceViewPanel = (SourceViewPanel)activeDocument; + sourceViewPanel = sourceViewPanel.GetActivePanel(); + int32 line; int32 column; sourceViewPanel.GetCursorPosition(out line, out column); - /*var ewc = sourceViewPanel.mEditWidget.Content; - int cursorPos = ewc.CursorTextPos; - if (cursorPos < ewc.mData.mTextLength) - { - ewc.mData.mTextIdData.Prepare(); - g.DrawString(StackStringFormat!("Id {0}", ewc.mData.mTextIdData.GetIdAtIndex(cursorPos)), mWidth - GS!(310), 0); - }*/ - - - /*line = 8'888'888; - column = 8'888'888;*/ - if (gApp.mSettings.mEnableDevMode) g.DrawString(StackStringFormat!("Idx {0}", sourceViewPanel.mEditWidget.Content.CursorTextPos), mWidth - GS!(240), 0); g.DrawString(StackStringFormat!("Ln {0}", line + 1), mWidth - GS!(150), 0); diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index bd7e0779..f9c27ebe 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -1906,7 +1906,7 @@ void BfAutoComplete::CheckNode(BfAstNode* node) } } -bool BfAutoComplete::GetMethodInfo(BfMethodInstance* methodInst, StringImpl* showString, StringImpl* insertString, bool isExplicitInterface) +bool BfAutoComplete::GetMethodInfo(BfMethodInstance* methodInst, StringImpl* showString, StringImpl* insertString, bool isImplementing, bool isExplicitInterface) { auto methodDef = methodInst->mMethodDef; bool isInterface = methodInst->GetOwner()->IsInterface(); @@ -1917,24 +1917,21 @@ bool BfAutoComplete::GetMethodInfo(BfMethodInstance* methodInst, StringImpl* sho StringT<128> methodName; StringT<256> impString; - bool isAbstract = (methodDef->mIsAbstract) && (!isInterface); + bool isAbstract = methodDef->mIsAbstract || isInterface;// (methodDef->mIsAbstract) && (!isInterface); - if (!isAbstract) + if (isAbstract) { - if (isInterface) - { - if (!methodInst->mReturnType->IsVoid()) - impString += "return default;"; - } - else - { - if (!methodInst->mReturnType->IsVoid()) - impString = "return "; + if (!methodInst->mReturnType->IsVoid()) + impString += "return default;"; + } + else if (!isAbstract) + { + if (!methodInst->mReturnType->IsVoid()) + impString = "return "; - impString += "base."; - impString += methodDef->mName; - impString += "("; - } + impString += "base."; + impString += methodDef->mName; + impString += "("; } auto methodDeclaration = methodDef->GetMethodDeclaration(); @@ -1963,19 +1960,19 @@ bool BfAutoComplete::GetMethodInfo(BfMethodInstance* methodInst, StringImpl* sho if (paramIdx > 0) { methodName += ", "; - if ((!isAbstract) && (!isInterface)) + if (!isAbstract) impString += ", "; } methodName += mModule->TypeToString(methodInst->GetParamType(paramIdx), BfTypeNameFlag_ReduceName); methodName += " "; methodName += methodDef->mParams[paramIdx]->mName; - if ((!isAbstract) && (!isInterface)) + if (!isAbstract) impString += methodDef->mParams[paramIdx]->mName; } methodName += ")"; - if ((!isAbstract) && (!isInterface)) + if (!isAbstract) impString += ");"; if (showString != NULL) @@ -2115,7 +2112,7 @@ void BfAutoComplete::AddOverrides(const StringImpl& filter) continue; StringT<512> insertString; - GetMethodInfo(methodInst, &insertString, &insertString, false); + GetMethodInfo(methodInst, &insertString, &insertString, true, false); if (insertString.IsEmpty()) continue; AddEntry(AutoCompleteEntry("override", insertString, NULL), filter); @@ -2475,7 +2472,37 @@ bool BfAutoComplete::CheckFixit(BfAstNode* node) return true; } -void BfAutoComplete::ChcekInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode* node) +int BfAutoComplete::FixitGetMemberInsertPos(BfTypeDef* typeDef) +{ + BfTypeDeclaration* typeDecl = typeDef->mTypeDeclaration; + BfTokenNode* openNode = NULL; + BfTokenNode* closeNode = NULL; + if (auto blockNode = BfNodeDynCast(typeDecl->mDefineNode)) + { + openNode = blockNode->mOpenBrace; + closeNode = blockNode->mCloseBrace; + } + + int insertPos = -1; + BfParserData* parser = typeDef->mTypeDeclaration->GetSourceData()->ToParserData(); + if ((parser != NULL) && (closeNode != NULL)) + { + int startPos = openNode->mSrcStart + 1; + insertPos = closeNode->mSrcStart; + while (insertPos > startPos) + { + char prevC = parser->mSrc[insertPos - 1]; + if (prevC == '\n') + break; + insertPos--; + } + if (insertPos > startPos) + insertPos--; + } + return insertPos; +} + +void BfAutoComplete::CheckInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode* node) { if (!CheckFixit(node)) return; @@ -2529,30 +2556,11 @@ void BfAutoComplete::ChcekInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode } if (!missingMethods.IsEmpty()) - { - BfTypeDeclaration* typeDecl = declTypeDef->mTypeDeclaration; - BfTokenNode* openNode = NULL; - BfTokenNode* closeNode = NULL; - if (auto blockNode = BfNodeDynCast(typeDecl->mDefineNode)) - { - openNode = blockNode->mOpenBrace; - closeNode = blockNode->mCloseBrace; - } - + { BfParserData* parser = declTypeDef->mTypeDeclaration->GetSourceData()->ToParserData(); - if ((parser != NULL) && (closeNode != NULL)) - { - int startPos = openNode->mSrcStart + 1; - int insertPos = closeNode->mSrcStart; - while (insertPos > startPos) - { - char prevC = parser->mSrc[insertPos - 1]; - if (prevC == '\n') - break; - insertPos--; - } - if (insertPos > startPos) - insertPos--; + if (parser != NULL) + { + int insertPos = FixitGetMemberInsertPos(declTypeDef); bool wantsBreak = false; String insertStr = "\f"; @@ -2563,7 +2571,7 @@ void BfAutoComplete::ChcekInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode insertStr += "\r\r"; wantsBreak = false; } - if (GetMethodInfo(methodInst, NULL, &insertStr, false)) + if (GetMethodInfo(methodInst, NULL, &insertStr, true, false)) { insertStr += "\b"; wantsBreak = true; @@ -2579,20 +2587,87 @@ void BfAutoComplete::ChcekInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode explicitInsertStr += "\r\r"; wantsBreak = false; } - if (GetMethodInfo(methodInst, NULL, &explicitInsertStr, true)) + if (GetMethodInfo(methodInst, NULL, &explicitInsertStr, true, true)) { explicitInsertStr += "\b"; wantsBreak = true; } } - - mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Implement interface '%s'\tusing|%s|%d|%s", - mModule->TypeToString(ifaceInst).c_str(), parser->mFileName.c_str(), insertPos, insertStr.c_str()).c_str())); - mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Implement interface '%s' explicitly\tusing|%s|%d|%s", - mModule->TypeToString(ifaceInst).c_str(), parser->mFileName.c_str(), insertPos, explicitInsertStr.c_str()).c_str())); + if (insertPos != -1) + { + mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Implement interface '%s'\tusing|%s|%s", + mModule->TypeToString(ifaceInst).c_str(), FixitGetLocation(parser, insertPos).c_str(), insertStr.c_str()).c_str())); + mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Implement interface '%s' explicitly\tusing|%s|%s", + mModule->TypeToString(ifaceInst).c_str(), FixitGetLocation(parser, insertPos).c_str(), explicitInsertStr.c_str()).c_str())); + } } - } + } + } + + if ((!typeInstance->IsInterface()) && (!typeInstance->IsUnspecializedTypeVariation()) && (!typeInstance->IsBoxed())) + { + if (!typeInstance->mTypeDef->mIsAbstract) + { + Array missingMethods; + + for (int methodIdx = 0; methodIdx < (int)typeInstance->mVirtualMethodTable.size(); methodIdx++) + { + auto& methodRef = typeInstance->mVirtualMethodTable[methodIdx].mImplementingMethod; + if (methodRef.mMethodNum == -1) + { + BF_ASSERT(mCompiler->mOptions.mHasVDataExtender); + if (methodRef.mTypeInstance == typeInstance) + { + if (typeInstance->GetImplBaseType() != NULL) + BF_ASSERT(methodIdx == (int)typeInstance->GetImplBaseType()->mVirtualMethodTableSize); + } + continue; + } + auto methodInstance = (BfMethodInstance*)methodRef; + if ((methodInstance != NULL) && (methodInstance->mMethodDef->mIsAbstract)) + { + if (methodInstance->mMethodDef->mIsAbstract) + { + if (!typeInstance->IsUnspecializedTypeVariation()) + missingMethods.Add(methodInstance); + } + } + } + + if (!missingMethods.IsEmpty()) + { + auto declTypeDef = typeInstance->mTypeDef; + BfParserData* parser = declTypeDef->mTypeDeclaration->GetSourceData()->ToParserData(); + if (parser != NULL) + { + int insertPos = FixitGetMemberInsertPos(declTypeDef); + + bool wantsBreak = false; + String insertStr = "\f"; + for (auto methodInst : missingMethods) + { + if (wantsBreak) + { + insertStr += "\r\r"; + wantsBreak = false; + } + + if (GetMethodInfo(methodInst, NULL, &insertStr, true, false)) + { + insertStr += "\b"; + wantsBreak = true; + } + } + + if (insertPos != -1) + { + mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Implement abstract methods\tmethod|%s|%s", + FixitGetLocation(parser, insertPos).c_str(), insertStr.c_str()).c_str())); + } + } + } + } } } @@ -2644,7 +2719,8 @@ void BfAutoComplete::FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, } } - AddEntry(AutoCompleteEntry("fixit", StrFormat("Create field '%s' in '%s'\taddField|%s|%d||%s", fieldName.c_str(), fullName.c_str(), parser->mFileName.c_str(), fileLoc, fieldStr.c_str()).c_str())); + AddEntry(AutoCompleteEntry("fixit", StrFormat("Create field '%s' in '%s'\taddField|%s||%s", fieldName.c_str(), fullName.c_str(), + FixitGetLocation(parser->mParserData, fileLoc).c_str(), fieldStr.c_str()).c_str())); } void BfAutoComplete::FixitAddCase(BfTypeInstance* typeInst, const StringImpl& caseName, const BfTypeVector& fieldTypes) @@ -2728,7 +2804,8 @@ void BfAutoComplete::FixitAddCase(BfTypeInstance* typeInst, const StringImpl& ca fieldStr += ";"; } - AddEntry(AutoCompleteEntry("fixit", StrFormat("Create case '%s' in '%s'\taddField|%s|%d|%s", caseName.c_str(), fullName.c_str(), parser->mFileName.c_str(), fileLoc, fieldStr.c_str()).c_str())); + AddEntry(AutoCompleteEntry("fixit", StrFormat("Create case '%s' in '%s'\taddField|%s|%s", caseName.c_str(), fullName.c_str(), + FixitGetLocation(parser->mParserData, fileLoc).c_str(), fieldStr.c_str()).c_str())); } void BfAutoComplete::FixitGetParamString(const BfTypeVector& paramTypes, StringImpl& outStr) @@ -2772,7 +2849,16 @@ void BfAutoComplete::FixitGetParamString(const BfTypeVector& paramTypes, StringI if (isOut) checkName = "out" + checkName; else if (isupper(checkName[0])) + { checkName[0] = tolower(checkName[0]); + for (int i = 1; i < (int)checkName.length(); i++) + { + if ((i + 1 < (int)checkName.length()) && + (islower(checkName[i + 1]))) + break; + checkName[i] = tolower(checkName[i]); + } + } if (isArr) checkName += "Arr"; break; @@ -2803,6 +2889,14 @@ void BfAutoComplete::FixitGetParamString(const BfTypeVector& paramTypes, StringI } } +String BfAutoComplete::FixitGetLocation(BfParserData* parser, int insertPos) +{ + int line = 0; + int lineChar = 0; + parser->GetLineCharAtIdx(insertPos, line, lineChar); + return StrFormat("%s|%d:%d", parser->mFileName.c_str(), line, lineChar); +} + void BfAutoComplete::FixitAddMethod(BfTypeInstance* typeInst, const StringImpl& methodName, BfType* returnType, const BfTypeVector& paramTypes, bool wantStatic) { if ((typeInst->IsEnum()) && (returnType == typeInst) && (wantStatic)) @@ -2819,6 +2913,8 @@ void BfAutoComplete::FixitAddMethod(BfTypeInstance* typeInst, const StringImpl& String fullName = typeInst->mTypeDef->mFullName.ToString(); String methodStr; + methodStr += "\f\a"; + if (typeInst == mModule->mCurTypeInstance) { // Implicitly private @@ -2844,12 +2940,40 @@ void BfAutoComplete::FixitAddMethod(BfTypeInstance* typeInst, const StringImpl& FixitGetParamString(paramTypes, methodStr); - int fileLoc = typeInst->mTypeDef->mTypeDeclaration->GetSrcEnd(); - if (auto defineBlock = BfNodeDynCast(typeInst->mTypeDef->mTypeDeclaration->mDefineNode)) - fileLoc = defineBlock->mCloseBrace->GetSrcStart(); + int insertPos = FixitGetMemberInsertPos(typeInst->mTypeDef); methodStr += ")"; - AddEntry(AutoCompleteEntry("fixit", StrFormat("Create method '%s' in '%s'\taddMethod|%s|%d|||%s|{||}", methodName.c_str(), fullName.c_str(), parser->mFileName.c_str(), fileLoc, methodStr.c_str()).c_str())); + methodStr += "\t"; + AddEntry(AutoCompleteEntry("fixit", StrFormat("Create method '%s' in '%s'\taddMethod|%s|%s", methodName.c_str(), fullName.c_str(), FixitGetLocation(parser->mParserData, insertPos).c_str(), methodStr.c_str()).c_str())); } } -} \ No newline at end of file +} + +void BfAutoComplete::FixitCheckNamespace(BfTypeDef* activeTypeDef, BfTypeReference* typeRef, BfTokenNode* nextDotToken) +{ + if (nextDotToken == NULL) + return; + + auto parserData = typeRef->GetParserData(); + + BfSizedAtomComposite namespaceComposite; + String namespaceString = typeRef->ToString(); + bool isValid = mSystem->ParseAtomComposite(namespaceString, namespaceComposite); + + bool hasNamespace = false; + if (activeTypeDef != NULL) + hasNamespace = activeTypeDef->mNamespaceSearch.Contains(namespaceComposite); + + if (hasNamespace) + { + AddEntry(AutoCompleteEntry("fixit", StrFormat("Remove unneeded '%s'\taddMethod|%s-%d|", typeRef->ToString().c_str(), + FixitGetLocation(parserData, typeRef->GetSrcStart()).c_str(), nextDotToken->GetSrcEnd() - typeRef->GetSrcStart()).c_str())); + } + else + { + BfUsingFinder usingFinder; + usingFinder.VisitMembers(typeRef->GetSourceData()->mRootNode); + mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("using %s;\tusing|%s|%d||using %s;", namespaceString.c_str(), parserData->mFileName.c_str(), + usingFinder.mLastIdx, namespaceString.c_str()).c_str())); + } +} diff --git a/IDEHelper/Compiler/BfAutoComplete.h b/IDEHelper/Compiler/BfAutoComplete.h index d720719d..c7e620c1 100644 --- a/IDEHelper/Compiler/BfAutoComplete.h +++ b/IDEHelper/Compiler/BfAutoComplete.h @@ -218,8 +218,10 @@ public: void UpdateReplaceData(); void AddTypeInstanceEntry(BfTypeInstance* typeInst); void CheckDocumentation(AutoCompleteEntry* entry, BfCommentNode* documentation); - bool GetMethodInfo(BfMethodInstance* methodInst, StringImpl* methodName, StringImpl* insertString, bool isExplicitInterface); + bool GetMethodInfo(BfMethodInstance* methodInst, StringImpl* methodName, StringImpl* insertString, bool isImplementing, bool isExplicitInterface); void FixitGetParamString(const BfTypeVector& paramTypes, StringImpl& outStr); + int FixitGetMemberInsertPos(BfTypeDef* typeDef); + String FixitGetLocation(BfParserData* parserData, int insertPos); public: BfAutoComplete(BfResolveType resolveType = BfResolveType_Autocomplete); @@ -247,12 +249,12 @@ public: void CheckLabel(BfIdentifierNode* identifierNode, BfAstNode* precedingNode = NULL); void CheckEmptyStart(BfAstNode* prevNode, BfType* type); bool CheckFixit(BfAstNode* node); - void ChcekInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode* node); + void CheckInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode* node); void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic, BfTypeInstance* referencedFrom); void FixitAddCase(BfTypeInstance * typeInst, const StringImpl & caseName, const BfTypeVector & fieldTypes); void FixitAddMethod(BfTypeInstance* typeInst, const StringImpl& methodName, BfType* returnType, const BfTypeVector& paramTypes, bool wantStatic); - + void FixitCheckNamespace(BfTypeDef* activeTypeDef, BfTypeReference* typeRef, BfTokenNode* nextDotToken); }; NS_BF_END \ No newline at end of file diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index edddd59a..e2a74332 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -3768,7 +3768,7 @@ void BfCompiler::ProcessAutocompleteTempType() autoComplete->mInsertEndIdx = nameNode->GetSrcEnd(); } } - autoComplete->ChcekInterfaceFixit(typeInst, tempTypeDef->mTypeDeclaration->mNameNode); + autoComplete->CheckInterfaceFixit(typeInst, tempTypeDef->mTypeDeclaration->mNameNode); if (tempTypeDef->mTypeCode == BfTypeCode_TypeAlias) { diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index fa12c453..e1fb624a 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -5632,6 +5632,11 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy { if (mCompiler->mIsResolveOnly) { + bool isGetDefinition = false; + BfAutoComplete* autoComplete = NULL; + if (mCompiler->IsAutocomplete()) + autoComplete = mCompiler->mResolvePassData->mAutoComplete; + BfSourceData* typeRefSource = NULL; if (typeRef->IsTemporary()) { @@ -5680,7 +5685,7 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy { StringView leftString = qualifiedTypeRef->mLeft->ToStringView(); BfSizedAtomComposite leftComposite; - bool isValid = mSystem->ParseAtomComposite(leftString, leftComposite); + bool isValid = mSystem->ParseAtomComposite(leftString, leftComposite); mCompiler->mResolvePassData->mSourceClassifier->SetElementType(qualifiedTypeRef->mRight, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_TypeRef); if (resolvedTypeInstance == NULL) { @@ -5688,7 +5693,11 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy isNamespace = true; } else if ((isValid) && (resolvedTypeInstance->mTypeDef->mNamespace.EndsWith(leftComposite))) + { + if ((autoComplete != NULL) && (autoComplete->CheckFixit(typeRef))) + autoComplete->FixitCheckNamespace(GetActiveTypeDef(), qualifiedTypeRef->mLeft, qualifiedTypeRef->mDot); isNamespace = true; + } checkTypeRef = qualifiedTypeRef->mLeft; } @@ -5714,11 +5723,7 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy mCompiler->mResolvePassData->mSourceClassifier->SetElementType(checkNameNode, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_TypeRef); } } - - bool isGetDefinition = false; - BfAutoComplete* autoComplete = NULL; - if (mCompiler->IsAutocomplete()) - autoComplete = mCompiler->mResolvePassData->mAutoComplete; + if (autoComplete != NULL) { isGetDefinition = autoComplete->mIsGetDefinition; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 74da798f..3017b2d4 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -503,7 +503,11 @@ BfImportKind BfMethodInstance::GetImportKind() return mMethodDef->mImportKind; auto module = GetOwner()->mModule; - BfCustomAttribute* customAttribute = GetCustomAttributes()->Get(module->mCompiler->mImportAttributeTypeDef); + auto customAttributes = GetCustomAttributes(); + if (customAttributes == NULL) + return BfImportKind_None; + + BfCustomAttribute* customAttribute = customAttributes->Get(module->mCompiler->mImportAttributeTypeDef); if (customAttribute == NULL) return BfImportKind_Import_Static;