2019-09-29 07:44:23 -07:00
using System ;
using System.Security.Cryptography ;
using System.Text ;
2019-08-23 11:56:54 -07:00
using System.Collections.Generic ;
using System.Text ;
using System.IO ;
using System.Reflection ;
using System.Threading ;
using System.Threading.Tasks ;
using Beefy ;
using Beefy.widgets ;
using Beefy.gfx ;
using Beefy.theme ;
using Beefy.theme.dark ;
using Beefy.sys ;
using Beefy.events ;
using Beefy.geom ;
using Beefy.res ;
using System.Diagnostics ;
using Beefy.utils ;
using IDE.Debugger ;
using IDE.Compiler ;
using IDE.Util ;
2019-09-29 07:44:23 -07:00
using IDE.ui ;
2019-08-23 11:56:54 -07:00
using IDE.util ;
[AttributeUsage(.Method, .ReflectAttribute | .AlwaysIncludeTarget, ReflectUser=.All)]
struct IDECommandAttribute : Attribute
{
}
namespace IDE
{
public class WindowData
{
public DrawLayer mOverlayLayer ~ delete _ ;
}
enum SourceShowType
{
ShowExisting ,
ShowExistingInActivePanel ,
New ,
Temp ,
}
enum Verbosity
{
2019-09-22 08:25:38 -07:00
Default ,
2019-08-23 11:56:54 -07:00
Quiet ,
Minimal ,
Normal ,
Detailed ,
2019-09-04 07:00:38 -07:00
Diagnostic
2019-08-23 11:56:54 -07:00
}
class DeferredUserRequest
{
}
class DeferredShowPCLocation : DeferredUserRequest
{
public int32 mStackIdx ;
public this ( int32 stackIdx )
{
mStackIdx = stackIdx ;
}
}
enum BeefVerb
{
None ,
Open ,
New ,
OpenOrNew ,
2019-09-22 08:25:38 -07:00
Test ,
2019-10-09 16:18:11 -07:00
Run ,
GetVersion
2019-08-23 11:56:54 -07:00
}
enum HotResolveState
{
None ,
Pending ,
PendingWithDataChanges
}
public class IDETabbedView : DarkTabbedView
{
public ~ this ( )
{
if ( gApp . mActiveDocumentsTabbedView = = this )
gApp . mActiveDocumentsTabbedView = null ;
}
}
public class IDEApp : BFApp
{
public static String sRTVersionStr = "042" ;
#if BF_PLATFORM_WINDOWS
public static readonly String sPlatform64Name = "Win64" ;
public static readonly String sPlatform32Name = "Win32" ;
#elif BF_PLATFORM_LINUX
public static readonly String sPlatform64Name = "Linux64" ;
public static readonly String sPlatform32Name = "Linux32" ;
2019-10-15 12:28:21 -07:00
#elif BF_PLATFORM_MACOS
2019-10-14 17:49:10 -07:00
public static readonly String sPlatform64Name = "macOS" ;
public static readonly String sPlatform32Name = null ;
2019-08-23 11:56:54 -07:00
#else
public static readonly String sPlatform64Name = "Unknown64" ;
public static readonly String sPlatform32Name = "Unknown32" ;
#endif
public const uint32 cDialogOutlineLightColor = 0xFF404040 ;
public const uint32 cDialogOutlineDarkColor = 0xFF202020 ;
public static bool sExitTest ;
2019-09-22 08:25:38 -07:00
public Verbosity mVerbosity = . Default ;
2019-08-23 11:56:54 -07:00
public BeefVerb mVerb ;
public bool mDbgCompileDump ;
public int mDbgCompileIdx = - 1 ;
public String mDbgCompileDir ~ delete _ ;
public String mDbgVersionedCompileDir ~ delete _ ;
public DateTime mDbgHighestTime ;
2019-10-05 10:24:58 -07:00
public bool mForceFirstRun ;
2019-09-16 09:32:02 -07:00
public bool mIsFirstRun ;
2019-09-22 08:25:38 -07:00
public int? mTargetExitCode ;
2019-09-18 08:13:00 -07:00
public FileVersionInfo mVersionInfo ~ delete _ ;
2019-08-23 11:56:54 -07:00
//public ToolboxPanel mToolboxPanel;
public Monitor mMonitor = new Monitor ( ) ~ delete _ ;
public Thread mMainThread ;
public PropertiesPanel mPropertiesPanel ;
public Font mTinyCodeFont ~ delete _ ;
public Font mCodeFont ~ delete _ ;
protected bool mInitialized ;
public bool mConfig_NoIR ;
public bool mFailed ;
public bool mLastTestFailed ;
public bool mLastCompileFailed ;
public bool mLastCompileSucceeded ;
public bool mLastCompileHadMessages ;
public bool mPauseOnExit ;
public bool mDbgDelayedAutocomplete ;
public BeefConfig mBeefConfig = new BeefConfig ( ) ~ delete _ ;
public List < String > mDeferredFails = new . ( ) ~ DeleteContainerAndItems ! ( _ ) ;
public String mInitialCWD = new . ( ) ~ delete _ ;
public Commands mCommands = new . ( ) ~ delete _ ;
public KeyChordState mKeyChordState ~ delete _ ;
public WidgetWindow mMainWindow ;
public DarkDockingFrame mDockingFrame ;
public MainFrame mMainFrame ;
public GlobalUndoManager mGlobalUndoManager = new GlobalUndoManager ( ) ~ delete _ ;
public SourceControl mSourceControl = new SourceControl ( ) ~ delete _ ;
public WidgetWindow mPopupWindow ;
public IDETabbedView mActiveDocumentsTabbedView ;
public static new IDEApp sApp ;
public Image mTransparencyGridImage ~ delete _ ;
public Image mSquiggleImage ~ delete _ ;
public Image mCircleImage ~ delete _ ;
public OutputPanel mOutputPanel ;
public ImmediatePanel mImmediatePanel ;
public FindResultsPanel mFindResultsPanel ;
public WatchPanel mAutoWatchPanel ;
public WatchPanel mWatchPanel ;
public MemoryPanel mMemoryPanel ;
public CallStackPanel mCallStackPanel ;
2020-01-06 13:49:35 -08:00
public ErrorsPanel mErrorsPanel ;
2019-08-23 11:56:54 -07:00
public BreakpointPanel mBreakpointPanel ;
public ModulePanel mModulePanel ;
public ThreadPanel mThreadPanel ;
public ProfilePanel mProfilePanel ;
public ProjectPanel mProjectPanel ;
public ClassViewPanel mClassViewPanel ;
public Widget mLastActivePanel ;
public SourceViewPanel mLastActiveSourceViewPanel ;
public AutoCompletePanel mAutoCompletePanel ;
public Rect mRequestedWindowRect = Rect ( 64 , 64 , 1200 , 1024 ) ;
2019-09-27 13:03:47 -07:00
public BFWindow . ShowKind mRequestedShowKind ;
2019-08-23 11:56:54 -07:00
public WakaTime mWakaTime ~ delete _ ;
public Settings mSettings = new Settings ( ) ~ delete _ ;
public Workspace mWorkspace = new Workspace ( ) ~ delete _ ;
public FileWatcher mFileWatcher = new FileWatcher ( ) ~ delete _ ;
public int mLastFileChangeId ;
public bool mHaveSourcesChangedInternallySinceLastCompile ;
public bool mHaveSourcesChangedExternallySinceLastCompile ;
public String mConfigName = new String ( ) ~ delete _ ;
public String mPlatformName = new String ( ) ~ delete _ ;
2019-10-15 14:39:47 -07:00
public String mSetConfigName ~ delete _ ;
public String mSetPlatformName ~ delete _ ;
2019-08-23 11:56:54 -07:00
public Targets mTargets = new Targets ( ) ~ delete _ ;
public DebugManager mDebugger ~ delete _ ;
public String mSymSrvStatus = new String ( ) ~ delete _ ;
public Action < String > mPendingDebugExprHandler = null ;
public bool mIsImmediateDebugExprEval ;
public BookmarkManager mBookmarkManager = new BookmarkManager ( ) ~ delete _ ;
public HistoryManager mHistoryManager = new HistoryManager ( ) ~ delete _ ;
public Stopwatch mCompileAndRunStopwatch ~ delete _ ;
// The Beef build system only gets populated when a build is requested,
// but the Clang build system keeps up-to-date with the projects' files
// and watches for file changes
public BfSystem mBfBuildSystem ~ delete _ ;
public BfCompiler mBfBuildCompiler ;
public int mCompileSinceCleanCount ;
2019-08-27 08:04:41 -07:00
public BuildContext mBuildContext ~ delete _ ;
2019-08-23 11:56:54 -07:00
#if IDE_C_SUPPORT
public ClangCompiler mDepClang ~ delete _ ;
#endif
// The Beef resolve system is up-to-date with the projects' files,
// but the Clang resolver only has open files in it
public bool mNoResolve = false ;
public BfSystem mBfResolveSystem ~ delete _ ;
public BfCompiler mBfResolveCompiler ;
public BfResolveHelper mBfResolveHelper ~ delete _ ;
#if IDE_C_SUPPORT
public ClangCompiler mResolveClang ;
#endif
public SpellChecker mSpellChecker ;
public List < String > mExternalChangeDeferredOpen = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
public SettingHistoryManager mLaunchHistoryManager = new SettingHistoryManager ( true ) ~ delete _ ;
public SettingHistoryManager mFindAndReplaceHistoryManager = new SettingHistoryManager ( true ) ~ delete _ ;
List < Object > mIdleDeferredDeletes = new List < Object > ( ) ~ delete _ ;
public bool mCompilingBeef = false ;
public bool mWantsClean = false ;
public bool mWantsBeefClean = false ;
public bool mWantsRehupCallstack = false ;
public bool mDebugAutoBuild = false ;
public bool mDebugAutoRun = false ;
public bool mDisableBuilding ;
public int32 mDebugAutoShutdownCounter ;
public bool mTargetDidInitBreak = false ;
public bool mTargetHadFirstBreak = false ;
public bool mTargetStartWithStep = false ;
public Breakpoint mMainBreakpoint ;
2019-08-27 08:04:41 -07:00
public Breakpoint mMainBreakpoint2 ;
2019-08-23 11:56:54 -07:00
public bool mInDisassemblyView ;
public bool mIsAttachPendingSourceShow ;
public bool mStepOverExternalFiles ;
public bool mRunningTestScript ;
2019-09-07 06:40:03 -07:00
public bool mStartedWithTestScript ;
2019-08-23 11:56:54 -07:00
public bool mExitWhenTestScriptDone = true ;
public ScriptManager mScriptManager = new ScriptManager ( ) ~ delete _ ;
public TestManager mTestManager ;
public bool mExecutionPaused = false ;
public HotResolveState mHotResolveState ;
public int mHotResolveTryIdx ;
public bool mDebuggerPerformingTask = false ; // Executing an expression, loading from symbol server
public int32 mForegroundTargetCountdown = 0 ;
public int32 mDebuggerContinueIdx ;
public SysMenu mWindowMenu ;
public List < SourceViewPanel > mPostRemoveUpdatePanels = new . ( ) ~ delete _ ;
public List < String > mRecentlyDisplayedFiles = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
public List < SysMenu > mRecentlyDisplayedFilesMenuItems = new List < SysMenu > ( ) ~ delete _ ;
public Dictionary < BFWindow , WindowData > mWindowDatas = new Dictionary < BFWindow , WindowData > ( ) ~ delete _ ;
public Dictionary < String , FileEditData > mFileEditData = new Dictionary < String , FileEditData > ( ) ~
{
for ( var editDataPair in mFileEditData )
{
delete editDataPair . key ;
editDataPair . value . Deref ( ) ;
}
delete _ ;
} ;
public int32 mFileDataDataRevision ;
/ * public Point mLastAbsMousePos ;
public Point mLastRelMousePos ;
public int32 mMouseStillTicks ;
public Widget mLastMouseWidget ; * /
public int32 mCloseDelay ;
public FileChangedDialog mFileChangedDialog ;
public FindAndReplaceDialog mFindAndReplaceDialog ;
public LaunchDialog mLaunchDialog ;
public SymbolReferenceHelper mSymbolReferenceHelper ;
public WrappedMenuValue mViewWhiteSpace = . ( false ) ;
public bool mEnableGCCollect = true ;
public bool mDbgFastUpdate ;
public bool mTestEnableConsole = false ;
public ProfileInstance mLongUpdateProfileId ;
public uint32 mLastLongUpdateCheck ;
public uint32 mLastLongUpdateCheckError ;
bool mRunTest ;
int mRunTestDelay ;
bool mEnableRunTiming = false ; ///
ProfileInstance mRunTimingProfileId ;
bool mDoingRunTiming ;
bool mProfileCompile = false ;
ProfileInstance mProfileCompileProfileId ;
#if ! CLI
public IPCHelper mIPCHelper ~ delete _ ;
public bool mIPCHadFocus ;
#endif
int32 mProcessAttachId ;
#if BF_PLATFORM_WINDOWS
Windows . EventHandle mProcessAttachHandle ;
#endif
String mCrashDumpPath ~ delete _ ;
bool mShowedFirstDocument = false ;
class LaunchData
{
2019-11-28 09:12:49 -08:00
public String mTargetPath ~ delete _ ;
2019-08-23 11:56:54 -07:00
public String mArgs ~ delete _ ;
public String mWorkingDir ~ delete _ ;
public bool mPaused = false ;
}
LaunchData mLaunchData ~ delete _ ;
DeferredUserRequest mDeferredUserRequest ~ delete _ ;
enum DeferredOpenKind
{
None ,
File ,
Workspace ,
2019-09-05 08:18:24 -07:00
NewWorkspace ,
NewWorkspaceOrProject ,
2019-08-23 11:56:54 -07:00
CrashDump ,
DebugSession
}
DeferredOpenKind mDeferredOpen ;
String mDeferredOpenFileName ;
2019-08-27 08:04:41 -07:00
public class ExecutionCmd
2019-08-23 11:56:54 -07:00
{
public bool mOnlyIfNotFailed ;
}
2019-08-27 08:04:41 -07:00
public class BuildCompletedCmd : ExecutionCmd
2019-08-23 11:56:54 -07:00
{
public Stopwatch mStopwatch ~ delete _ ;
public String mHotProjectName ~ delete _ ;
public bool mFailed ;
#if IDE_C_SUPPORT
public HashSet < String > mClangCompiledFiles = new HashSet < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
#endif
}
class ProcessBfCompileCmd : ExecutionCmd
{
public BfPassInstance mBfPassInstance ;
public bool mRunAfter ;
public Project mHotProject ;
public Stopwatch mStopwatch ~ delete _ ;
public Profiler mProfiler ;
public ProfileCmd mProfileCmd ~ delete _ ;
public bool mHadBeef ;
public ~ this ( )
{
}
}
class ProfileCmd : ExecutionCmd
{
public int mThreadId ;
public String mDesc ~ delete _ ;
public int mSampleRate ;
}
class StartDebugCmd : ExecutionCmd
{
public bool mWasCompiled ;
2019-08-29 14:19:07 -07:00
public this ( )
{
}
2019-08-23 11:56:54 -07:00
}
2019-08-27 08:04:41 -07:00
public class TargetCompletedCmd : ExecutionCmd
2019-08-23 11:56:54 -07:00
{
2019-08-27 08:04:41 -07:00
public Project mProject ;
public bool mIsReady = true ;
2019-08-23 11:56:54 -07:00
public this ( Project project )
{
mProject = project ;
}
2019-09-28 09:48:37 -07:00
public ~ this ( )
{
}
2019-08-23 11:56:54 -07:00
}
2019-08-27 08:04:41 -07:00
public enum ArgsFileKind
2019-08-23 11:56:54 -07:00
{
None ,
UTF8 ,
UTF16WithBom
}
2019-08-27 08:04:41 -07:00
public class ExecutionQueueCmd : ExecutionCmd
2019-08-23 11:56:54 -07:00
{
public String mFileName ~ delete _ ;
public String mArgs ~ delete _ ;
public String mWorkingDir ~ delete _ ;
public Dictionary < String , String > mEnvVars ~ DeleteDictionyAndKeysAndItems ! ( _ ) ;
public ArgsFileKind mUseArgsFile ;
2019-09-22 08:25:38 -07:00
public int32 mParallelGroup = - 1 ;
public bool mIsTargetRun ;
2019-10-23 07:12:36 -07:00
public String mStdInData ~ delete _ ;
2019-08-23 11:56:54 -07:00
}
2019-08-27 08:04:41 -07:00
public List < ExecutionCmd > mExecutionQueue = new List < ExecutionCmd > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
2019-08-23 11:56:54 -07:00
public class ExecutionInstance
{
public SpawnedProcess mProcess /*~ delete _*/ ;
public List < String > mDeferredOutput = new List < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
public Stopwatch mStopwatch = new Stopwatch ( ) ~ delete _ ;
public String mTempFileName ~ delete _ ;
public int32 mParallelGroup = - 1 ;
public Task < String > mReadTask /*~ delete _*/ ;
public Action < Task < String > > mOnReadTaskComplete /*~ delete _*/ ;
public Task < String > mErrorTask /*~ delete _*/ ;
public Action < Task < String > > mOnErrorTaskComplete /*~ delete _*/ ;
public Monitor mMonitor = new Monitor ( ) ~ delete _ ;
2019-10-23 07:12:36 -07:00
public String mStdInData ~ delete _ ;
2019-08-23 11:56:54 -07:00
public Thread mOutputThread ;
public Thread mErrorThread ;
2019-10-23 07:12:36 -07:00
public Thread mInputThread ;
2019-08-23 11:56:54 -07:00
public int? mExitCode ;
public bool mAutoDelete = true ;
public bool mCanceled ;
2019-09-22 08:25:38 -07:00
public bool mIsTargetRun ;
2019-08-23 11:56:54 -07:00
public ~ this ( )
{
delete mProcess ;
/ * if ( mProcess ! = null )
mProcess . Close ( ) ; * /
2019-10-23 07:12:36 -07:00
if ( mInputThread ! = null )
mInputThread . Join ( ) ;
delete mInputThread ;
2019-08-23 11:56:54 -07:00
if ( mOutputThread ! = null )
mOutputThread . Join ( ) ;
delete mOutputThread ;
2019-10-23 07:12:36 -07:00
2019-08-23 11:56:54 -07:00
if ( mErrorThread ! = null )
mErrorThread . Join ( ) ;
2019-10-23 07:12:36 -07:00
delete mErrorThread ;
2019-08-23 11:56:54 -07:00
delete mReadTask ;
delete mOnReadTaskComplete ;
delete mErrorTask ;
delete mOnErrorTaskComplete ;
}
public void Cancel ( )
{
mCanceled = true ;
mProcess . Kill ( 0 , . KillChildren ) ;
}
}
List < ExecutionInstance > mExecutionInstances = new List < ExecutionInstance > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
public int32 mHotIndex = 0 ;
private int32 mStepCount ;
private int32 mNoDebugMessagesTick ;
public bool IsCompiling
{
get
{
2019-08-27 08:04:41 -07:00
return ( mExecutionInstances . Count > 0 ) | | ( mExecutionQueue . Count > 0 ) | | ( mBuildContext ! = null ) ;
2019-08-23 11:56:54 -07:00
}
}
public bool EnableGCCollect
{
get
{
return mEnableGCCollect ;
}
set
{
mEnableGCCollect = value ;
//GC.SetAutoCollectPeriod(mEnableGCCollect ? 2000 : -1);
GC . SetAutoCollectPeriod ( mEnableGCCollect ? 20 : - 1 ) ;
GC . SetCollectFreeThreshold ( mEnableGCCollect ? 64 * 1024 * 1024 : - 1 ) ;
}
}
2019-10-17 05:31:57 -07:00
[StdCall,CLink]
static extern void IDEHelper_ProgramStart ( ) ;
[StdCall,CLink]
static extern void IDEHelper_ProgramDone ( ) ;
2019-08-23 11:56:54 -07:00
public this ( )
{
sApp = this ;
gApp = this ;
mMainThread = Thread . CurrentThread ;
2019-10-17 05:31:57 -07:00
IDEHelper_ProgramStart ( ) ;
2019-08-23 11:56:54 -07:00
#if ! CLI
mDebugger = new DebugManager ( ) ;
mVerb = . OpenOrNew ;
#endif
//BfParser_Go();///
mScriptManager . AddTarget ( this ) ;
}
public static this ( )
{
//Profiler.StartSampling();
}
public void GetBfSystems ( List < BfSystem > systems )
{
systems . Add ( mBfBuildSystem ) ;
if ( mBfResolveSystem ! = null )
systems . Add ( mBfResolveSystem ) ;
}
public void GetBfCompilers ( List < BfCompiler > compiler )
{
compiler . Add ( mBfBuildCompiler ) ;
compiler . Add ( mBfResolveCompiler ) ;
}
public bool HaveSourcesChanged ( )
{
return mHaveSourcesChangedInternallySinceLastCompile | | mHaveSourcesChangedExternallySinceLastCompile ;
}
public void MarkWatchesDirty ( )
{
WithWatchPanels ( scope ( watchPanel ) = >
{
watchPanel . MarkWatchesDirty ( false ) ;
} ) ;
}
void PCChanged ( )
{
var disasmPanel = TryGetDisassemblyPanel ( ) ;
if ( disasmPanel ! = null )
disasmPanel . mLocationDirty = true ;
mDebugger . mCallStackDirty = true ;
WithWatchPanels ( scope ( watchPanel ) = >
{
watchPanel . MarkWatchesDirty ( true , ! mTargetHadFirstBreak ) ;
} ) ;
mMemoryPanel . MarkViewDirty ( ) ;
mCallStackPanel . MarkCallStackDirty ( ) ;
mThreadPanel . MarkThreadsDirty ( ) ;
mDebugger . CheckCallStack ( ) ;
// If we do a "PCChanged" from the execution of a method in the Immediate panel, don't move
// the focus away from the Immediate edit widget
bool setFocus = true ;
for ( var window in mWindows )
{
var widgetWindow = window as WidgetWindow ;
if ( ( widgetWindow ! = null ) & & ( widgetWindow . mHasFocus ) )
{
if ( widgetWindow . mFocusWidget is ImmediateWidget )
{
setFocus = false ;
}
}
}
if ( mRunningTestScript )
setFocus = true ;
ShowPCLocation ( mDebugger . mActiveCallStackIdx , false , false , false , setFocus ) ;
}
public ~ this ( )
{
#if ! CLI
2019-10-05 10:24:58 -07:00
if ( ! mStartedWithTestScript & & ! mForceFirstRun )
2019-08-23 11:56:54 -07:00
{
mSettings . Save ( ) ;
SaveDefaultLayoutData ( ) ;
}
#endif
/ * WithTabs ( scope ( tabButton ) = >
{
var panel = tabButton . mContent as Panel ;
if ( panel ! = null )
{
if ( ! panel . mAutoDelete )
{
// Is part of the panel list, clear mContent so we don't double-delete
tabButton . mContent = null ;
}
}
} ) ; * /
mixin RemoveAndDelete ( var widget )
{
Widget . RemoveAndDelete ( widget ) ;
widget = null ;
}
2020-01-12 09:21:50 -08:00
2019-08-23 11:56:54 -07:00
RemoveAndDelete ! ( mProjectPanel ) ;
RemoveAndDelete ! ( mClassViewPanel ) ;
RemoveAndDelete ! ( mOutputPanel ) ;
RemoveAndDelete ! ( mImmediatePanel ) ;
RemoveAndDelete ! ( mFindResultsPanel ) ;
RemoveAndDelete ! ( mAutoWatchPanel ) ;
RemoveAndDelete ! ( mWatchPanel ) ;
RemoveAndDelete ! ( mMemoryPanel ) ;
RemoveAndDelete ! ( mCallStackPanel ) ;
RemoveAndDelete ! ( mBreakpointPanel ) ;
RemoveAndDelete ! ( mModulePanel ) ;
RemoveAndDelete ! ( mThreadPanel ) ;
RemoveAndDelete ! ( mProfilePanel ) ;
RemoveAndDelete ! ( mPropertiesPanel ) ;
RemoveAndDelete ! ( mAutoCompletePanel ) ;
if ( mSymbolReferenceHelper ! = null )
mSymbolReferenceHelper . Close ( ) ;
if ( mBfBuildCompiler ! = null )
mBfBuildCompiler . CancelBackground ( ) ;
if ( mBfResolveCompiler ! = null )
mBfResolveCompiler . CancelBackground ( ) ;
2020-01-06 15:07:13 -08:00
2019-08-23 11:56:54 -07:00
#if IDE_C_SUPPORT
mDepClang . CancelBackground ( ) ;
mResolveClang . CancelBackground ( ) ;
#endif
/ * if ( mMainBreakpoint ! = null )
{
mMainBreakpoint . Dispose ( ) ;
mMainBreakpoint = null ;
} * /
/ * delete mBfBuildCompiler ;
delete mBfBuildSystem ;
delete mDepClang ;
delete mBfResolveCompiler ;
delete mBfResolveSystem ;
delete mResolveClang ;
delete mSpellChecker ;
//base.Dispose();
delete mDebugger ;
delete ThemeFactory . mDefault ; * /
for ( var val in mWindowDatas . Values )
delete val ;
2020-01-29 16:36:41 -08:00
if ( mErrorsPanel ? . mParent ! = null )
2020-01-29 16:27:11 -08:00
mErrorsPanel . RemoveSelf ( ) ;
2019-08-23 11:56:54 -07:00
ProcessIdleDeferredDeletes ( ) ;
// Get rid of panels
ProcessDeferredDeletes ( ) ;
delete mBfBuildCompiler ;
delete mBfResolveCompiler ;
#if IDE_C_SUPPORT
delete mResolveClang ;
#endif
delete mSpellChecker ;
2020-01-06 15:07:13 -08:00
//NOTE: this must be done after the resolve compiler has been destroyed
RemoveAndDelete ! ( mErrorsPanel ) ;
2019-08-23 11:56:54 -07:00
// Clear these out, for delete ordering purposes
ProcessDeferredDeletes ( ) ;
}
public bool IsCrashDump
{
get
{
return mCrashDumpPath ! = null ;
}
}
2020-01-12 09:21:50 -08:00
void WithStandardPanels ( delegate void ( Panel panel ) dlg )
{
dlg ( mProjectPanel ) ;
dlg ( mClassViewPanel ) ;
dlg ( mOutputPanel ) ;
dlg ( mImmediatePanel ) ;
dlg ( mFindResultsPanel ) ;
dlg ( mAutoWatchPanel ) ;
dlg ( mWatchPanel ) ;
dlg ( mMemoryPanel ) ;
dlg ( mCallStackPanel ) ;
dlg ( mErrorsPanel ) ;
dlg ( mBreakpointPanel ) ;
dlg ( mModulePanel ) ;
dlg ( mThreadPanel ) ;
dlg ( mProfilePanel ) ;
dlg ( mPropertiesPanel ) ;
dlg ( mAutoCompletePanel ) ;
}
2019-08-23 11:56:54 -07:00
public override void ShutdownCompleted ( )
{
base . ShutdownCompleted ( ) ;
}
public override void Shutdown ( )
{
if ( ( mDebugger ! = null ) & & ( mDebugger . mIsRunning ) )
{
mDebugger . DisposeNativeBreakpoints ( ) ;
mDebugger . Detach ( ) ;
mDebugger . mIsRunning = false ;
mExecutionPaused = false ;
}
base . Shutdown ( ) ;
}
public override void Run ( )
{
base . Run ( ) ;
}
public void Cmd_NewFileView ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
ShowSourceFile ( sourceViewPanel . mFilePath , sourceViewPanel . mProjectSource , SourceShowType . New ) ;
}
}
public void IdleDeferDelete ( Object obj )
{
mIdleDeferredDeletes . Add ( obj ) ;
}
void ProcessIdleDeferredDeletes ( )
{
if ( ( ( mBfBuildCompiler ! = null ) & & mBfBuildCompiler . HasQueuedCommands ( ) ) | |
( ( mBfResolveCompiler ! = null ) & & ( mBfResolveCompiler . HasQueuedCommands ( ) ) )
#if IDE_C_SUPPORT
| | ( mDepClang . HasQueuedCommands ( ) ) | |
( mResolveClang . HasQueuedCommands ( ) )
#endif
)
return ;
for ( var obj in mIdleDeferredDeletes )
delete obj ;
mIdleDeferredDeletes . Clear ( ) ;
}
public void DoOpenFile ( )
{
#if ! CLI
String fullDir = scope . ( ) ;
let sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
Path . GetDirectoryPath ( sourceViewPanel . mFilePath , fullDir ) ;
}
else if ( ( gApp . mDebugger . mRunningPath ! = null ) & & ( ! mWorkspace . IsInitialized ) )
{
Path . GetDirectoryPath ( gApp . mDebugger . mRunningPath , fullDir ) ;
}
var fileDialog = scope OpenFileDialog ( ) ;
fileDialog . Title = "Open File" ;
fileDialog . Multiselect = true ;
fileDialog . ValidateNames = true ;
if ( ! fullDir . IsEmpty )
fileDialog . InitialDirectory = fullDir ;
mMainWindow . PreModalChild ( ) ;
if ( fileDialog . ShowDialog ( GetActiveWindow ( ) ) . GetValueOrDefault ( ) = = . OK )
{
for ( String openFileName in fileDialog . FileNames )
{
//openFileName.Replace('\\', '/');
AddRecentFile ( . OpenedFile , openFileName ) ;
ShowSourceFile ( openFileName ) ;
}
}
#endif
}
2019-09-18 08:13:00 -07:00
public void OpenWorkspace ( StringView openFileName )
{
CloseWorkspace ( ) ;
mWorkspace . mDir = new String ( ) ;
Path . GetDirectoryPath ( openFileName , mWorkspace . mDir ) ;
mWorkspace . mName = new String ( ) ;
Path . GetFileName ( mWorkspace . mDir , mWorkspace . mName ) ;
LoadWorkspace ( . OpenOrNew ) ;
FinishShowingNewWorkspace ( ) ;
}
2020-01-12 09:21:50 -08:00
public void DoOpenWorkspace ( bool isCreating = false )
2019-08-23 11:56:54 -07:00
{
#if ! CLI
if ( mDeferredOpenFileName ! = null )
{
2019-12-26 07:03:35 -08:00
String prevFilePath = scope . ( mDeferredOpenFileName ) ;
mDeferredOpenFileName . Clear ( ) ;
Path . GetActualPathName ( prevFilePath , mDeferredOpenFileName ) ;
2019-09-18 08:13:00 -07:00
OpenWorkspace ( mDeferredOpenFileName ) ;
2019-08-23 11:56:54 -07:00
DeleteAndNullify ! ( mDeferredOpenFileName ) ;
return ;
}
2020-01-12 09:21:50 -08:00
var folderDialog = scope FolderBrowserDialog ( isCreating ? . Save : . Open ) ;
2019-09-18 08:13:00 -07:00
var initialDir = scope String ( ) ;
if ( mInstallDir . Length > 0 )
Path . GetDirectoryPath ( . ( mInstallDir , 0 , mInstallDir . Length - 1 ) , initialDir ) ;
initialDir . Concat ( Path . DirectorySeparatorChar , "Samples" ) ;
folderDialog . SelectedPath = initialDir ;
2020-01-12 09:21:50 -08:00
//folderDialog.
2019-08-23 11:56:54 -07:00
if ( folderDialog . ShowDialog ( GetActiveWindow ( ) ) . GetValueOrDefault ( ) = = . OK )
{
var selectedPath = scope String . . AppendF ( folderDialog . SelectedPath ) ;
selectedPath . Append ( Path . DirectorySeparatorChar ) ;
selectedPath . Append ( "BeefSpace.toml" ) ;
String . NewOrSet ! ( mDeferredOpenFileName , selectedPath ) ;
mDeferredOpen = . Workspace ;
}
#endif
}
public void DoOpenDebugSession ( StringView filePath )
{
let data = scope StructuredData ( ) ;
if ( data . Load ( filePath ) case . Err )
{
2019-08-27 08:04:41 -07:00
CreateDefaultLayout ( ) ;
2019-08-23 11:56:54 -07:00
OutputErrorLine ( "Failed to load debug session '{}'" , filePath ) ;
return ;
}
AddRecentFile ( . OpenedDebugSession , filePath ) ;
NewDebugSession ( true ) ;
let project = mWorkspace . mProjects [ 0 ] ;
project . mProjectPath . Set ( filePath ) ;
LoadWorkspaceUserData ( data ) ;
using ( data . Open ( "DebugSession" ) )
{
project . Deserialize ( data ) ;
}
}
public void DoOpenDebugSession ( )
{
#if ! CLI
if ( mDeferredOpenFileName ! = null )
{
CloseWorkspace ( ) ;
DoOpenDebugSession ( mDeferredOpenFileName ) ;
FinishShowingNewWorkspace ( false ) ;
DeleteAndNullify ! ( mDeferredOpenFileName ) ;
return ;
}
var fileDialog = scope OpenFileDialog ( ) ;
fileDialog . Title = "Open Debug Session" ;
fileDialog . SetFilter ( "Debug Session (*.bfdbg)|*.bfdbg|All files (*.*)|*.*" ) ;
fileDialog . ValidateNames = true ;
mMainWindow . PreModalChild ( ) ;
if ( fileDialog . ShowDialog ( GetActiveWindow ( ) ) . GetValueOrDefault ( ) = = . OK )
{
for ( String openFileName in fileDialog . FileNames )
{
String . NewOrSet ! ( mDeferredOpenFileName , openFileName ) ;
mDeferredOpen = . DebugSession ;
break ;
}
}
#endif
}
public void OpenCrashDump ( StringView path )
{
AddRecentFile ( . OpenedCrashDump , path ) ;
StopDebugging ( ) ;
String . NewOrSet ! ( mCrashDumpPath , path ) ;
if ( mDebugger . OpenMiniDump ( mCrashDumpPath ) )
{
mDebugger . mIsRunning = true ;
mExecutionPaused = false ; // Make this false so we can detect a Pause immediately
}
else
{
Fail ( StackStringFormat ! ( "Failed to load minidump '{0}'" , mCrashDumpPath ) ) ;
DeleteAndNullify ! ( mCrashDumpPath ) ;
}
}
public void DoOpenCrashDump ( )
{
#if ! CLI
2019-09-20 10:40:09 -07:00
if ( mDeferredOpenFileName ! = null )
2019-08-23 11:56:54 -07:00
{
2019-09-20 10:40:09 -07:00
OpenCrashDump ( mDeferredOpenFileName ) ;
2019-08-23 11:56:54 -07:00
DeleteAndNullify ! ( mDeferredOpenFileName ) ;
return ;
2019-09-20 10:40:09 -07:00
}
2019-08-23 11:56:54 -07:00
var fileDialog = scope OpenFileDialog ( ) ;
fileDialog . Title = "Open Crash Dump" ;
fileDialog . SetFilter ( "Crash Dump (*.dmp)|*.dmp|All files (*.*)|*.*" ) ;
fileDialog . ValidateNames = true ;
mMainWindow . PreModalChild ( ) ;
if ( fileDialog . ShowDialog ( GetActiveWindow ( ) ) . GetValueOrDefault ( ) = = . OK )
{
for ( String openFileName in fileDialog . FileNames )
{
OpenCrashDump ( openFileName ) ;
break ;
}
}
#endif
}
public void CheckProjectRelativePath ( String path )
{
if ( path . Length < 2 )
return ;
if ( ( path [ 0 ] = = '\\' ) | | ( path [ 0 ] = = '/' ) | | ( path [ 1 ] = = ':' ) )
return ;
for ( var project in mWorkspace . mProjects )
{
String testPath = scope String ( ) ;
testPath . Append ( project . mProjectDir ) ;
testPath . Append ( Path . DirectorySeparatorChar ) ;
testPath . Append ( path ) ;
if ( File . Exists ( testPath ) )
{
path . Set ( testPath ) ;
return ;
}
}
}
public void PerformAction ( String cmdStr )
{
List < String > cmds = scope List < String > ( ) ;
int strIdx = 0 ;
while ( true )
{
String str = scope : : String ( ) ;
Utils . ParseSpaceSep ( cmdStr , ref strIdx , str ) ;
if ( str . IsEmpty )
break ;
cmds . Add ( str ) ;
}
if ( cmds . Count = = 0 )
return ;
switch ( cmds [ 0 ] )
{
case "ShowCode" :
if ( cmds . Count < 3 )
break ;
if ( var sourceViewPanel = GetActiveSourceViewPanel ( true ) )
sourceViewPanel . RecordHistoryLocation ( ) ;
int32 char8Idx = int32 . Parse ( cmds [ 2 ] ) . GetValueOrDefault ( ) ;
var sourceViewPanel = ShowSourceFile ( cmds [ 1 ] , null , SourceShowType . Temp ) ;
if ( sourceViewPanel = = null )
return ;
var editWidgetContent = sourceViewPanel . mEditWidget . mEditWidgetContent ;
int line ;
int lineChar ;
editWidgetContent . GetLineCharAtIdx ( char8Idx , out line , out lineChar ) ;
sourceViewPanel . ShowFileLocation ( char8Idx , . Always ) ;
case "ShowCodeAddr" :
var sourceViewPanel = GetActiveSourceViewPanel ( true ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . RecordHistoryLocation ( ) ;
int64 addr = int64 . Parse ( cmds [ 1 ] , System . Globalization . NumberStyles . HexNumber ) . GetValueOrDefault ( ) ;
String fileName = scope String ( ) ;
int lineNum = 0 ;
int column ;
int hotIdx ;
int defLineStart ;
int defLineEnd ;
mDebugger . GetCodeAddrInfo ( ( int ) addr , fileName , out hotIdx , out defLineStart , out defLineEnd , out lineNum , out column ) ;
if ( fileName . Length > 0 )
{
int showHotIdx = - 1 ;
if ( ( defLineStart = = - 1 ) | | ( sourceViewPanel = = null ) | | ( sourceViewPanel . HasTextChangedSinceCompile ( defLineStart , defLineEnd , hotIdx ) ) )
showHotIdx = hotIdx ;
ShowSourceFileLocation ( fileName , showHotIdx , hotIdx , lineNum , column , LocatorType . Always ) ;
}
else if ( addr ! = 0 )
{
var disassemblyPanel = ShowDisassemblyPanel ( true ) ;
disassemblyPanel . Show ( addr ) ;
}
}
}
public Dialog QuerySaveFiles ( List < String > changedList , WidgetWindow window = null )
{
Dialog aDialog ;
if ( changedList . Count = = 1 )
{
aDialog = ThemeFactory . mDefault . CreateDialog ( "Save file?" , StackStringFormat ! ( "{0} has been modified. Save before closing?" , changedList [ 0 ] ) , DarkTheme . sDarkTheme . mIconWarning ) ;
}
else
{
String text = scope String ( "The following files have been modified: " ) ;
text . Join ( ", " , changedList . GetEnumerator ( ) ) ;
text . Append ( ". Save before closing?" ) ;
aDialog = ThemeFactory . mDefault . CreateDialog ( "Save files?" , text , DarkTheme . sDarkTheme . mIconWarning ) ;
}
return aDialog ;
}
public bool CheckCloseWorkspace ( BFWindow window , Action onSave , Action onNoSave , Action onCancel )
{
void DeleteDelegates ( )
{
delete onSave ;
delete onNoSave ;
delete onCancel ;
}
if ( mStopping )
{
DeleteDelegates ( ) ;
return true ;
}
List < String > changedList = scope List < String > ( ) ;
if ( mWorkspace . mHasChanged )
{
var path = scope String ( ) ;
GetWorkspaceFileName ( path ) ;
var fileName = new String ( ) ;
Path . GetFileName ( path , fileName ) ;
if ( fileName . IsEmpty )
fileName . Append ( "Workspace" ) ;
changedList . Add ( fileName ) ;
}
for ( var project in mWorkspace . mProjects )
if ( project . mHasChanged )
{
var fileName = new String ( ) ;
Path . GetFileName ( project . mProjectPath , fileName ) ;
if ( fileName . IsEmpty )
fileName . Append ( project . IsDebugSession ? "Debug Session" : "Project" ) ;
changedList . Add ( fileName ) ;
}
mWorkspace . WithProjectItems ( scope ( projectItem ) = >
{
var projectSource = projectItem as ProjectSource ;
if ( projectSource ! = null )
{
if ( ( projectSource . mEditData ! = null ) & & ( projectSource . mEditData . HasTextChanged ( ) ) )
{
var fileName = new String ( ) ;
Path . GetFileName ( projectSource . mPath , fileName ) ;
changedList . Add ( fileName ) ;
}
}
} ) ;
WithSourceViewPanels ( scope ( sourceViewPanel ) = >
{
if ( sourceViewPanel . HasUnsavedChanges ( ) )
{
var fileName = scope String ( ) ;
Path . GetFileName ( sourceViewPanel . mFilePath , fileName ) ;
if ( ! changedList . Contains ( fileName ) )
changedList . Add ( new String ( fileName ) ) ;
}
} ) ;
if ( changedList . Count = = 0 )
{
DeleteDelegates ( ) ;
if ( ! mRunningTestScript )
SaveWorkspaceUserData ( false ) ;
return true ;
}
var aDialog = QuerySaveFiles ( changedList ) ;
DeleteAndClearItems ! ( changedList ) ;
aDialog . mDefaultButton = aDialog . AddButton ( "Save" , new ( evt ) = >
{
onSave ( ) ;
} ~ delete onSave ) ;
aDialog . AddButton ( "Don't Save" , new ( evt ) = >
{
2019-09-18 08:13:00 -07:00
OutputLine ( "Changes not saved." ) ;
2019-08-23 11:56:54 -07:00
onNoSave ( ) ;
} ~ delete onNoSave ) ;
aDialog . mEscButton = aDialog . AddButton ( "Cancel" , new ( evt ) = >
{
if ( onCancel ! = null )
onCancel ( ) ;
} ~ delete onCancel ) ;
aDialog . PopupWindow ( ( WidgetWindow ) window ? ? mMainWindow ) ;
return false ;
}
public bool AllowClose ( BFWindow window )
{
if ( mRunningTestScript )
return true ;
return CheckCloseWorkspace ( window ,
new ( ) = >
{
// We use a close delay after saving so the user can see we actually saved before closing down
if ( SaveAll ( ) )
mCloseDelay = 30 ;
} ,
new ( ) = >
{
SaveWorkspaceUserData ( false ) ;
mMainWindow . Close ( true ) ;
} , null ) ;
}
public bool SecondaryAllowClose ( BFWindow window )
{
if ( mRunningTestScript )
return true ;
List < String > changedList = scope List < String > ( ) ;
defer ClearAndDeleteItems ( changedList ) ;
WithSourceViewPanels ( scope ( sourceViewPanel ) = >
{
if ( ( sourceViewPanel . mWidgetWindow = = window ) & & ( sourceViewPanel . HasUnsavedChanges ( ) ) )
{
var fileName = new String ( ) ;
Path . GetFileName ( sourceViewPanel . mFilePath , fileName ) ;
changedList . Add ( fileName ) ;
}
} ) ;
if ( changedList . Count = = 0 )
return true ;
var aDialog = QuerySaveFiles ( changedList , ( WidgetWindow ) window ) ;
aDialog . mDefaultButton = aDialog . AddButton ( "Save" , new ( evt ) = >
{
bool hadError = false ;
// We use a close delay after saving so the user can see we actually saved before closing down
var _this = this ;
WithSourceViewPanels ( scope [ & ] ( sourceViewPanel ) = >
{
if ( ( ! hadError ) & & ( sourceViewPanel . mWidgetWindow = = window ) & & ( sourceViewPanel . HasUnsavedChanges ( ) ) )
if ( ! _this . SaveFile ( sourceViewPanel ) )
hadError = true ;
} ) ;
if ( hadError )
return ;
mMainWindow . SetForeground ( ) ;
window . Close ( true ) ;
} ) ;
aDialog . AddButton ( "Don't Save" , new ( evt ) = >
{
mMainWindow . SetForeground ( ) ;
window . Close ( true ) ;
} ) ;
aDialog . mEscButton = aDialog . AddButton ( "Cancel" ) ;
aDialog . PopupWindow ( ( WidgetWindow ) window ? ? mMainWindow ) ;
return false ;
}
public SourceViewPanel GetActiveSourceViewPanel ( bool includeLastActive = false )
{
if ( mRunningTestScript )
return mLastActiveSourceViewPanel ;
var activePanel = GetActiveDocumentPanel ( ) ;
var sourceViewPanel = activePanel as SourceViewPanel ;
if ( sourceViewPanel ! = null )
return sourceViewPanel . GetActivePanel ( ) ;
if ( ( mLastActiveSourceViewPanel ! = null ) & & ( includeLastActive ) )
return mLastActiveSourceViewPanel . GetActivePanel ( ) ;
return null ;
}
public TextPanel GetActiveTextPanel ( )
{
var activePanel = GetActivePanel ( ) ;
return activePanel as TextPanel ;
}
public void RefreshVisibleViews ( SourceViewPanel excludeSourceViewPanel = null )
{
WithSourceViewPanels ( scope ( sourceViewPanel ) = >
{
if ( ( sourceViewPanel . mParent ! = null ) & & ( sourceViewPanel ! = excludeSourceViewPanel ) )
sourceViewPanel . QueueFullRefresh ( true ) ;
} ) ;
}
public bool SaveFile ( ProjectSource projectSource )
{
if ( projectSource . mEditData . HasTextChanged ( ) )
{
for ( var user in projectSource . mEditData . mEditWidget . mEditWidgetContent . mData . mUsers )
{
user . MarkDirty ( ) ;
}
using ( mFileWatcher . mMonitor . Enter ( ) )
{
String path = scope String ( ) ;
projectSource . GetFullImportPath ( path ) ;
String text = scope String ( ) ;
projectSource . mEditData . mEditWidget . GetText ( text ) ;
2019-11-22 12:27:13 -08:00
if ( ! SafeWriteTextFile ( path , text , true , projectSource . mEditData . mLineEndingKind , scope ( outStr ) = >
{
projectSource . mEditData . BuildHash ( outStr ) ;
} ) )
{
2019-08-23 11:56:54 -07:00
return false ;
2019-11-22 12:27:13 -08:00
}
2019-08-23 11:56:54 -07:00
mFileWatcher . OmitFileChange ( path , text ) ;
projectSource . mEditData . mLastFileTextVersion = projectSource . mEditData . mEditWidget . Content . mData . mCurTextVersionId ;
#if IDE_C_SUPPORT
mDepClang . FileSaved ( path ) ;
#endif
if ( mWakaTime ! = null )
mWakaTime . QueueFile ( path , projectSource . mProject . mProjectName , true ) ;
}
}
return true ;
}
2019-11-22 12:27:13 -08:00
public bool SafeWriteTextFile ( StringView path , StringView text , bool showErrors = true , LineEndingKind lineEndingKind = . Default , delegate void ( StringView str ) strOutDlg = null )
2019-08-23 11:56:54 -07:00
{
if ( mWorkspace . IsSingleFileWorkspace )
{
if ( mWorkspace . mCompositeFile . IsIncluded ( path ) )
{
mWorkspace . mCompositeFile . Set ( path , text ) ;
return true ;
}
}
StringView useText = text ;
if ( lineEndingKind ! = . Lf )
{
var str = scope : : String ( ) . . Append ( text ) ;
if ( lineEndingKind = = . Cr )
str . Replace ( '\n' , '\r' ) ;
else
str . Replace ( "\n" , "\r\n" ) ;
useText = str ;
}
if ( Utils . WriteTextFile ( path , useText ) case . Err )
{
if ( gApp . mSettings . mEditorSettings . mPerforceAutoCheckout )
mSourceControl . Checkout ( path ) ;
Thread . Sleep ( 10 ) ;
if ( Utils . WriteTextFile ( path , useText ) case . Err )
{
Thread . Sleep ( 100 ) ;
if ( Utils . WriteTextFile ( path , useText ) case . Err )
{
if ( showErrors )
Fail ( StackStringFormat ! ( "Failed to write file '{0}'" , path ) ) ;
return false ;
}
}
}
2019-11-22 12:27:13 -08:00
if ( strOutDlg ! = null )
strOutDlg ( useText ) ;
2019-08-23 11:56:54 -07:00
return true ;
}
public Result < void , FileError > LoadTextFile ( String fileName , String outBuffer , bool autoRetry = true , delegate void ( ) onPreFilter = null )
{
if ( mWorkspace . IsSingleFileWorkspace )
{
if ( mWorkspace . mCompositeFile . IsIncluded ( fileName ) )
{
mWorkspace . mCompositeFile . Get ( fileName , outBuffer ) ;
if ( onPreFilter ! = null )
onPreFilter ( ) ;
return . Ok ;
}
}
return Utils . LoadTextFile ( fileName , outBuffer , autoRetry , onPreFilter ) ;
}
public bool SaveFileAs ( SourceViewPanel sourceViewPanel )
{
#if ! CLI
SaveFileDialog dialog = scope . ( ) ;
//dialog.ValidateNames = true;
if ( sourceViewPanel . mFilePath ! = null )
{
String ext = scope . ( ) ;
Path . GetExtension ( sourceViewPanel . mFilePath , ext ) ;
dialog . DefaultExt = ext ;
String fileName = scope . ( ) ;
Path . GetFileName ( sourceViewPanel . mFilePath , fileName ) ;
dialog . FileName = fileName ;
}
//dialog.SetFilter("Beef projects (BeefProj.toml)|BeefProj.toml");
let activeWindow = GetActiveWindow ( ) ;
dialog . OverwritePrompt = true ;
if ( dialog . ShowDialog ( activeWindow ) . GetValueOrDefault ( ) ! = . OK )
return false ;
if ( dialog . FileNames . Count ! = 1 )
return false ;
String filePath = dialog . FileNames [ 0 ] ;
// Same path?
if ( ( sourceViewPanel . mFilePath ! = null ) & & ( Path . Equals ( filePath , sourceViewPanel . mFilePath ) ) )
return true ;
if ( ! SaveFile ( sourceViewPanel , filePath ) )
return false ;
// Kinda hacky - we lose all view information...
CloseDocument ( sourceViewPanel ) ;
ShowSourceFile ( filePath ) ;
#endif
return true ;
}
public bool SaveFile ( SourceViewPanel sourceViewPanel , String forcePath = null )
{
if ( ( sourceViewPanel . HasUnsavedChanges ( ) ) | | ( forcePath ! = null ) )
{
if ( ( forcePath = = null ) & & ( sourceViewPanel . mFilePath = = null ) )
{
return SaveFileAs ( sourceViewPanel ) ;
}
var lineEndingKind = LineEndingKind . Default ;
if ( sourceViewPanel . mEditData ! = null )
{
for ( var user in sourceViewPanel . mEditData . mEditWidget . mEditWidgetContent . mData . mUsers )
{
user . MarkDirty ( ) ;
}
lineEndingKind = sourceViewPanel . mEditData . mLineEndingKind ;
}
// Lock file watcher to synchronize the 'file changed' notification so we don't
// think a file was externally saved
using ( mFileWatcher . mMonitor . Enter ( ) )
{
String path = forcePath ? ? sourceViewPanel . mFilePath ;
String text = scope String ( ) ;
sourceViewPanel . mEditWidget . GetText ( text ) ;
2019-11-22 12:27:13 -08:00
if ( ! SafeWriteTextFile ( path , text , true , lineEndingKind , scope ( outStr ) = >
{
sourceViewPanel . mEditData . BuildHash ( outStr ) ;
} ) )
{
2019-08-23 11:56:54 -07:00
return false ;
2019-11-22 12:27:13 -08:00
}
2019-08-23 11:56:54 -07:00
mFileWatcher . OmitFileChange ( path , text ) ;
if ( forcePath = = null )
sourceViewPanel . FileSaved ( ) ;
#if IDE_C_SUPPORT
mDepClang . FileSaved ( path ) ;
#endif
if ( sourceViewPanel . mProjectSource ! = null )
{
if ( mWakaTime ! = null )
{
mWakaTime . QueueFile ( path , sourceViewPanel . mProjectSource . mProject . mProjectName , true ) ;
}
}
}
}
return true ;
}
public ProjectSource FindProjectItem ( ProjectFolder projectFolder , String relPath )
{
for ( var childItem in projectFolder . mChildItems )
{
ProjectSource projectSource = childItem as ProjectSource ;
if ( projectSource ! = null )
{
if ( String . Equals ( projectSource . mPath , relPath , Environment . IsFileSystemCaseSensitive ? StringComparison . Ordinal : StringComparison . OrdinalIgnoreCase ) )
return projectSource ;
}
ProjectFolder childFolder = childItem as ProjectFolder ;
if ( childFolder ! = null )
{
projectSource = FindProjectItem ( childFolder , relPath ) ;
if ( projectSource ! = null )
return projectSource ;
}
}
return null ;
}
public Project FindProjectByName ( String projectName )
{
for ( var project in mWorkspace . mProjects )
if ( project . mProjectName = = projectName )
return project ;
return null ;
}
public ProjectSource FindProjectSourceItem ( String filePath )
{
for ( var project in mWorkspace . mProjects )
{
String relPath = scope String ( ) ;
project . GetProjectRelPath ( filePath , relPath ) ;
var projectItem = FindProjectItem ( project . mRootFolder , relPath ) ;
if ( projectItem ! = null )
return projectItem ;
}
return null ;
}
///
void SerializeWindow ( StructuredData data , WidgetWindow window )
{
2019-09-27 13:03:47 -07:00
data . Add ( "X" , window . mNormX ) ;
data . Add ( "Y" , window . mNormY ) ;
data . Add ( "Width" , window . mNormWidth ) ;
data . Add ( "Height" , window . mNormHeight ) ;
data . Add ( "ShowKind" , window . mShowKind ) ;
2019-08-23 11:56:54 -07:00
}
void SerializeTabbedView ( StructuredData data , DarkTabbedView tabbedView , bool serializeDocs )
{
if ( tabbedView = = mActiveDocumentsTabbedView )
data . Add ( "DefaultDocumentsTabbedView" , true ) ;
data . Add ( "Type" , "TabbedView" ) ;
using ( data . CreateArray ( "Tabs" ) )
{
for ( var tabWidget in tabbedView . mTabs )
{
if ( ! serializeDocs )
{
if ( tabWidget . mContent is SourceViewPanel )
continue ;
2019-09-07 06:40:03 -07:00
if ( tabWidget . mContent is DisassemblyPanel )
continue ;
2019-09-23 09:41:21 -07:00
if ( tabWidget . mContent is WelcomePanel )
continue ;
2019-08-23 11:56:54 -07:00
}
using ( data . CreateObject ( ) )
{
2019-09-23 09:41:21 -07:00
var panel = tabWidget . mContent as Panel ;
if ( ! panel . WantsSerialization )
continue ;
2019-08-23 11:56:54 -07:00
if ( tabWidget . mIsActive )
data . Add ( "Active" , true ) ;
data . Add ( "TabLabel" , tabWidget . mLabel ) ;
data . Add ( "TabWidth" , tabWidget . mWantWidth / DarkTheme . sScale ) ;
if ( var watchPanel = tabWidget . mContent as WatchPanel )
{
watchPanel . Serialize ( data , serializeDocs ) ;
}
2019-09-23 09:41:21 -07:00
else if ( panel ! = null )
2019-08-23 11:56:54 -07:00
{
panel . Serialize ( data ) ;
}
else
{
var innerTabbedView = tabWidget . mContent as DarkTabbedView ;
if ( innerTabbedView ! = null )
{
SerializeTabbedView ( data , innerTabbedView , serializeDocs ) ;
}
}
}
}
}
}
void SerializeDockingFrame ( StructuredData data , DockingFrame dockingFrame , bool serializeDocs )
{
data . Add ( "Type" , "DockingFrame" ) ;
data . Add ( "SplitType" , ( int32 ) dockingFrame . mSplitType ) ;
using ( data . CreateArray ( "DockedWidgets" ) )
{
for ( var dockedWidget in dockingFrame . mDockedWidgets )
{
using ( data . CreateObject ( ) )
{
if ( dockedWidget . mIsFillWidget )
data . Add ( "IsFillWidget" , true ) ;
if ( ! dockedWidget . mAutoClose )
data . Add ( "Permanent" , true ) ;
data . Add ( "RequestedWidth" , dockedWidget . mRequestedWidth ) ;
data . Add ( "RequestedHeight" , dockedWidget . mRequestedHeight ) ;
data . ConditionalAdd ( "SizePriority" , dockedWidget . mSizePriority , 0 ) ;
if ( dockedWidget is DarkDockingFrame )
{
var innerDockingFrame = ( DarkDockingFrame ) dockedWidget ;
SerializeDockingFrame ( data , innerDockingFrame , serializeDocs ) ;
}
if ( dockedWidget is DarkTabbedView )
{
var tabbedView = ( DarkTabbedView ) dockedWidget ;
SerializeTabbedView ( data , tabbedView , serializeDocs ) ;
}
}
}
}
}
bool SaveDefaultLayoutData ( )
{
2019-09-23 14:55:26 -07:00
if ( mMainWindow = = null )
return true ;
2019-08-23 11:56:54 -07:00
StructuredData sd = scope StructuredData ( ) ;
sd . CreateNew ( ) ;
sd . Add ( "FileVersion" , 1 ) ;
using ( sd . CreateObject ( "MainWindow" ) )
{
SerializeWindow ( sd , mMainWindow ) ;
}
using ( sd . CreateObject ( "MainDockingFrame" ) )
{
SerializeDockingFrame ( sd , mDockingFrame , false ) ;
}
String projectUserFileName = scope String ( ) ;
GetDefaultLayoutDataFileName ( projectUserFileName ) ;
String dataStr = scope String ( ) ;
sd . ToTOML ( dataStr ) ;
return SafeWriteTextFile ( projectUserFileName , dataStr , true ) ;
}
bool LoadDefaultLayoutData ( )
{
String projectUserFileName = scope String ( ) ;
GetDefaultLayoutDataFileName ( projectUserFileName ) ;
StructuredData sd = scope . ( ) ;
if ( sd . Load ( projectUserFileName ) case . Err )
return false ;
return LoadWorkspaceUserData ( sd ) ;
}
void SaveWorkspaceUserData ( StructuredData sd )
{
sd . Add ( "FileVersion" , 1 ) ;
sd . Add ( "LastConfig" , mConfigName ) ;
sd . Add ( "LastPlatform" , mPlatformName ) ;
using ( sd . CreateObject ( "MainWindow" ) )
{
2020-01-12 09:21:50 -08:00
if ( mMainWindow ! = null )
SerializeWindow ( sd , mMainWindow ) ;
else
{
sd . Add ( "X" , mRequestedWindowRect . mX ) ;
sd . Add ( "Y" , mRequestedWindowRect . mY ) ;
sd . Add ( "Width" , mRequestedWindowRect . mWidth ) ;
sd . Add ( "Height" , mRequestedWindowRect . mHeight ) ;
sd . Add ( "ShowKind" , mRequestedShowKind ) ;
}
2019-08-23 11:56:54 -07:00
}
using ( sd . CreateObject ( "MainDockingFrame" ) )
{
SerializeDockingFrame ( sd , mDockingFrame , true ) ;
}
using ( sd . CreateArray ( "RecentFilesList" ) )
{
for ( var recentFile in mRecentlyDisplayedFiles )
sd . Add ( recentFile ) ;
}
2019-10-01 12:46:38 -07:00
using ( sd . CreateArray ( "UserPlatforms" ) )
{
for ( var platformName in gApp . mWorkspace . mUserPlatforms )
sd . Add ( platformName ) ;
}
2019-08-23 11:56:54 -07:00
using ( sd . CreateArray ( "Breakpoints" ) )
{
for ( var breakpoint in mDebugger . mBreakpointList )
{
if ( ( breakpoint . mFileName ! = null ) | | ( breakpoint . mIsMemoryBreakpoint ) | | ( breakpoint . mSymbol ! = null ) )
{
using ( sd . CreateObject ( ) )
{
if ( breakpoint . mFileName ! = null )
{
sd . Add ( "File" , breakpoint . mFileName ) ;
sd . Add ( "Line" , breakpoint . mLineNum ) ;
sd . Add ( "Column" , breakpoint . mColumn ) ;
if ( breakpoint . mInstrOffset ! = - 1 )
sd . Add ( "InstrOffset" , breakpoint . mInstrOffset ) ;
}
if ( breakpoint . mSymbol ! = null )
sd . Add ( "Symbol" , breakpoint . mSymbol ) ;
if ( breakpoint . mIsMemoryBreakpoint )
sd . Add ( "MemoryWatchExpression" , breakpoint . mMemoryWatchExpression ) ;
if ( breakpoint . mCondition ! = null )
sd . Add ( "Condition" , breakpoint . mCondition ) ;
if ( breakpoint . mLogging ! = null )
sd . Add ( "Logging" , breakpoint . mLogging ) ;
sd . ConditionalAdd ( "BreakAfterLogging" , breakpoint . mBreakAfterLogging , false ) ;
sd . ConditionalAdd ( "HitCountBreak" , breakpoint . mHitCountBreakKind , . None ) ;
sd . ConditionalAdd ( "HitCountTarget" , breakpoint . mHitCountTarget , 0 ) ;
if ( breakpoint . mDisabled )
sd . Add ( "Disabled" , true ) ;
if ( breakpoint . mThreadId ! = - 1 )
sd . Add ( "HasThreadId" , true ) ;
}
}
}
}
using ( sd . CreateArray ( "Bookmarks" ) )
{
for ( var bookmark in mBookmarkManager . mBookmarkList )
{
if ( bookmark . mFileName ! = null )
{
using ( sd . CreateObject ( ) )
{
sd . Add ( "File" , bookmark . mFileName ) ;
sd . Add ( "Line" , bookmark . mLineNum ) ;
sd . Add ( "Column" , bookmark . mColumn ) ;
}
}
}
}
using ( sd . CreateObject ( "DebuggerDisplayTypes" ) )
{
var displayTypeNames = scope String ( ) ;
mDebugger . GetDisplayTypeNames ( displayTypeNames ) ;
var referenceIds = String . StackSplit ! ( displayTypeNames , '\n' ) ;
for ( var referenceId in referenceIds )
{
if ( ! referenceId . StartsWith ( "0" , StringComparison . Ordinal ) )
{
DebugManager . IntDisplayType intDisplayType ;
DebugManager . MmDisplayType mmDisplayType ;
mDebugger . GetDisplayTypes ( referenceId , out intDisplayType , out mmDisplayType ) ;
using ( sd . CreateObject ( referenceId ) )
{
sd . Add ( "IntDisplayType" , intDisplayType ) ;
sd . Add ( "MmDisplayType" , mmDisplayType ) ;
}
}
}
}
using ( sd . CreateArray ( "StepFilters" ) )
{
for ( var stepFilter in mDebugger . mStepFilterList . Values )
{
if ( stepFilter . mIsGlobal )
continue ;
if ( stepFilter . mKind = = . Filtered )
sd . Add ( stepFilter . mFilter ) ;
}
sd . RemoveIfEmpty ( ) ;
}
using ( sd . CreateArray ( "StepNotFilters" ) )
{
for ( var stepFilter in mDebugger . mStepFilterList . Values )
{
if ( stepFilter . mIsGlobal )
continue ;
if ( stepFilter . mKind = = . NotFiltered )
sd . Add ( stepFilter . mFilter ) ;
}
sd . RemoveIfEmpty ( ) ;
}
}
bool SaveWorkspaceUserData ( bool showErrors = true )
{
2019-09-05 08:18:24 -07:00
// Don't save if we didn't finish creating the workspace
if ( mWorkspace . mNeedsCreate )
return false ;
2019-08-23 11:56:54 -07:00
if ( mWorkspace . IsDebugSession )
{
bool hasUnsavedProjects = false ;
for ( let project in mWorkspace . mProjects )
if ( project . mHasChanged )
hasUnsavedProjects = true ;
// If we purposely abandoned changes then don't save now
if ( ! hasUnsavedProjects )
SaveDebugSession ( ) ;
return true ;
}
StructuredData sd = scope StructuredData ( ) ;
sd . CreateNew ( ) ;
SaveWorkspaceUserData ( sd ) ;
String projectUserFileName = scope String ( ) ;
GetWorkspaceUserDataFileName ( projectUserFileName ) ;
String jsonString = scope String ( ) ;
sd . ToTOML ( jsonString ) ;
if ( projectUserFileName . IsEmpty )
return false ;
return SafeWriteTextFile ( projectUserFileName , jsonString , showErrors ) ;
}
bool GetWorkspaceUserDataFileName ( String outResult )
{
if ( mWorkspace . mDir = = null )
return false ;
if ( mWorkspace . mCompositeFile ! = null )
{
outResult . Append ( mWorkspace . mCompositeFile . mFilePath , ".bfuser" ) ;
}
else
{
outResult . Append ( mWorkspace . mDir , "/BeefSpace_User.toml" ) ;
var legacyName = scope String ( mWorkspace . mDir , "/BeefUser.toml" ) ;
if ( File . Exists ( legacyName ) )
{
File . Move ( legacyName , outResult ) . IgnoreError ( ) ;
}
}
// Temporary for legacy
if ( ! mInitialized )
{
String legacyName = scope String ( ) ;
legacyName . Append ( mWorkspace . mDir , "/" , mWorkspace . mName , ".bfuser" ) ;
if ( File . Exists ( legacyName ) )
{
File . Move ( legacyName , outResult ) . IgnoreError ( ) ;
File . Delete ( legacyName ) . IgnoreError ( ) ;
}
}
return true ;
}
void GetDefaultLayoutDataFileName ( String outResult )
{
outResult . Append ( mInstallDir , "/DefaultLayout.toml" ) ;
}
bool GetWorkspaceFileName ( String outResult )
{
if ( mWorkspace . mDir = = null )
return false ;
//LEGACY:
/ * if ( ! mInitialized )
{
outResult . Append ( mWorkspace . mDir , "/" , mWorkspace . mName , ".bfspace" ) ;
if ( File . Exists ( outResult ) )
return true ;
outResult . Clear ( ) ;
} * /
outResult . Append ( mWorkspace . mDir , "/BeefSpace.toml" ) ;
IDEUtils . FixFilePath ( outResult ) ;
return true ;
}
///
bool SaveWorkspace ( )
{
2019-11-30 13:28:40 -08:00
if ( mWorkspace . mNeedsCreate )
mWorkspace . mNeedsCreate = false ;
2019-08-23 11:56:54 -07:00
if ( ! mWorkspace . IsSingleFileWorkspace )
{
#if ! CLI
if ( mWorkspace . mDir = = null )
{
let activeWindow = GetActiveWindow ( ) ;
FolderBrowserDialog folderDialog = scope FolderBrowserDialog ( ) ;
//folderDialog.SelectedPath = fullDir;
if ( activeWindow ! = null )
activeWindow . PreModalChild ( ) ;
if ( folderDialog . ShowDialog ( gApp . GetActiveWindow ( ) ) . GetValueOrDefault ( ) ! = . OK )
return false ;
mWorkspace . mDir = new String ( folderDialog . SelectedPath ) ;
String workspaceFileName = scope . ( ) ;
GetWorkspaceFileName ( workspaceFileName ) ;
if ( File . Exists ( workspaceFileName ) )
{
Fail ( scope String ( ) . . AppendF ( "A Beef workspace already exists at '{0}'" , mWorkspace . mDir ) ) ;
DeleteAndNullify ! ( mWorkspace . mDir ) ;
return false ;
}
}
#endif
if ( Directory . CreateDirectory ( mWorkspace . mDir ) case . Err )
{
Fail ( StackStringFormat ! ( "Failed to create workspace directory '{0}'" , mWorkspace . mDir ) ) ;
return false ;
}
}
StructuredData data = scope StructuredData ( ) ;
data . CreateNew ( ) ;
mWorkspace . Serialize ( data ) ;
String tomlString = scope String ( ) ;
data . ToTOML ( tomlString ) ;
if ( ! mWorkspace . IsSingleFileWorkspace )
{
String workspaceFileName = scope String ( ) ;
GetWorkspaceFileName ( workspaceFileName ) ;
if ( ! SafeWriteTextFile ( workspaceFileName , tomlString ) )
{
Fail ( StackStringFormat ! ( "Failed to write workspace file '{0}'" , workspaceFileName ) ) ;
return false ;
}
}
else
{
// If it's just the FileVersion then don't save anything...
/ * if ( tomlString . Count ( '\n' ) < 2 )
tomlString . Clear ( ) ; * /
mWorkspace . mCompositeFile . Set ( "Workspace" , tomlString ) ;
}
mWorkspace . mHasChanged = false ;
MarkDirty ( ) ;
return true ;
}
bool SaveDebugSession ( )
{
let project = mWorkspace . mProjects [ 0 ] ;
#if ! CLI
if ( project . mProjectPath . IsEmpty )
{
SaveFileDialog dialog = scope . ( ) ;
let activeWindow = GetActiveWindow ( ) ;
2019-08-27 08:04:41 -07:00
let workspaceOptions = GetCurWorkspaceOptions ( ) ;
2019-08-23 11:56:54 -07:00
let options = GetCurProjectOptions ( project ) ;
if ( ! options . mDebugOptions . mCommand . IsWhiteSpace )
{
2019-08-27 08:04:41 -07:00
String execCmd = scope . ( ) ;
2019-10-14 17:49:10 -07:00
ResolveConfigString ( mPlatformName , workspaceOptions , project , options , options . mDebugOptions . mCommand , "command" , execCmd ) ;
2019-08-27 08:04:41 -07:00
2019-08-23 11:56:54 -07:00
String initialDir = scope . ( ) ;
2019-08-27 08:04:41 -07:00
Path . GetDirectoryPath ( execCmd , initialDir ) ;
2019-08-23 11:56:54 -07:00
dialog . InitialDirectory = initialDir ;
dialog . SetFilter ( "Debug Session (*.bfdbg)|*.bfdbg" ) ;
dialog . DefaultExt = ".bfdbg" ;
String fileName = scope . ( ) ;
2019-08-27 08:04:41 -07:00
Path . GetFileNameWithoutExtension ( execCmd , fileName ) ;
2019-08-23 11:56:54 -07:00
if ( ! fileName . IsEmpty )
{
fileName . Append ( ".bfdbg" ) ;
dialog . FileName = fileName ;
}
}
dialog . OverwritePrompt = true ;
if ( dialog . ShowDialog ( activeWindow ) . GetValueOrDefault ( ) ! = . OK )
return false ;
project . mProjectPath . Set ( dialog . FileNames [ 0 ] ) ;
}
#endif
if ( project . mProjectPath . IsEmpty )
return false ;
StructuredData sd = scope StructuredData ( ) ;
sd . CreateNew ( ) ;
SaveWorkspaceUserData ( sd ) ;
using ( sd . CreateObject ( "DebugSession" ) )
{
project . Serialize ( sd ) ;
}
String jsonString = scope String ( ) ;
sd . ToTOML ( jsonString ) ;
if ( ! SafeWriteTextFile ( project . mProjectPath , jsonString , true ) )
return false ;
project . mHasChanged = false ;
MarkDirty ( ) ;
return true ;
}
void LoadDebugSession ( )
{
/ * String path = scope String ( ) ;
if ( ! GetWorkspaceUserDataFileName ( path ) )
return false ;
var data = scope StructuredData ( ) ;
if ( data . Load ( path ) case . Err )
return false ;
if ( ! LoadWorkspaceUserData ( data ) )
return false ; * /
}
public void AddProjectToWorkspace ( Project project , bool addToProjectList = true )
{
if ( addToProjectList )
mWorkspace . mProjects . Add ( project ) ;
mBfBuildSystem . AddProject ( project ) ;
#if ! CLI
if ( mBfResolveSystem ! = null )
mBfResolveSystem . AddProject ( project ) ;
#endif
mWorkspace . ClearProjectNameCache ( ) ;
}
public void AddNewProjectToWorkspace ( Project project , VerSpecRecord verSpec = null )
{
AddProjectToWorkspace ( project ) ;
mWorkspace . SetChanged ( ) ;
var relPath = scope String ( ) ;
Path . GetRelativePath ( project . mProjectPath , mWorkspace . mDir , relPath ) ;
relPath . Replace ( "\\" , "/" ) ;
int lastSlash = relPath . LastIndexOf ( '/' ) ;
if ( lastSlash ! = - 1 )
relPath . RemoveToEnd ( lastSlash ) ;
/ * var endStr = "/BeefProj.toml" ;
if ( relPath . EndsWith ( endStr ) )
relPath . RemoveToEnd ( relPath . Length - endStr . Length ) ; * /
var projectSpec = new Workspace . ProjectSpec ;
projectSpec . mProjectName = new . ( project . mProjectName ) ;
if ( verSpec ! = null )
{
projectSpec . mVerSpec = verSpec ;
}
else
{
projectSpec . mVerSpec = new . ( ) ;
projectSpec . mVerSpec . SetPath ( relPath ) ;
}
mWorkspace . mProjectSpecs . Add ( projectSpec ) ;
var dep = new Project . Dependency ( ) ;
dep . mProjectName = new . ( "corlib" ) ;
dep . mVerSpec = new . ( ) ;
dep . mVerSpec . SetSemVer ( "*" ) ;
project . mDependencies . Add ( dep ) ;
for ( var checkProject in mWorkspace . mProjects )
{
int idx = checkProject . mDependencies . FindIndex ( scope ( dep ) = > dep . mProjectName = = project . mProjectName ) ;
if ( idx ! = - 1 )
ProjectOptionsChanged ( checkProject ) ;
}
ProjectOptionsChanged ( project , false ) ;
}
2019-09-05 08:18:24 -07:00
public Project CreateProject ( String projName , String projDir , Project . TargetType targetType )
2019-08-23 11:56:54 -07:00
{
Project project = new Project ( ) ;
project . mProjectName . Set ( projName ) ;
project . mProjectPath . Set ( projDir ) ;
Utils . GetDirWithSlash ( project . mProjectPath ) ;
project . mProjectPath . Append ( "BeefProj.toml" ) ;
project . mProjectDir . Set ( projDir ) ;
project . mGeneralOptions . mTargetType = targetType ;
project . SetupDefault ( ) ;
project . SetChanged ( ) ;
AddNewProjectToWorkspace ( project ) ;
project . FinishCreate ( ) ;
mProjectPanel . InitProject ( project ) ;
mProjectPanel . Sort ( ) ;
mWorkspace . FixOptions ( ) ;
mWorkspace . mHasChanged = true ;
mWorkspace . ClearProjectNameCache ( ) ;
CurrentWorkspaceConfigChanged ( ) ;
2019-09-05 08:18:24 -07:00
return project ;
2019-08-23 11:56:54 -07:00
}
void StopDebugging ( )
{
if ( mDebugger . mIsRunning )
{
mDebugger . StopDebugging ( ) ;
while ( mDebugger . GetRunState ( ) ! = . Terminated )
{
mDebugger . Update ( ) ;
}
mDebugger . mIsRunning = false ;
mExecutionPaused = false ;
}
mDebugger . DisposeNativeBreakpoints ( ) ;
mWantsRehupCallstack = false ;
}
void CloseWorkspace ( )
{
StopDebugging ( ) ;
mDebugger . Reset ( ) ;
WithWatchPanels ( scope ( watchPanel ) = >
{
watchPanel . Reset ( ) ;
} ) ;
mMemoryPanel . MarkViewDirty ( ) ;
mCallStackPanel . MarkCallStackDirty ( ) ;
mThreadPanel . MarkThreadsDirty ( ) ;
if ( mBfResolveCompiler ! = null )
{
mBfResolveCompiler . RequestCancelBackground ( ) ;
mBfResolveCompiler . CancelBackground ( ) ;
delete mBfResolveCompiler ;
delete mBfResolveSystem ;
delete mBfResolveHelper ;
}
mBfBuildCompiler . RequestCancelBackground ( ) ;
mBfBuildCompiler . CancelBackground ( ) ;
delete mBfBuildCompiler ;
delete mBfBuildSystem ;
if ( ! mNoResolve )
{
mBfResolveSystem = new BfSystem ( ) ;
mBfResolveCompiler = mBfResolveSystem . CreateCompiler ( true ) ;
mBfResolveHelper = new BfResolveHelper ( ) ;
}
mCompileSinceCleanCount = 0 ;
mBfBuildSystem = new BfSystem ( ) ;
mBfBuildCompiler = mBfBuildSystem . CreateCompiler ( false ) ;
mBfBuildCompiler . ClearBuildCache ( ) ;
/ * var docPanels = scope List < Widget > ( ) ;
WithTabs ( scope [ & ] ( tab ) = >
{
var sourceViewPanel = tab . mContent as SourceViewPanel ;
if ( sourceViewPanel ! = null )
{
docPanels . Add ( sourceViewPanel ) ;
}
} ) ;
for ( var docPanel in docPanels )
CloseDocument ( docPanel ) ; * /
while ( mWindows . Count > 1 )
mWindows . Back . Close ( true ) ;
void ResetPanel ( Widget widget )
{
if ( widget . mParent ! = null )
widget . RemoveSelf ( ) ;
}
if ( ! mRunningTestScript )
{
mActiveDocumentsTabbedView = null ;
2020-01-12 09:21:50 -08:00
WithStandardPanels ( scope ( panel ) = >
{
ResetPanel ( panel ) ;
} ) ;
2019-08-23 11:56:54 -07:00
mMainFrame . Reset ( ) ;
}
mGlobalUndoManager . Clear ( ) ;
mHaveSourcesChangedExternallySinceLastCompile = false ;
mHaveSourcesChangedInternallySinceLastCompile = false ;
mIsImmediateDebugExprEval = false ;
//mActiveDocumentsTabbedView;
if ( mConfigName . IsEmpty )
mConfigName . Set ( "Debug" ) ;
if ( mPlatformName . IsEmpty )
mPlatformName . Set ( sPlatform64Name ) ;
mDockingFrame = mMainFrame . mDockingFrame ;
//mMainFrame.AddedToParent;
delete mWorkspace ;
mWorkspace = new Workspace ( ) ;
2019-09-18 08:13:00 -07:00
2020-01-12 09:21:50 -08:00
mErrorsPanel . Clear ( ) ;
2019-09-18 08:13:00 -07:00
OutputLine ( "Workspace closed." ) ;
2019-08-23 11:56:54 -07:00
}
void FinishShowingNewWorkspace ( bool loadUserData = true )
{
if ( ( loadUserData ) & & ( ! mRunningTestScript ) )
{
if ( ! LoadWorkspaceUserData ( ) )
2019-09-07 06:40:03 -07:00
{
2019-08-23 11:56:54 -07:00
CreateDefaultLayout ( ) ;
2019-09-07 06:40:03 -07:00
}
2019-08-23 11:56:54 -07:00
}
WorkspaceLoaded ( ) ;
UpdateTitle ( ) ;
UpdateRecentDisplayedFilesMenuItems ( ) ;
mProjectPanel . RebuildUI ( ) ;
ShowPanel ( mOutputPanel , false ) ;
mMainFrame . RehupSize ( ) ;
2019-09-07 06:40:03 -07:00
ShowStartupFile ( ) ;
2019-08-23 11:56:54 -07:00
}
void CloseWorkspaceAndSetupNew ( )
{
CloseWorkspace ( ) ;
FinishShowingNewWorkspace ( ) ;
}
// TryCloseWorkspaceAndSetupNew
[IDECommand]
void Cmd_CloseWorkspaceAndSetupNew ( )
{
bool done = CheckCloseWorkspace ( mMainWindow ,
new ( ) = >
{
// We use a close delay after saving so the user can see we actually saved before closing down
if ( SaveAll ( ) )
{
CloseWorkspaceAndSetupNew ( ) ;
}
} ,
new ( ) = >
{
CloseWorkspaceAndSetupNew ( ) ;
} , null ) ;
if ( done )
{
CloseWorkspaceAndSetupNew ( ) ;
}
//CloseWorkspace();
//FinishShowingNewWorkspace();
}
public Result < void , StructuredData . Error > StructuredLoad ( StructuredData data , StringView filePath )
{
if ( mWorkspace . IsSingleFileWorkspace )
{
String dataStr = scope . ( ) ;
mWorkspace . mCompositeFile . Get ( filePath , dataStr ) ;
Try ! ( data . LoadFromString ( dataStr ) ) ;
return . Ok ;
}
return data . Load ( filePath ) ;
}
public Result < void > StructuredSave ( StringView filePath , StringView contents )
{
if ( mWorkspace . IsSingleFileWorkspace )
{
mWorkspace . mCompositeFile . Set ( filePath , contents ) ;
return . Ok ;
}
if ( gApp . SafeWriteTextFile ( filePath , contents ) )
return . Ok ;
else
return . Err ;
}
2019-12-01 10:19:00 -08:00
void FlushDeferredLoadProjects ( )
{
while ( true )
{
bool hadLoad = false ;
for ( int projectIdx = 0 ; projectIdx < mWorkspace . mProjects . Count ; projectIdx + + )
{
var project = mWorkspace . mProjects [ projectIdx ] ;
if ( project . mLoadDeferred )
{
hadLoad = true ;
var projectPath = project . mProjectPath ;
if ( ! project . Load ( projectPath ) )
{
OutputErrorLine ( "Failed to load project '{0}' from '{1}'" , project . mProjectName , projectPath ) ;
LoadFailed ( ) ;
project . mFailed = true ;
}
AddProjectToWorkspace ( project , false ) ;
}
}
if ( ! hadLoad )
break ;
}
}
2019-09-05 08:18:24 -07:00
protected void LoadWorkspace ( BeefVerb verb )
2019-08-23 11:56:54 -07:00
{
scope AutoBeefPerf ( "IDEApp.LoadWorkspace" ) ;
AddRecentFile ( . OpenedWorkspace , mWorkspace . mDir ) ;
StructuredData data = null ;
String workspaceFileName = scope String ( ) ;
if ( mWorkspace . IsSingleFileWorkspace )
{
if ( mWorkspace . mCompositeFile . Load ( ) case . Err )
{
OutputErrorLine ( "Failed to load workspace '{0}'" , mWorkspace . mCompositeFile . FilePath ) ;
}
workspaceFileName . Append ( "Workspace" ) ;
}
else
GetWorkspaceFileName ( workspaceFileName ) ;
data = scope StructuredData ( ) ; //.LoadFromFile(workspaceFileName).GetValueOrDefault();
LoadConfig ( ) ;
bool isNew = false ;
bool wantSave = false ;
if ( StructuredLoad ( data , workspaceFileName ) case . Err ( let err ) )
{
2019-10-04 10:39:25 -07:00
mBeefConfig . Refresh ( ) ;
2019-08-23 11:56:54 -07:00
switch ( err )
{
case . FormatError ( int lineNum ) :
OutputLineSmart ( "ERROR: Workspace format error in '{0}' on line {1}" , workspaceFileName , lineNum ) ;
LoadFailed ( ) ;
return ;
case . FileError : // Assume 'file not found'
2019-09-05 08:18:24 -07:00
if ( verb = = . OpenOrNew )
2019-08-23 11:56:54 -07:00
{
isNew = true ;
}
2019-09-05 08:18:24 -07:00
else if ( verb = = . New )
2019-08-23 11:56:54 -07:00
{
isNew = true ;
wantSave = true ;
}
else
{
#if CLI
OutputLineSmart ( "ERROR: Workspace '{0}' does not exist. Use the '-new' command line argument to create a new workspace." , workspaceFileName ) ;
LoadFailed ( ) ;
return ;
#endif
}
default :
OutputErrorLine ( "Failed to load workspace '{0}'" , workspaceFileName ) ;
LoadFailed ( ) ;
return ;
}
//Directory.CreateDirectory(mWorkspace.mDir).IgnoreError();
2020-01-12 09:21:50 -08:00
//int lastSlashPos = mWorkspace.mDir.LastIndexOf(IDEUtils.cNativeSlash);
String projectName = mWorkspace . mName ;
Debug . Assert ( ! projectName . IsWhiteSpace ) ;
2019-08-23 11:56:54 -07:00
String projectPath = scope String ( mWorkspace . mDir ) ;
Utils . GetDirWithSlash ( projectPath ) ;
projectPath . Append ( "BeefProj.toml" ) ;
Project project = new Project ( ) ;
mWorkspace . mProjects . Add ( project ) ;
2019-09-18 08:13:00 -07:00
project . mProjectPath . Set ( projectPath ) ;
2019-08-23 11:56:54 -07:00
if ( ! project . Load ( projectPath ) )
{
project . mBeefGlobalOptions . mDefaultNamespace . Set ( projectName ) ;
project . mBeefGlobalOptions . mStartupObject . Clear ( ) ;
project . mBeefGlobalOptions . mStartupObject . AppendF ( "{0}.Program" , projectName ) ;
project . mProjectName . Set ( projectName ) ;
project . SetupDefault ( ) ;
project . mNeedsCreate = true ;
project . mHasChanged = true ;
project . mProjectDir . Set ( mWorkspace . mDir ) ;
2019-09-19 05:34:11 -07:00
2019-09-05 08:18:24 -07:00
project . FinishCreate ( false ) ;
2019-08-23 11:56:54 -07:00
var verSpec = new VerSpecRecord ( ) ;
verSpec . SetSemVer ( "*" ) ;
switch ( AddProject ( "corlib" , verSpec ) )
{
case . Ok ( let libProject ) :
var dep = new Project . Dependency ( ) ;
dep . mProjectName = new String ( "corlib" ) ;
dep . mVerSpec = verSpec ;
project . mDependencies . Add ( dep ) ;
default :
delete verSpec ;
}
}
var projSpec = new Workspace . ProjectSpec ;
projSpec . mProjectName = new String ( project . mProjectName ) ;
projSpec . mVerSpec = new VerSpecRecord ( ) ;
projSpec . mVerSpec . SetPath ( "." ) ;
mWorkspace . mProjectSpecs . Add ( projSpec ) ;
mWorkspace . mStartupProject = project ;
mWorkspace . mHasChanged = true ;
AddProjectToWorkspace ( project , false ) ;
ShowPanel ( mOutputPanel , false ) ;
/ * var str = scope String ( ) ;
Font . StrEncodeColor ( 0xfffef860 , str ) ;
str . AppendF ( "Created new workspace in '{0}'" , mWorkspace . mDir ) ;
Font . StrEncodePopColor ( str ) ;
OutputLine ( str ) ; * /
2019-09-22 08:25:38 -07:00
OutputWarnLine ( "Created new workspace in '{0}'" , mWorkspace . mDir ) ;
2019-08-23 11:56:54 -07:00
if ( wantSave )
{
SaveWorkspace ( ) ;
project . Save ( ) ;
}
else
{
mWorkspace . mNeedsCreate = true ;
2019-09-22 08:25:38 -07:00
OutputLine ( "Use 'File\\Save All' to commit to disk." ) ;
2019-08-23 11:56:54 -07:00
}
}
else
{
if ( mVerb = = . New )
{
OutputLineSmart ( "ERROR: Workspace '{0}' already exists, but '-new' argument was specified." , workspaceFileName ) ;
LoadFailed ( ) ;
}
var startupProjectName = scope String ( ) ;
using ( data . Open ( "Workspace" ) )
{
data . GetString ( "StartupProject" , startupProjectName ) ;
}
if ( mWorkspace . IsSingleFileWorkspace )
{
var project = new Project ( ) ;
project . mProjectName . Set ( "Program" ) ;
project . mGeneralOptions . mTargetType = . BeefConsoleApplication ;
Path . GetDirectoryPath ( mWorkspace . mCompositeFile . FilePath , project . mProjectDir ) ;
project . DeferLoad ( "" ) ;
mWorkspace . mProjects . Add ( project ) ;
}
if ( data . Contains ( "Projects" ) )
{
for ( var projectName in data . Enumerate ( "Projects" ) )
{
var projSpec = new Workspace . ProjectSpec ;
projSpec . mProjectName = new String ( projectName ) ;
projSpec . mVerSpec = new VerSpecRecord ( ) ;
mWorkspace . mProjectSpecs . Add ( projSpec ) ;
if ( projSpec . mVerSpec . Parse ( data ) case . Err )
{
var err = scope String ( ) ;
err . AppendF ( "Unable to parse version specifier for {0} in {1}" , projectName , workspaceFileName ) ;
Fail ( err ) ;
LoadFailed ( ) ;
continue ;
}
switch ( AddProject ( projectName , projSpec . mVerSpec ) )
{
case . Ok ( let project ) :
if ( ( ! startupProjectName . IsEmpty ) & & ( StringView . Compare ( startupProjectName , projectName , true ) = = 0 ) )
{
mWorkspace . mStartupProject = project ;
}
project . mLocked = data . GetBool ( "Locked" , project . mLockedDefault ) ;
case . Err :
OutputLineSmart ( "ERROR: Unable to load project '{0}' specified in workspace" , projectName ) ;
LoadFailed ( ) ;
default :
}
}
}
mWorkspace . Deserialize ( data ) ;
}
2019-12-01 10:19:00 -08:00
FlushDeferredLoadProjects ( ) ;
2019-08-23 11:56:54 -07:00
mWorkspace . FinishDeserialize ( data ) ;
mWorkspace . FixOptions ( mConfigName , mPlatformName ) ;
#if ! CLI
if ( mBfResolveCompiler ! = null )
mBfResolveCompiler . QueueSetWorkspaceOptions ( null , 0 ) ;
#endif
MarkDirty ( ) ;
}
public void RetryProjectLoad ( Project project )
{
2019-12-01 10:19:00 -08:00
LoadConfig ( ) ;
2019-08-23 11:56:54 -07:00
var projectPath = project . mProjectPath ;
if ( ! project . Load ( projectPath ) )
{
Fail ( scope String ( ) . . AppendF ( "Failed to load project '{0}' from '{1}'" , project . mProjectName , projectPath ) ) ;
LoadFailed ( ) ;
project . mFailed = true ;
}
else
{
2019-12-01 10:19:00 -08:00
FlushDeferredLoadProjects ( ) ;
mWorkspace . FixOptions ( ) ;
2019-08-23 11:56:54 -07:00
project . mFailed = false ;
mProjectPanel . RebuildUI ( ) ;
2019-12-01 10:19:00 -08:00
CurrentWorkspaceConfigChanged ( ) ;
2019-08-23 11:56:54 -07:00
}
}
public enum ProjectAddError
{
InvalidVersion ,
InvalidVersionSpec ,
LoadFailed ,
NotFound
}
public Result < Project , ProjectAddError > AddProject ( StringView projectName , VerSpecRecord verSpecRecord )
{
VerSpecRecord useVerSpecRecord = verSpecRecord ;
String verConfigDir = mWorkspace . mDir ;
2019-12-01 10:19:00 -08:00
if ( let project = mWorkspace . FindProject ( projectName ) )
return project ;
2019-11-02 06:24:36 -07:00
if ( useVerSpecRecord . mVerSpec case . SemVer )
2019-08-23 11:56:54 -07:00
{
2019-11-02 06:24:36 -07:00
for ( int regEntryIdx = mBeefConfig . mRegistry . Count - 1 ; regEntryIdx > = 0 ; regEntryIdx - - )
2019-08-23 11:56:54 -07:00
{
2019-11-02 06:24:36 -07:00
var regEntry = mBeefConfig . mRegistry [ regEntryIdx ] ;
if ( regEntry . mProjName = = projectName )
{
useVerSpecRecord = regEntry . mLocation ;
verConfigDir = regEntry . mConfigFile . mConfigDir ;
}
2019-08-23 11:56:54 -07:00
}
}
var project = new Project ( ) ;
// For project locking, assume that only anything that is referenced with a path is editable
project . mLockedDefault = ! ( verSpecRecord . mVerSpec case . Path ) ;
project . mLocked = project . mLockedDefault ;
mWorkspace . mProjects . Add ( project ) ;
bool success = false ;
defer
{
if ( ! success )
{
mWorkspace . mProjects . Remove ( project ) ;
delete project ;
}
}
String projectFilePath = null ;
switch ( useVerSpecRecord . mVerSpec )
{
case . Path ( let path ) :
var relPath = scope String ( path ) ;
IDEUtils . FixFilePath ( relPath ) ;
if ( ! relPath . EndsWith ( IDEUtils . cNativeSlash ) )
relPath . Append ( IDEUtils . cNativeSlash ) ;
var absPath = scope String ( ) ;
Path . GetAbsolutePath ( relPath , verConfigDir , absPath ) ;
projectFilePath = scope : : String ( ) ;
projectFilePath . Append ( absPath , "BeefProj.toml" ) ;
case . SemVer ( let semVer ) :
//
default :
Fail ( "Invalid version specifier" ) ;
return . Err ( . InvalidVersionSpec ) ;
}
if ( projectFilePath = = null )
{
return . Err ( . NotFound ) ;
}
project . mProjectName . Set ( projectName ) ;
project . DeferLoad ( projectFilePath ) ;
success = true ;
2019-12-01 10:19:00 -08:00
mWorkspace . AddProjectToCache ( project ) ;
2019-08-23 11:56:54 -07:00
/ * if ( ! project . Load ( projectFilePath ) )
{
Fail ( StackStringFormat ! ( "Failed to load project {0}" , projectFilePath ) ) ;
delete project ;
return . Err ( . LoadFailed ) ;
}
success = true ;
AddProjectToWorkspace ( project , false ) ; * /
return . Ok ( project ) ;
}
protected void WorkspaceLoaded ( )
{
scope AutoBeefPerf ( "IDE.WorkspaceLoaded" ) ;
2019-09-20 09:21:29 -07:00
if ( ! Environment . IsFileSystemCaseSensitive )
{
// Make sure we have the correct actual path
String newPath = new String ( ) ;
Path . GetActualPathName ( mWorkspace . mDir , newPath ) ;
delete mWorkspace . mDir ;
mWorkspace . mDir = newPath ;
}
2019-08-23 11:56:54 -07:00
List < String > platforms = scope List < String > ( ) ;
2019-10-14 17:49:10 -07:00
if ( IDEApp . sPlatform32Name ! = null )
platforms . Add ( IDEApp . sPlatform32Name ) ;
if ( IDEApp . sPlatform64Name ! = null )
platforms . Add ( IDEApp . sPlatform64Name ) ;
2019-08-23 11:56:54 -07:00
List < String > configs = scope List < String > ( ) ;
configs . Add ( "Debug" ) ;
configs . Add ( "Release" ) ;
configs . Add ( "Paranoid" ) ;
configs . Add ( "Test" ) ;
for ( let platformName in platforms )
{
for ( let configName in configs )
{
mWorkspace . FixOptions ( configName , platformName ) ;
}
}
mWorkspace . FixOptions ( mConfigName , mPlatformName ) ;
#if ! CLI
PreConfigureBeefSystem ( mBfResolveSystem , mBfResolveCompiler ) ;
#endif
for ( var project in mWorkspace . mProjects )
{
project . mEnabled = IsProjectEnabled ( project ) ;
#if ! CLI
if ( mBfResolveSystem ! = null )
SetupBeefProjectSettings ( mBfResolveSystem , mBfResolveCompiler , project ) ;
#endif
project . mRootFolder . SortItems ( ) ;
}
if ( mWorkspace . IsSingleFileWorkspace )
{
AddToRecentDisplayedFilesList ( CompositeFile . sMainFileName ) ;
}
}
///
void DeserializeTabbedView ( StructuredData data , IDETabbedView tabbedView )
{
if ( data . GetBool ( "DefaultDocumentsTabbedView" ) )
mActiveDocumentsTabbedView = tabbedView ;
SourceViewTab activeTab = null ;
for ( data . Enumerate ( "Tabs" ) )
{
Panel panel = Panel . Create ( data ) ;
if ( panel = = null )
continue ;
Debug . Assert ( panel ! = null ) ;
bool isActive = data . GetBool ( "Active" ) ;
var newTabButton = new SourceViewTab ( ) ;
newTabButton . Label = "" ;
data . GetString ( "TabLabel" , newTabButton . mLabel ) ;
newTabButton . mOwnsContent = panel . mAutoDelete ;
newTabButton . mTabWidthOffset = panel . TabWidthOffset ;
//newTabButton.mWantWidth = (float)Math.Round(data.GetFloat("TabWidth") * DarkTheme.sScale);
newTabButton . mHeight = tabbedView . mTabHeight ;
newTabButton . mContent = panel ;
tabbedView . AddTab ( newTabButton , tabbedView . GetTabCount ( ) ) ;
newTabButton . RehupScale ( 1.0f , 1.0f ) ;
newTabButton . mCloseClickedEvent . Add ( new ( ) = > DocumentCloseClicked ( panel ) ) ;
if ( isActive )
activeTab = newTabButton ;
}
if ( activeTab ! = null )
activeTab . Activate ( false ) ;
}
void DeserializeDockingFrame ( StructuredData data , DockingFrame dockingFrame )
{
dockingFrame . mSplitType = ( DockingFrame . SplitType ) data . GetInt ( "SplitType" ) ;
for ( var _docWid in data . Enumerate ( "DockedWidgets" ) )
{
//for (int32 dockedWidgetIdx = 0; dockedWidgetIdx < data.Count; dockedWidgetIdx++)
//for (var dockedWidgetKV in data)
{
//using (data.Open(dockedWidgetIdx))
//using (data.Open(@dockedWidgetKV))
{
DockedWidget dockedWidget = null ;
IDETabbedView tabbedView = null ;
String type = scope String ( ) ;
data . GetString ( "Type" , type ) ;
if ( type = = "DockingFrame" )
{
var innerDockingFrame = new DarkDockingFrame ( ) ;
DeserializeDockingFrame ( data , innerDockingFrame ) ;
dockedWidget = innerDockingFrame ;
}
else if ( type = = "TabbedView" )
{
tabbedView = CreateTabbedView ( ) ;
DeserializeTabbedView ( data , tabbedView ) ;
dockedWidget = tabbedView ;
}
dockedWidget . mParentDockingFrame = dockingFrame ;
dockedWidget . mIsFillWidget = data . GetBool ( "IsFillWidget" ) ;
dockedWidget . mAutoClose = ! data . GetBool ( "Permanent" ) ;
if ( dockedWidget . mIsFillWidget )
dockedWidget . mHasFillWidget = true ;
if ( dockedWidget . mHasFillWidget )
dockingFrame . mHasFillWidget = true ;
if ( ( dockedWidget . mIsFillWidget ) & & ( tabbedView ! = null ) & & ( mActiveDocumentsTabbedView = = null ) )
mActiveDocumentsTabbedView = tabbedView ;
dockedWidget . mHasFillWidget = data . GetBool ( "HasFillWidget" ) ;
dockedWidget . mSizePriority = data . GetFloat ( "SizePriority" ) ;
dockedWidget . mRequestedWidth = data . GetFloat ( "RequestedWidth" ) ;
dockedWidget . mRequestedHeight = data . GetFloat ( "RequestedHeight" ) ;
dockedWidget . mWidth = dockedWidget . mRequestedWidth ;
dockedWidget . mHeight = dockedWidget . mRequestedHeight ;
dockingFrame . AddWidget ( dockedWidget ) ;
dockingFrame . mDockedWidgets . Add ( dockedWidget ) ;
}
}
}
dockingFrame . Rehup ( ) ;
dockingFrame . ResizeContent ( ) ;
}
void DeserializeWindow ( StructuredData data , WidgetWindow window )
{
int32 x = data . GetInt ( "X" ) ;
int32 y = data . GetInt ( "Y" ) ;
int32 width = data . GetInt ( "Width" ) ;
int32 height = data . GetInt ( "Height" ) ;
if ( ( width > 0 ) & & ( height > 0 ) )
2019-09-27 13:03:47 -07:00
{
2019-08-23 11:56:54 -07:00
mRequestedWindowRect = Rect ( x , y , width , height ) ;
2019-09-27 13:03:47 -07:00
}
mRequestedShowKind = data . GetEnum < BFWindow . ShowKind > ( "ShowKind" ) ;
2019-08-23 11:56:54 -07:00
}
bool LoadWorkspaceUserData ( StructuredData data )
{
String configName = scope String ( ) ;
data . GetString ( "LastConfig" , configName ) ;
if ( ! configName . IsEmpty )
{
mConfigName . Set ( configName ) ;
}
2019-10-01 12:46:38 -07:00
//
2019-08-23 11:56:54 -07:00
{
2019-10-01 12:46:38 -07:00
String platformName = scope String ( ) ;
data . GetString ( "LastPlatform" , platformName ) ;
if ( ! platformName . IsEmpty )
{
Workspace . Config config ;
mWorkspace . mConfigs . TryGetValue ( mConfigName , out config ) ;
if ( config ! = null )
{
if ( Utils . Contains ( config . mPlatforms . Keys , platformName ) )
mPlatformName . Set ( platformName ) ;
}
}
2019-08-23 11:56:54 -07:00
}
using ( data . Open ( "MainWindow" ) )
DeserializeWindow ( data , mMainWindow ) ;
if ( mMainWindow = = null )
mMainFrame . Resize ( 0 , 0 , mRequestedWindowRect . mWidth , mRequestedWindowRect . mHeight ) ;
using ( data . Open ( "MainDockingFrame" ) )
DeserializeDockingFrame ( data , mDockingFrame ) ;
DeleteAndClearItems ! ( mRecentlyDisplayedFiles ) ;
for ( data . Enumerate ( "RecentFilesList" ) )
{
String fileStr = new String ( ) ;
data . GetCurString ( fileStr ) ;
IDEUtils . FixFilePath ( fileStr ) ;
mRecentlyDisplayedFiles . Add ( fileStr ) ;
}
2019-10-01 12:46:38 -07:00
DeleteAndClearItems ! ( gApp . mWorkspace . mUserPlatforms ) ;
for ( data . Enumerate ( "UserPlatforms" ) )
{
String platformName = scope String ( ) ;
data . GetCurString ( platformName ) ;
if ( ! gApp . mWorkspace . mUserPlatforms . Contains ( platformName ) )
{
gApp . mWorkspace . mUserPlatforms . Add ( new String ( platformName ) ) ;
gApp . mWorkspace . FixOptionsForPlatform ( platformName ) ;
}
}
2019-08-23 11:56:54 -07:00
for ( var _breakpoint in data . Enumerate ( "Breakpoints" ) )
{
String fileName = scope String ( ) ;
data . GetString ( "File" , fileName ) ;
IDEUtils . FixFilePath ( fileName ) ;
int32 lineNum = data . GetInt ( "Line" ) ;
int32 column = data . GetInt ( "Column" ) ;
int32 instrOffset = data . GetInt ( "InstrOffset" , - 1 ) ;
String memoryWatchExpression = scope String ( ) ;
data . GetString ( "MemoryWatchExpression" , memoryWatchExpression ) ;
Breakpoint breakpoint = null ;
if ( memoryWatchExpression . Length > 0 )
breakpoint = mDebugger . CreateMemoryBreakpoint ( memoryWatchExpression , ( int ) 0 , 0 , null ) ;
else if ( fileName . Length > 0 )
breakpoint = mDebugger . CreateBreakpoint ( fileName , lineNum , column , instrOffset ) ;
else
{
String symbol = scope . ( ) ;
data . GetString ( "Symbol" , symbol ) ;
if ( ! symbol . IsEmpty )
breakpoint = mDebugger . CreateSymbolBreakpoint ( symbol ) ;
}
if ( breakpoint ! = null )
{
String condition = scope String ( ) ;
data . GetString ( "Condition" , condition ) ;
if ( condition . Length > 0 )
breakpoint . SetCondition ( condition ) ;
let logging = scope String ( ) ;
data . GetString ( "Logging" , logging ) ;
bool breakAfterLogging = data . GetBool ( "BreakAfterLogging" ) ;
breakpoint . SetLogging ( logging , breakAfterLogging ) ;
let hitCountBreakKind = data . GetEnum < Breakpoint . HitCountBreakKind > ( "HitCountBreak" ) ;
int hitCountTarget = data . GetInt ( "HitCountTarget" ) ;
breakpoint . SetHitCountTarget ( hitCountTarget , hitCountBreakKind ) ;
if ( data . GetBool ( "Disabled" ) )
mDebugger . SetBreakpointDisabled ( breakpoint , true ) ;
if ( data . GetBool ( "HasThreadId" ) )
breakpoint . SetThreadId ( 0 ) ;
}
}
for ( var _bookmark in data . Enumerate ( "Bookmarks" ) )
{
String fileName = scope String ( ) ;
data . GetString ( "File" , fileName ) ;
IDEUtils . FixFilePath ( fileName ) ;
int32 lineNum = data . GetInt ( "Line" ) ;
int32 column = data . GetInt ( "Column" ) ;
mBookmarkManager . CreateBookmark ( fileName , lineNum , column ) ;
}
for ( var referenceId in data . Enumerate ( "DebuggerDisplayTypes" ) )
{
var referenceIdStr = scope String ( referenceId ) ;
if ( referenceIdStr . Length = = 0 )
referenceIdStr = null ;
var intDisplayType = data . GetEnum < DebugManager . IntDisplayType > ( "IntDisplayType" ) ;
var mmDisplayType = data . GetEnum < DebugManager . MmDisplayType > ( "MmDisplayType" ) ;
mDebugger . SetDisplayTypes ( referenceIdStr , intDisplayType , mmDisplayType ) ;
}
for ( data . Enumerate ( "StepFilters" ) )
{
String filter = scope String ( ) ;
data . GetCurString ( filter ) ;
if ( ! filter . IsEmpty )
mDebugger . CreateStepFilter ( filter , false , . Filtered ) ;
}
for ( data . Enumerate ( "StepNotFilters" ) )
{
String filter = scope String ( ) ;
data . GetCurString ( filter ) ;
if ( ! filter . IsEmpty )
mDebugger . CreateStepFilter ( filter , false , . NotFiltered ) ;
}
return true ;
}
bool LoadWorkspaceUserData ( )
{
scope AutoBeefPerf ( "IDEApp.LoadWorkspaceUserData" ) ;
//return false;
String path = scope String ( ) ;
if ( ! GetWorkspaceUserDataFileName ( path ) )
return false ;
var data = scope StructuredData ( ) ;
if ( data . Load ( path ) case . Err )
return false ;
if ( ! LoadWorkspaceUserData ( data ) )
return false ;
return true ;
}
///
public void RehupStepFilters ( )
{
mDebugger . SetStepOverExternalFiles ( mStepOverExternalFiles ) ;
}
public void SaveClangFiles ( )
{
WithSourceViewPanels ( scope ( sourceViewPanel ) = >
{
if ( sourceViewPanel . mIsClang )
SaveFile ( sourceViewPanel ) ;
} ) ;
}
[IDECommand]
public void SaveFile ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
SaveFile ( sourceViewPanel ) ;
}
[IDECommand]
public void SaveAs ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
SaveFileAs ( sourceViewPanel ) ;
}
}
[IDECommand]
public void OpenWorkspace ( )
{
mDeferredOpen = . Workspace ;
}
void NewDebugSession ( bool fromLoad )
{
if ( ! fromLoad )
CloseWorkspaceAndSetupNew ( ) ;
mWorkspace . mIsDebugSession = true ;
/ * DebugSessionProperties workspaceProperties = new . ( ) ;
workspaceProperties . PopupWindow ( mMainWindow ) ;
workspaceProperties . StartNew ( ) ; * /
mPlatformName . Set ( sPlatform64Name ) ;
mConfigName . Set ( "Debug" ) ;
Project project = new . ( ) ;
project . mGeneralOptions . mTargetType = . CustomBuild ;
project . mProjectName . Set ( "Debug Session" ) ;
AddProjectToWorkspace ( project ) ;
mWorkspace . mStartupProject = project ;
if ( ! fromLoad )
project . mHasChanged = true ;
gApp . mWorkspace . FixOptions ( mConfigName , mPlatformName ) ;
mProjectPanel . RebuildUI ( ) ;
if ( ! fromLoad )
{
ProjectProperties dialog = new . ( project ) ;
dialog . PopupWindow ( mMainWindow ) ;
dialog . mNewDebugSessionCountdown = 60 ;
}
}
[IDECommand]
public void Cmd_NewDebugSession ( )
{
#if ! CLI
/ * SaveFileDialog dialog = scope . ( ) ;
let activeWindow = GetActiveWindow ( ) ;
dialog . OverwritePrompt = true ;
dialog . SetFilter ( "Debug Session (*.bfdbg)|*.bfdbg" ) ;
dialog . DefaultExt = ".bfdbg" ;
if ( dialog . ShowDialog ( activeWindow ) . GetValueOrDefault ( ) ! = . OK )
return ; * /
bool done = CheckCloseWorkspace ( mMainWindow ,
new ( ) = >
{
// We use a close delay after saving so the user can see we actually saved before closing down
if ( SaveAll ( ) )
{
NewDebugSession ( false ) ;
}
} ,
new ( ) = >
{
NewDebugSession ( false ) ;
} , null ) ;
if ( done )
{
NewDebugSession ( false ) ;
}
#endif
}
[IDECommand]
public void Cmd_NewWorkspace ( )
{
2019-09-05 08:18:24 -07:00
mDeferredOpen = . NewWorkspaceOrProject ;
2019-08-23 11:56:54 -07:00
}
[IDECommand]
public void Cmd_NewProject ( )
{
mProjectPanel . [ Friend ] AddNewProject ( ) ;
}
[IDECommand]
public void Cmd_NewFile ( )
{
ShowSourceFile ( null , null , . New ) ;
}
[IDECommand]
public void Cmd_OpenProject ( )
{
mProjectPanel . [ Friend ] ImportProject ( ) ;
}
[IDECommand]
public void OpenFile ( )
{
mDeferredOpen = . File ;
}
[IDECommand]
public void OpenCrashDump ( )
{
mDeferredOpen = . CrashDump ;
}
[IDECommand]
public bool SaveAll ( )
{
bool success = true ;
WithSourceViewPanels ( scope [ & ] ( sourceViewPanel ) = >
{
success & = SaveFile ( sourceViewPanel ) ;
} ) ;
mWorkspace . WithProjectItems ( scope [ & ] ( projectItem ) = >
{
var projectSource = projectItem as ProjectSource ;
if ( projectSource ! = null )
{
if ( ( projectSource . mEditData ! = null ) & & ( projectSource . mEditData . HasTextChanged ( ) ) )
{
success & = SaveFile ( projectSource ) ;
}
}
} ) ;
for ( var project in mWorkspace . mProjects )
{
if ( project . mHasChanged )
{
if ( project . IsDebugSession )
success & = SaveDebugSession ( ) ;
else
project . Save ( ) ;
}
}
if ( ( mWorkspace . IsInitialized ) & & ( ! mWorkspace . IsDebugSession ) & &
( ( mWorkspace . mHasChanged ) | | ( mWorkspace . mDir = = null ) ) )
success & = SaveWorkspace ( ) ;
if ( ! mRunningTestScript )
{
2020-01-12 09:21:50 -08:00
#if ! CLI
2019-08-23 11:56:54 -07:00
if ( ! mWorkspace . IsDebugSession )
success & = SaveWorkspaceUserData ( ) ;
2019-11-07 06:54:54 -08:00
if ( mSettings . mLoadedSettings )
mSettings . Save ( ) ;
2020-01-12 09:21:50 -08:00
#endif
2019-08-23 11:56:54 -07:00
}
MarkDirty ( ) ;
return success ;
}
[IDECommand]
void Cmd_Exit ( )
{
mMainWindow . Close ( ) ;
}
WidgetWindow GetCurrentWindow ( )
{
if ( mRunningTestScript )
{
if ( mLastActivePanel ! = null )
return mLastActivePanel . mWidgetWindow ;
return mMainWindow ;
}
for ( var window in mWindows )
{
if ( window . mHasFocus )
{
var returnWindow = window ;
// With this "modal" flag, it caused errors to popup within a hoverwatch on a failed variable edit
while ( ( returnWindow . mParent ! = null ) /*&& (returnWindow.mWindowFlags.HasFlag(BFWindow.Flags.Modal))*/ )
returnWindow = returnWindow . mParent ;
return ( WidgetWindow ) returnWindow ;
}
}
return mMainWindow ;
}
public Dialog Fail ( String text , Widget addWidget = null , WidgetWindow parentWindow = null )
{
// Always write to STDOUT even if we're running as a GUI, allowing cases like RunAndWait to pass us a stdout handle
Console . Error . WriteLine ( "ERROR: {0}" , text ) ;
#if CLI
mFailed = true ;
return null ;
#endif
# unwarn
if ( mMainWindow = = null )
{
mDeferredFails . Add ( new String ( text ) ) ;
return null ;
}
if ( mRunningTestScript )
{
2019-09-03 11:17:13 -07:00
if ( mScriptManager . IsErrorExpected ( text ) )
2019-08-23 11:56:54 -07:00
{
DeleteAndNullify ! ( mScriptManager . mExpectingError ) ;
OutputLine ( "Received expected error: {0}" , text ) ;
return null ;
}
ShowOutput ( ) ;
mFailed = true ;
OutputLineSmart ( "ERROR: {0}" , text ) ;
Console . Error . WriteLine ( "ERROR: {0}" , text ) ;
return null ;
}
# unwarn
Debug . Assert ( Thread . CurrentThread = = mMainThread ) ;
if ( mMainWindow = = null )
{
Internal . FatalError ( StackStringFormat ! ( "FAILED: {0}" , text ) ) ;
}
Beep ( MessageBeepType . Error ) ;
Dialog dialog = ThemeFactory . mDefault . CreateDialog ( "ERROR" , text , DarkTheme . sDarkTheme . mIconError ) ;
dialog . mDefaultButton = dialog . AddButton ( "OK" ) ;
dialog . mEscButton = dialog . mDefaultButton ;
dialog . mWindowFlags | = . Modal ;
dialog . PopupWindow ( parentWindow ? ? GetCurrentWindow ( ) ) ;
if ( addWidget ! = null )
{
dialog . AddWidget ( addWidget ) ;
addWidget . mY = dialog . mHeight - 60 ;
addWidget . mX = 90 ;
}
return dialog ;
}
public void MessageDialog ( String title , String text )
{
Dialog dialog = ThemeFactory . mDefault . CreateDialog ( title , text ) ;
dialog . mDefaultButton = dialog . AddButton ( "OK" ) ;
dialog . mEscButton = dialog . mDefaultButton ;
dialog . PopupWindow ( mMainWindow ) ;
}
public void DoQuickFind ( bool isReplace )
{
var textPanel = GetActiveTextPanel ( ) ;
if ( textPanel ! = null )
textPanel . ShowQuickFind ( isReplace ) ;
else
{
2019-09-05 08:18:24 -07:00
if ( let activeWindow = GetActiveWindow ( ) )
2019-08-23 11:56:54 -07:00
{
var widget = activeWindow . mFocusWidget ;
while ( widget ! = null )
{
if ( let watchStringEdit = widget as WatchStringEdit )
{
watchStringEdit . ShowQuickFind ( isReplace ) ;
return ;
}
widget = widget . mParent ;
}
}
}
}
[IDECommand]
public void ShowAbout ( )
{
Dialog dialog = new AboutDialog ( ) ;
dialog . PopupWindow ( mMainWindow ) ;
}
[IDECommand]
public void Cmd_Document__Find ( )
{
DoQuickFind ( false ) ;
}
[IDECommand]
public void Cmd_Document__Replace ( )
{
DoQuickFind ( true ) ;
}
private void DoFindAndReplace ( bool isReplace )
{
RecordHistoryLocation ( ) ;
if ( mFindAndReplaceDialog ! = null )
{
mFindAndReplaceDialog . mWidgetWindow . SetForeground ( ) ;
return ;
}
mFindAndReplaceDialog = new FindAndReplaceDialog ( isReplace ) ;
mFindAndReplaceDialog . PopupWindow ( mMainWindow ) ;
mFindAndReplaceDialog . mOnClosed . Add ( new ( ) = > { mFindAndReplaceDialog = null ; } ) ;
}
[IDECommand]
public void Cmd_Find ( )
{
DoFindAndReplace ( false ) ;
}
[IDECommand]
public void Cmd_Replace ( )
{
DoFindAndReplace ( true ) ;
}
[IDECommand]
public void Cmd_FindPrev ( )
{
DoFindNext ( - 1 ) ;
}
[IDECommand]
public void Cmd_FindNext ( )
{
DoFindNext ( 1 ) ;
}
[IDECommand]
public void CursorToLineEnd ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . mEditWidget . mEditWidgetContent . CursorToLineEnd ( ) ;
}
[IDECommand]
public void CursorToLineStart ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . mEditWidget . mEditWidgetContent . CursorToLineStart ( true ) ;
}
public void DoFindNext ( int32 dir = 1 )
{
var textPanel = GetActiveTextPanel ( ) ;
if ( textPanel ! = null )
{
textPanel . FindNext ( dir ) ;
}
else
{
2019-09-05 08:18:24 -07:00
if ( let activeWindow = GetActiveWindow ( ) )
2019-08-23 11:56:54 -07:00
{
var widget = activeWindow . mFocusWidget ;
while ( widget ! = null )
{
if ( let watchStringEdit = widget as WatchStringEdit )
{
watchStringEdit . FindNext ( dir ) ;
return ;
}
widget = widget . mParent ;
}
}
}
}
void DoShowNextDocumentPanel ( )
{
var activeDoumentPanel = GetActiveDocumentPanel ( ) ;
if ( ( activeDoumentPanel = = null ) & & ( mActiveDocumentsTabbedView ! = null ) )
{
var activeTab = mActiveDocumentsTabbedView . GetActiveTab ( ) ;
activeTab . Activate ( ) ;
return ;
}
DarkTabbedView nextTabbedView = null ;
DarkTabbedView firstTabbedView = null ;
bool foundActiveTabbedView = false ;
WithDocumentTabbedViews ( scope [ & ] ( tabbedView ) = >
{
if ( tabbedView . mIsFillWidget )
{
if ( firstTabbedView = = null )
firstTabbedView = tabbedView ;
if ( tabbedView = = mActiveDocumentsTabbedView )
foundActiveTabbedView = true ;
else if ( ( foundActiveTabbedView ) & & ( nextTabbedView = = null ) )
nextTabbedView = tabbedView ;
}
} ) ;
if ( nextTabbedView = = null )
nextTabbedView = firstTabbedView ;
if ( nextTabbedView ! = null )
{
var activeTab = nextTabbedView . GetActiveTab ( ) ;
activeTab . Activate ( ) ;
}
}
[IDECommand]
public void Cmd_ShowCurrent ( )
{
var activePanel = GetActivePanel ( ) ;
if ( var sourceViewPanel = activePanel as SourceViewPanel )
{
sourceViewPanel . ShowCurrent ( ) ;
}
else if ( var disassemblyPanel = activePanel as DisassemblyPanel )
{
disassemblyPanel . GoToSource ( ) ;
}
}
[IDECommand]
public void Cmd_GotoLine ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
sourceViewPanel . GotoLine ( ) ;
return ;
}
var activePanel = GetActivePanel ( ) ;
if ( let memoryPanel = activePanel as MemoryPanel )
{
memoryPanel . GotoAddress ( ) ;
}
}
[IDECommand]
public void Cmd_GotoMethod ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . GotoMethod ( ) ;
}
[IDECommand]
public void Cmd_RenameItem ( )
{
let activePanel = GetActivePanel ( ) ;
if ( var projectPanel = activePanel as ProjectPanel )
{
projectPanel . TryRenameItem ( ) ;
}
else if ( var watchPanel = activePanel as WatchPanel )
{
watchPanel . TryRenameItem ( ) ;
}
}
[IDECommand]
public void Cmd_RenameSymbol ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . RenameSymbol ( ) ;
}
[IDECommand]
public void Cmd_FindAllReferences ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . FindAllReferences ( ) ;
}
[IDECommand]
public void Cmd_FindClass ( )
{
var widgetWindow = GetCurrentWindow ( ) ;
if ( widgetWindow ! = null )
{
var dialog = new FindClassDialog ( ) ;
dialog . PopupWindow ( mMainWindow ) ;
}
}
[IDECommand]
public void Cmd_ViewWhiteSpace ( )
{
mViewWhiteSpace . Toggle ( ) ;
MarkDirty ( ) ;
}
[IDECommand]
public void Cmd_ShowAutoComplete ( )
{
2019-09-29 07:44:23 -07:00
var sewc = GetActiveSourceEditWidgetContent ( ) ;
if ( sewc ! = null )
2019-08-23 11:56:54 -07:00
{
2019-09-29 07:44:23 -07:00
sewc . ShowAutoComplete ( true ) ;
2019-08-23 11:56:54 -07:00
}
}
[IDECommand]
public void Cmd_ShowFixit ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . FixitAtCursor ( ) ;
}
[IDECommand]
public void Cmd_PrevBookmark ( )
{
mBookmarkManager . PrevBookmark ( ) ;
}
[IDECommand]
public void Cmd_NextBookmark ( )
{
mBookmarkManager . NextBookmark ( ) ;
}
[IDECommand]
public void Cmd_ToggleBookmark ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . ToggleBookmarkAtCursor ( ) ;
}
[IDECommand]
public void Cmd_ClearBookmarks ( )
{
mBookmarkManager . Clear ( ) ;
}
[IDECommand]
public void Cmd_Clean ( )
{
if ( IsCompiling )
{
Fail ( "Cannot clean while compilign" ) ;
return ; // Ignore
}
if ( mDebugger . mIsRunning )
{
Fail ( "Cannot clean while running" ) ;
return ; // Ignore
}
mWantsClean = true ;
}
[IDECommand]
public void Cmd_CleanBeef ( )
{
if ( IsCompiling )
{
Fail ( "Cannot clean while compilign" ) ;
return ; // Ignore
}
if ( mDebugger . mIsRunning )
{
Fail ( "Cannot clean while running" ) ;
return ; // Ignore
}
mWantsBeefClean = true ;
}
[IDECommand]
public void Cmd_CompileFile ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
if ( sourceViewPanel . mProjectSource ! = null )
{
var filePath = scope String ( ) ;
sourceViewPanel . mProjectSource . GetFullImportPath ( filePath ) ;
if ( ( filePath . EndsWith ( ".cpp" , StringComparison . OrdinalIgnoreCase ) ) | |
( filePath . EndsWith ( ".c" , StringComparison . OrdinalIgnoreCase ) ) )
{
ShowPanel ( mOutputPanel , false ) ;
SaveFile ( sourceViewPanel ) ;
var project = sourceViewPanel . mProjectSource . mProject ;
Project . Options options = GetCurProjectOptions ( project ) ;
if ( options ! = null )
{
Workspace . Options workspaceOptions = GetCurWorkspaceOptions ( ) ;
CompileSource ( project , workspaceOptions , options , filePath ) ;
}
}
}
}
}
[IDECommand]
public void Cmd_MatchBrace ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . MatchBrace ( ) ;
}
[IDECommand]
public void Cmd_GotoNextItem ( )
{
var curOutputPanel = mOutputPanel ;
if ( ( mFindResultsPanel ! = null ) & & ( mFindResultsPanel . mWidgetWindow ! = null ) )
{
if ( mFindResultsPanel . mLastFocusAppUpdateCnt > curOutputPanel . mLastFocusAppUpdateCnt )
curOutputPanel = mFindResultsPanel ;
}
curOutputPanel . GotoNextSourceReference ( ) ;
}
[IDECommand]
public void Cmd_ZoomOut ( )
{
float scale = DarkTheme . sScale ;
2019-09-30 12:23:27 -07:00
if ( scale > 0.25f )
2019-08-23 11:56:54 -07:00
{
if ( scale < 0 )
scale - = 0.05f ;
else //if (scale < 2.0f)
scale - = 0.10f ;
SetScale ( scale ) ;
}
}
[IDECommand]
public void Cmd_ZoomIn ( )
{
float scale = DarkTheme . sScale ;
if ( scale < 4.0f )
{
if ( scale < 0 )
scale + = 0.02f ; //0.05f;
else //if (scale < 2.0f)
scale + = 0.04f ; //0.10f;
SetScale ( scale ) ;
}
}
[IDECommand]
public void Cmd_ShowFileExternally ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
ProcessStartInfo psi = scope ProcessStartInfo ( ) ;
psi . SetFileName ( "/bin/OpenFileLine" ) ;
var args = scope String ( ) ;
args . AppendF ( "{0} {1}" , sourceViewPanel . mFilePath , sourceViewPanel . mEditWidget . mEditWidgetContent . CursorLineAndColumn . mLine + 1 ) ;
psi . SetArguments ( args ) ;
psi . UseShellExecute = false ;
SpawnedProcess process = scope SpawnedProcess ( ) ;
process . Start ( psi ) . IgnoreError ( ) ;
/ * if ( case . Ok ( var process ) = Process . Start ( psi ) )
delete process ; * /
}
}
[IDECommand]
public void Cmd_ZoomReset ( )
{
SetScale ( 1.0f , true ) ;
}
[IDECommand]
public void Cmd_ReformatDocument ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . ReformatDocument ( ) ;
}
void RemoveAllBreakpoints ( )
{
BfLog . LogDbg ( "IDEApp.RemoveAllBreakpoints\n" ) ;
while ( mDebugger . mBreakpointList . Count > 0 )
mDebugger . DeleteBreakpoint ( mDebugger . mBreakpointList [ 0 ] ) ;
}
[IDECommand]
void Cmd_Break ( )
{
mDebugger . BreakAll ( ) ;
}
public void ShowDisassemblyAtCursor ( )
{
if ( ! mDebugger . mIsRunning )
return ; // Ignore
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
int line ;
int lineChar ;
sourceViewPanel . mEditWidget . Content . GetCursorLineChar ( out line , out lineChar ) ;
var disassemblyPanel = ShowDisassemblyPanel ( ) ;
if ( ! disassemblyPanel . Show ( sourceViewPanel . mFilePath , line , lineChar ) )
ShowRecentFile ( 1 ) ; // Go back a file
}
}
[IDECommand]
public void ShowDisassemblyAtStack ( )
{
var activePanel = GetActivePanel ( ) ;
if ( var diassemblyPanel = activePanel as DisassemblyPanel )
{
diassemblyPanel . mStayInDisassemblyCheckbox . Checked ^ = true ;
return ;
}
if ( ( mDebugger . mIsRunning ) & & ( mDebugger . IsPaused ( ) ) )
{
ShowPCLocation ( mDebugger . mActiveCallStackIdx , false , false , true ) ;
}
else
{
ShowDisassemblyPanel ( true ) ;
}
mInDisassemblyView = true ;
}
public void GoToDefinition ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
int line ;
int lineChar ;
sourceViewPanel . mEditWidget . Content . GetCursorLineChar ( out line , out lineChar ) ;
#if IDE_C_SUPPORT
if ( sourceViewPanel . mIsClang )
{
String defFile = scope String ( ) ;
int defLine ;
int defColumn ;
mResolveClang . CancelBackground ( ) ;
int defIdx = sourceViewPanel . mEditWidget . Content . GetTextIdx ( line , lineChar ) ;
if ( mResolveClang . FindDefinition ( sourceViewPanel . mFilePath , defIdx ,
defFile , out defLine , out defColumn ) )
{
sourceViewPanel . RecordHistoryLocation ( ) ;
sourceViewPanel = ShowSourceFileLocation ( defFile , - 1 , - 1 , defLine , defColumn , LocatorType . Smart , true ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . RecordHistoryLocation ( ) ;
return ;
}
}
else
#endif
{
ResolveParams resolveParams = scope ResolveParams ( ) ;
sourceViewPanel . Classify ( ResolveType . GoToDefinition , resolveParams ) ;
if ( resolveParams . mOutFileName ! = null )
{
sourceViewPanel . RecordHistoryLocation ( ) ;
sourceViewPanel = ShowSourceFileLocation ( resolveParams . mOutFileName , - 1 , - 1 , resolveParams . mOutLine , resolveParams . mOutLineChar , LocatorType . Smart , true ) ;
sourceViewPanel . RecordHistoryLocation ( true ) ;
return ;
}
}
if ( mBfResolveCompiler . HasResolvedAll ( ) )
{
Fail ( "Unable to locate definition" ) ;
}
else
{
sourceViewPanel . ShowSymbolReferenceHelper ( . GoToDefinition ) ;
}
}
}
public void StackPositionChanged ( )
{
WithWatchPanels ( scope ( watchPanel ) = >
{
watchPanel . MarkWatchesDirty ( false , true ) ;
} ) ;
mMemoryPanel . MarkViewDirty ( ) ;
}
public void RefreshWatches ( )
{
//Debug.WriteLine("RefreshWatches");
WithWatchPanels ( scope ( watchPanel ) = >
{
watchPanel . MarkWatchesDirty ( false ) ;
} ) ;
MarkDirty ( ) ;
for ( var window in gApp . mWindows )
{
var widgetWindow = window as WidgetWindow ;
if ( var hoverWatch = widgetWindow . mRootWidget as HoverWatch )
{
hoverWatch . Refresh ( ) ;
}
}
}
public void MemoryEdited ( )
{
RefreshWatches ( ) ;
mMemoryPanel . MarkViewDirty ( ) ;
}
public void AddWatch ( String watchExpr )
{
ShowWatches ( ) ;
mWatchPanel . AddWatchItem ( watchExpr ) ;
mWatchPanel . MarkWatchesDirty ( false ) ;
}
public bool IsInDisassemblyMode ( bool wantShowSource = false )
{
//return GetActiveDocumentPanel() is DisassemblyPanel;
if ( ! mInDisassemblyView )
return false ;
DisassemblyPanel disassemblyPanel = TryGetDisassemblyPanel ( ) ;
if ( disassemblyPanel = = null )
return false ;
return ( ( disassemblyPanel . mStayInDisassemblyCheckbox ! = null ) & & ( disassemblyPanel . mStayInDisassemblyCheckbox . Checked ) ) | | ( ! wantShowSource ) ;
}
DisassemblyPanel TryGetDisassemblyPanel ( bool onlyIfVisible = true )
{
Debug . Assert ( true ) ;
DisassemblyPanel disassemblyPanel = null ;
WithTabs ( scope [ & ] ( tabButton ) = >
{
if ( ( disassemblyPanel = = null ) & & ( tabButton . mContent is DisassemblyPanel ) )
{
var checkDisassemblyPanel = ( DisassemblyPanel ) tabButton . mContent ;
if ( ( ! onlyIfVisible ) | | ( checkDisassemblyPanel . mWidgetWindow ! = null ) )
disassemblyPanel = checkDisassemblyPanel ;
}
} ) ;
return disassemblyPanel ;
}
[IDECommand]
void Compile ( )
{
2019-10-29 04:56:42 -07:00
CompilerLog ( "IDEApp.Compile" ) ;
2019-12-01 10:19:00 -08:00
for ( let project in gApp . mWorkspace . mProjects )
{
if ( project . mFailed )
{
OutputErrorLine ( "Project '{}' is not loaded. Retry loading by right clicking on the project in the Workspace panel and selecting 'Retry Load'" , project . mProjectName ) ;
return ;
}
}
2019-08-23 11:56:54 -07:00
if ( AreTestsRunning ( ) )
return ;
if ( mHotResolveState ! = . None )
return ;
2019-08-29 14:19:07 -07:00
if ( IsCompiling )
return ;
2019-08-23 11:56:54 -07:00
if ( mWorkspace . mProjects . IsEmpty )
{
Fail ( "No projects exist to compile. Create or load a project." ) ;
return ;
}
if ( mWorkspace . IsDebugSession )
{
bool hadCommands = false ;
for ( let project in mWorkspace . mProjects )
{
if ( project . mGeneralOptions . mTargetType = = . CustomBuild )
{
let options = GetCurProjectOptions ( project ) ;
if ( options = = null )
continue ;
if ( ( ! options . mBuildOptions . mPreBuildCmds . IsEmpty ) | | ( ! options . mBuildOptions . mPostBuildCmds . IsEmpty ) )
hadCommands = true ;
}
else
hadCommands = true ;
}
if ( ! hadCommands )
{
Fail ( "No build commands have been defined" ) ;
return ;
}
}
if ( ( ! mDebugger . mIsRunning ) | | ( ! mDebugger . mIsRunningCompiled ) )
{
if ( mExecutionQueue . Count = = 0 )
{
mOutputPanel . Clear ( ) ;
OutputLine ( "Compiling..." ) ;
Compile ( . Normal , null ) ;
}
}
else
{
mOutputPanel . Clear ( ) ;
OutputLine ( "Hot Compiling..." ) ;
Project runningProject = mWorkspace . mStartupProject ;
Compile ( . Normal , runningProject ) ;
}
}
2019-08-29 14:19:07 -07:00
[IDECommand]
void RunWithStep ( )
{
mTargetStartWithStep = true ;
CompileAndRun ( ) ;
}
2019-08-23 11:56:54 -07:00
[IDECommand]
void StepInto ( )
{
if ( mDebugger . mIsRunning )
{
if ( mExecutionPaused )
{
DebuggerUnpaused ( ) ;
mDebugger . StepInto ( IsInDisassemblyMode ( ) ) ;
}
}
else
{
2019-08-29 14:19:07 -07:00
RunWithStep ( ) ;
2019-08-23 11:56:54 -07:00
}
}
[IDECommand]
void StepOver ( )
{
mStepCount + + ;
if ( mDebugger . mIsRunning )
{
if ( mExecutionPaused )
{
DebuggerUnpaused ( ) ;
mDebugger . StepOver ( IsInDisassemblyMode ( ) ) ;
}
}
else
{
if ( mEnableRunTiming )
{
mRunTimingProfileId = Profiler . StartSampling ( "RunTiming" ) ;
}
2019-08-29 14:19:07 -07:00
RunWithStep ( ) ;
2019-08-23 11:56:54 -07:00
}
}
[IDECommand]
void StepOut ( )
{
if ( mExecutionPaused )
{
DebuggerUnpaused ( ) ;
mDebugger . StepOut ( IsInDisassemblyMode ( ) ) ;
}
}
[IDECommand]
void Cmd_Continue ( )
{
if ( mDebugger . mIsRunning )
{
if ( mDebugger . IsPaused ( ) )
{
DebuggerUnpaused ( ) ;
mDebugger . Continue ( ) ;
}
}
}
[IDECommand]
public void RunWithCompiling ( )
{
if ( mDebugger . mIsRunning )
{
if ( mDebugger . IsPaused ( ) )
{
DebuggerUnpaused ( ) ;
mDebugger . Continue ( ) ;
}
}
else if ( AreTestsRunning ( ) )
{
// Ignore
}
else
{
mTargetStartWithStep = false ;
CompileAndRun ( ) ;
}
}
[IDECommand]
void RunWithoutCompiling ( )
{
if ( ! mDebugger . mIsRunning )
{
OutputLine ( "Starting target without compiling..." ) ;
mTargetStartWithStep = false ;
var startDebugCmd = new StartDebugCmd ( ) ;
startDebugCmd . mWasCompiled = false ;
startDebugCmd . mOnlyIfNotFailed = true ;
mExecutionQueue . Add ( startDebugCmd ) ;
}
}
[IDECommand]
void RunToCursor ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( mDebugger . mRunToCursorBreakpoint ! = null )
{
BfLog . LogDbg ( "Deleting mRunToCursorBreakpoint\n" ) ;
mDebugger . DeleteBreakpoint ( mDebugger . mRunToCursorBreakpoint ) ;
mDebugger . mRunToCursorBreakpoint = null ;
}
if ( sourceViewPanel ! = null )
{
BfLog . LogDbg ( "Creating mRunToCursorBreakpoint\n" ) ;
2019-12-13 14:25:15 -08:00
mDebugger . mRunToCursorBreakpoint = sourceViewPanel . ToggleBreakpointAtCursor ( . Force , . None , mDebugger . GetActiveThread ( ) ) ;
2019-08-23 11:56:54 -07:00
}
else if ( var disassemblyPanel = GetActiveDocumentPanel ( ) as DisassemblyPanel )
{
2019-12-13 14:25:15 -08:00
mDebugger . mRunToCursorBreakpoint = disassemblyPanel . ToggleAddrBreakpointAtCursor ( . Force , . None , mDebugger . GetActiveThread ( ) ) ;
2019-08-23 11:56:54 -07:00
}
if ( mDebugger . mIsRunning )
{
if ( mDebugger . IsPaused ( ) )
{
DebuggerUnpaused ( ) ;
mDebugger . Continue ( ) ;
}
}
else
{
mTargetStartWithStep = false ;
CompileAndRun ( ) ;
}
}
[IDECommand]
void SetNextStatement ( )
{
var documentPanel = GetActiveDocumentPanel ( ) ;
var sourceViewPanel = documentPanel as SourceViewPanel ;
var disassemblyPanel = GetActiveDocumentPanel ( ) as DisassemblyPanel ;
if ( mDebugger . mIsRunning )
{
if ( mExecutionPaused )
{
if ( gApp . mDebugger . mActiveCallStackIdx ! = 0 )
{
gApp . Fail ( "Set Next Statement cannot only be used when the top of the callstack is selected" ) ;
return ;
}
if ( disassemblyPanel ! = null )
{
String sourceFileName = scope String ( ) ;
int addr = disassemblyPanel . GetCursorAddress ( sourceFileName ) ;
if ( addr ! = ( int ) 0 )
{
mDebugger . SetNextStatement ( true , sourceFileName , addr , 0 ) ;
PCChanged ( ) ;
}
DebuggerUnpaused ( ) ;
}
else
{
var activePanel = sourceViewPanel . GetActivePanel ( ) ;
int lineIdx ;
int lineCharIdx ;
var editWidgetContent = activePanel . mEditWidget . Content ;
editWidgetContent . GetLineCharAtIdx ( editWidgetContent . CursorTextPos , out lineIdx , out lineCharIdx ) ;
/ * int hotFileIdx = sourceViewPanel . [ Friend ] mHotFileIdx ;
sourceViewPanel . [ Friend ] RemapActiveToCompiledLine ( hotFileIdx , ref lineIdx , ref lineCharIdx ) ; * /
int textPos = editWidgetContent . CursorTextPos - lineCharIdx ;
lineCharIdx = 0 ;
// Find first non-space char8
while ( ( textPos < editWidgetContent . mData . mTextLength ) & & ( ( ( char8 ) editWidgetContent . mData . mText [ textPos ] . mChar ) . IsWhiteSpace ) )
{
textPos + + ;
lineCharIdx + + ;
}
if ( sourceViewPanel . [ Friend ] mOldVersionPanel = = null )
{
int addr ;
String file = scope String ( ) ;
int hotIdx ;
int defLineStart ;
int defLineEnd ;
int line ;
int column ;
int language ;
int stackSize ;
mDebugger . CheckCallStack ( ) ;
String label = scope String ( ) ;
DebugManager . FrameFlags frameFlags ;
mDebugger . GetStackFrameInfo ( 0 , label , out addr , file , out hotIdx , out defLineStart , out defLineEnd , out line , out column , out language , out stackSize , out frameFlags ) ;
if ( hotIdx ! = - 1 )
sourceViewPanel . [ Friend ] RemapActiveToCompiledLine ( hotIdx , ref lineIdx , ref lineCharIdx ) ;
}
mDebugger . SetNextStatement ( false , sourceViewPanel . mFilePath , ( int ) lineIdx , lineCharIdx ) ;
PCChanged ( ) ;
DebuggerUnpaused ( ) ;
}
}
}
}
2019-12-13 14:25:15 -08:00
void ToggleBreakpoint ( WidgetWindow window , Breakpoint . SetKind setKind , Breakpoint . SetFlags setFlags , bool bindToThread = false )
2019-08-23 11:56:54 -07:00
{
var documentPanel = GetActiveDocumentPanel ( ) ;
if ( var sourceViewPanel = documentPanel as SourceViewPanel )
{
2019-12-13 14:25:15 -08:00
sourceViewPanel . ToggleBreakpointAtCursor ( setKind , setFlags , bindToThread ? gApp . mDebugger . GetActiveThread ( ) : - 1 ) ;
2019-08-23 11:56:54 -07:00
}
else if ( var disassemblyPanel = documentPanel as DisassemblyPanel )
{
2019-12-13 14:25:15 -08:00
disassemblyPanel . ToggleBreakpointAtCursor ( setKind , setFlags , bindToThread ? gApp . mDebugger . GetActiveThread ( ) : - 1 ) ;
2019-08-23 11:56:54 -07:00
}
}
[IDECommand]
void ToggleComment ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel = = null )
return ;
var ewc = ( SourceEditWidgetContent ) sourceViewPanel . mEditWidget . mEditWidgetContent ;
ewc . ToggleComment ( ) ;
}
[IDECommand]
void ToggleBreakpoint ( )
{
2019-12-13 14:25:15 -08:00
ToggleBreakpoint ( GetCurrentWindow ( ) , . Toggle , . None ) ;
}
[IDECommand]
public void ConfigureBreakpoint ( )
{
if ( var breakpointPanel = GetActivePanel ( ) as BreakpointPanel )
{
breakpointPanel . ConfigureBreakpoints ( breakpointPanel . mWidgetWindow ) ;
return ;
}
ToggleBreakpoint ( GetCurrentWindow ( ) , . EnsureExists , . Configure ) ;
}
[IDECommand]
public void DisableBreakpoint ( )
{
if ( var breakpointPanel = GetActivePanel ( ) as BreakpointPanel )
{
breakpointPanel . SetBreakpointsDisabled ( null ) ;
return ;
}
ToggleBreakpoint ( GetCurrentWindow ( ) , . MustExist , . Disable ) ;
2019-08-23 11:56:54 -07:00
}
[IDECommand]
void ToggleThreadBreakpoint ( )
{
2019-12-13 14:25:15 -08:00
ToggleBreakpoint ( GetCurrentWindow ( ) , . Toggle , . None , true ) ;
2019-08-23 11:56:54 -07:00
}
void CompileCurrentFile ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel = = null )
return ;
if ( sourceViewPanel . mProjectSource = = null )
return ;
if ( ! sourceViewPanel . mIsClang )
return ;
var project = sourceViewPanel . mProjectSource . mProject ;
var options = GetCurProjectOptions ( project ) ;
var workspaceOptions = GetCurWorkspaceOptions ( ) ;
CompileSource ( project , workspaceOptions , options , sourceViewPanel . mFilePath , "-v" ) ;
}
[IDECommand]
void CancelBuild ( )
{
mBfBuildCompiler . RequestCancelBackground ( ) ;
if ( IsCompiling )
{
OutputLine ( "Canceling Compilation..." ) ;
//DeleteAndClearItems!(mExecutionQueue);
for ( var cmd in mExecutionQueue )
{
# unwarn
if ( var processBfCompileCmd = cmd as ProcessBfCompileCmd )
{
2019-08-27 08:04:41 -07:00
}
else if ( var buildCompleteCmd = cmd as BuildCompletedCmd )
{
2019-08-23 11:56:54 -07:00
}
else
{
2019-08-27 08:04:41 -07:00
delete cmd ;
2019-08-23 11:56:54 -07:00
@cmd . Remove ( ) ;
}
}
for ( var executionInstance in mExecutionInstances )
{
executionInstance . Cancel ( ) ;
}
}
2019-08-27 08:04:41 -07:00
if ( ( mBuildContext ! = null ) & & ( mBuildContext . mScriptManager ! = null ) )
mBuildContext . mScriptManager . Cancel ( ) ;
2019-08-23 11:56:54 -07:00
}
TabbedView FindTabbedView ( DockingFrame dockingFrame , int32 xDir , int32 yDir )
{
bool useFirst = true ;
if ( dockingFrame . mSplitType = = DockingFrame . SplitType . Horz )
{
useFirst = xDir > 0 ;
}
else
useFirst = yDir > 0 ;
for ( int32 pass = 0 ; pass < 2 ; pass + + )
{
for ( int32 i = 0 ; i < dockingFrame . mDockedWidgets . Count ; i + + )
{
if ( ( useFirst ) & & ( i = = 0 ) & & ( pass = = 0 ) )
continue ;
var widget = dockingFrame . mDockedWidgets [ i ] ;
if ( widget is TabbedView )
return ( TabbedView ) widget ;
DockingFrame childFrame = widget as DockingFrame ;
if ( childFrame ! = null )
{
TabbedView tabbedView = FindTabbedView ( childFrame , xDir , yDir ) ;
if ( tabbedView ! = null )
return tabbedView ;
}
}
}
return null ;
}
enum ShowTabResult
{
Existing ,
OpenedNew
}
ShowTabResult ShowTab ( Widget tabContent , String name , bool ownsContent , bool setFocus )
{
var result = ShowTabResult . Existing ;
var tabButton = GetTab ( tabContent ) ;
if ( tabButton = = null )
{
TabbedView tabbedView = null ;
if ( var newPanel = tabContent as Panel )
{
WithTabs ( scope [ & ] ( tabButton ) = >
{
if ( newPanel . HasAffinity ( tabButton . mContent ) )
{
tabbedView = tabButton . mTabbedView ;
}
} ) ;
}
if ( tabbedView = = null )
tabbedView = FindTabbedView ( mDockingFrame , - 1 , 1 ) ;
if ( tabbedView = = null )
{
tabbedView = CreateTabbedView ( ) ;
mDockingFrame . AddDockedWidget ( tabbedView , null , . Left ) ;
}
if ( tabbedView ! = null )
{
tabButton = SetupTab ( tabbedView , name , 100 , tabContent , ownsContent ) ;
result = ShowTabResult . OpenedNew ;
}
}
if ( tabButton ! = null )
{
tabButton . RehupScale ( 1.0f , 1.0f ) ;
tabButton . Activate ( setFocus ) ;
}
return result ;
}
2019-12-25 12:43:45 -08:00
public void RecordHistoryLocation ( bool includeLastActive = false )
2019-08-23 11:56:54 -07:00
{
var sourceViewPanel = GetActiveSourceViewPanel ( includeLastActive ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . RecordHistoryLocation ( ) ;
}
void ShowPanel ( Panel panel , String label , bool setFocus = true )
{
mLastActivePanel = panel ;
RecordHistoryLocation ( ) ;
ShowTab ( panel , label , false , setFocus ) ;
if ( setFocus )
panel . FocusForKeyboard ( ) ;
2019-08-29 14:19:07 -07:00
if ( ( ! panel . mWidgetWindow . mHasFocus ) & & ( ! mRunningTestScript ) )
2019-08-23 11:56:54 -07:00
panel . mWidgetWindow . SetForeground ( ) ;
}
[IDECommand]
public void ShowWorkspacePanel ( )
{
ShowPanel ( mProjectPanel , "Workspace" ) ;
}
[IDECommand]
public void ShowClassViewPanel ( )
{
ShowPanel ( mClassViewPanel , "Class View" ) ;
}
[IDECommand]
public void ShowThreads ( )
{
ShowPanel ( mThreadPanel , "Threads" ) ;
}
[IDECommand]
public void ShowCallstack ( )
{
ShowPanel ( mCallStackPanel , "Call Stack" ) ;
}
2020-01-06 13:49:35 -08:00
[IDECommand]
public void ShowErrors ( )
{
ShowPanel ( mErrorsPanel , "Errors" ) ;
}
[IDECommand]
public void ShowErrorNext ( )
{
mErrorsPanel . ShowErrorNext ( ) ;
}
2019-08-23 11:56:54 -07:00
[IDECommand]
public void ShowWatches ( )
{
ShowPanel ( mWatchPanel , "Watch" ) ;
}
[IDECommand]
public void ShowAutoWatches ( )
{
ShowPanel ( mAutoWatchPanel , "Auto Watches" ) ;
}
[IDECommand]
public void ShowImmediatePanel ( )
{
ShowPanel ( mImmediatePanel , "Immediate" ) ;
}
[IDECommand]
public void ShowBreakpoints ( )
{
ShowPanel ( mBreakpointPanel , "Breakpoints" ) ;
}
[IDECommand]
public void ShowModules ( )
{
ShowPanel ( mModulePanel , "Modules" ) ;
}
[IDECommand]
public void ShowMemory ( )
{
ShowPanel ( mMemoryPanel , "Memory" ) ;
}
[IDECommand]
public void ShowProfilePanel ( )
{
ShowPanel ( mProfilePanel , "Profile" ) ;
}
[IDECommand]
public void ShowQuickWatch ( )
{
QuickWatchDialog dialog = new . ( ) ;
var activePanel = GetActivePanel ( ) ;
if ( let sourceViewPanel = activePanel as SourceViewPanel )
{
sourceViewPanel . RecordHistoryLocation ( ) ;
var debugExpr = scope String ( ) ;
var ewc = sourceViewPanel . EditWidget . Content ;
if ( ewc . HasSelection ( ) )
ewc . GetSelectionText ( debugExpr ) ;
else
sourceViewPanel . GetDebugExpressionAt ( ewc . CursorTextPos , debugExpr ) ;
dialog . Init ( debugExpr ) ;
}
else if ( let immediatePanel = activePanel as ImmediatePanel )
{
var debugExpr = scope String ( ) ;
immediatePanel . GetQuickExpression ( debugExpr ) ;
dialog . Init ( debugExpr ) ;
}
else
{
dialog . Init ( . ( ) ) ;
}
if ( activePanel ! = null )
dialog . PopupWindow ( activePanel . mWidgetWindow ) ;
else
dialog . PopupWindow ( mMainWindow ) ;
}
[IDECommand]
public void SelectConfig ( )
{
mMainFrame . mStatusBar . mConfigComboBox . ShowDropdown ( ) ;
}
[IDECommand]
public void SelectPlatform ( )
{
mMainFrame . mStatusBar . mPlatformComboBox . ShowDropdown ( ) ;
}
[IDECommand]
public void ShowSettings ( )
{
var workspaceProperties = new SettingsDialog ( ) ;
workspaceProperties . PopupWindow ( mMainWindow ) ;
}
[IDECommand]
public void ShowKeyboardShortcuts ( )
{
/ * var workspaceProperties = new SettingsDialog ( ) ;
workspaceProperties . PopupWindow ( mMainWindow ) ; * /
}
public void ShowFindResults ( bool setFocus )
{
ShowPanel ( mFindResultsPanel , "Find Results" , setFocus ) ;
}
[IDECommand]
public void ShowFindResults ( )
{
ShowFindResults ( true ) ;
}
[IDECommand]
public void ShowOutput ( )
{
ShowPanel ( mOutputPanel , "Output" ) ;
}
[IDECommand]
public void ShowAutoCompletePanel ( )
{
ShowPanel ( mAutoCompletePanel , "Autocomplete" , false ) ;
}
[IDECommand]
private void OpenCorresponding ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
String fileName = sourceViewPanel . mFilePath ;
String findFileName = null ;
int dotPos = fileName . LastIndexOf ( '.' ) ;
if ( ( fileName . EndsWith ( ".cpp" , StringComparison . OrdinalIgnoreCase ) ) | | ( fileName . EndsWith ( ".c" , StringComparison . OrdinalIgnoreCase ) ) )
{
findFileName = scope : : String ( fileName , 0 , dotPos ) ;
findFileName . Append ( ".h" ) ;
}
else if ( ( fileName . EndsWith ( ".h" , StringComparison . OrdinalIgnoreCase ) ) | | ( fileName . EndsWith ( ".hpp" , StringComparison . OrdinalIgnoreCase ) ) )
{
findFileName = scope : : String ( fileName , 0 , dotPos ) ;
findFileName . Append ( ".c" ) ;
if ( ! File . Exists ( findFileName ) )
{
findFileName = scope : : String ( fileName , 0 , dotPos ) ;
findFileName . Append ( ".cpp" ) ;
}
}
if ( findFileName ! = null )
{
if ( File . Exists ( findFileName ) )
{
ShowSourceFile ( findFileName ) ;
}
else
{
Fail ( "Unable to find corresponding file" ) ;
}
}
}
}
DarkTabbedView GetActiveTabbedView ( )
{
var activePanel = GetActivePanel ( ) ;
if ( activePanel = = null )
return null ;
return activePanel . mParent as DarkTabbedView ;
}
[IDECommand]
void TabFirst ( )
{
var tabbedView = GetActiveTabbedView ( ) ;
if ( ( tabbedView = = null ) | | ( tabbedView . mTabs . IsEmpty ) )
return ;
tabbedView . mTabs [ 0 ] . Activate ( ) ;
}
[IDECommand]
void TabLast ( )
{
var tabbedView = GetActiveTabbedView ( ) ;
if ( ( tabbedView = = null ) | | ( tabbedView . mTabs . IsEmpty ) )
return ;
tabbedView . mTabs . Back . Activate ( ) ;
}
[IDECommand]
void TabNext ( )
{
var tabbedView = GetActiveTabbedView ( ) ;
if ( ( tabbedView = = null ) | | ( tabbedView . mTabs . IsEmpty ) )
return ;
2019-12-13 14:25:15 -08:00
TabbedView . TabButton activateTab = tabbedView . mTabs [ 0 ] ;
2019-08-23 11:56:54 -07:00
for ( var tab in tabbedView . mTabs )
{
if ( tab . mIsActive )
{
if ( @tab . Index < tabbedView . mTabs . Count - 1 )
{
2019-12-13 14:25:15 -08:00
activateTab = tabbedView . mTabs [ @tab . Index + 1 ] ;
break ;
2019-08-23 11:56:54 -07:00
}
}
}
2019-12-13 14:25:15 -08:00
activateTab . Activate ( ) ;
if ( var sourceViewPanel = activateTab . mContent as SourceViewPanel )
sourceViewPanel . HilitePosition ( . Extra ) ;
2019-08-23 11:56:54 -07:00
}
[IDECommand]
void TabPrev ( )
{
var tabbedView = GetActiveTabbedView ( ) ;
if ( ( tabbedView = = null ) | | ( tabbedView . mTabs . IsEmpty ) )
return ;
2019-12-13 14:25:15 -08:00
TabbedView . TabButton activateTab = tabbedView . mTabs . Back ;
2019-08-23 11:56:54 -07:00
for ( var tab in tabbedView . mTabs )
{
if ( tab . mIsActive )
{
if ( @tab . Index > 0 )
{
2019-12-13 14:25:15 -08:00
activateTab = tabbedView . mTabs [ @tab . Index - 1 ] ;
break ;
2019-08-23 11:56:54 -07:00
}
}
}
2019-12-13 14:25:15 -08:00
activateTab . Activate ( ) ;
if ( var sourceViewPanel = activateTab . mContent as SourceViewPanel )
sourceViewPanel . HilitePosition ( . Extra ) ;
2019-08-23 11:56:54 -07:00
}
void DoErrorTest ( )
{
Dialog aDialog = ThemeFactory . mDefault . CreateDialog ( "ERROR" , "This\nmultiline!\nLine 3." , DarkTheme . sDarkTheme . mIconError ) ;
aDialog . mDefaultButton = aDialog . AddButton ( "OK" ) ;
aDialog . mEscButton = aDialog . mDefaultButton ;
aDialog . PopupWindow ( GetCurrentWindow ( ) ) ;
}
void ReportMemory ( )
{
mDebugger . FullReportMemory ( ) ;
if ( mBfResolveSystem ! = null )
mBfResolveSystem . ReportMemory ( ) ;
mBfBuildSystem . ReportMemory ( ) ;
Internal . ReportMemory ( ) ;
GC . Report ( ) ;
}
[IDECommand]
void DoAttach ( )
{
var widgetWindow = GetCurrentWindow ( ) ;
if ( widgetWindow ! = null )
{
var attachDialog = new AttachDialog ( ) ;
attachDialog . PopupWindow ( mMainWindow ) ;
}
}
[IDECommand]
void DoLaunch ( )
{
if ( mLaunchDialog ! = null )
{
mLaunchDialog . mWidgetWindow . SetForeground ( ) ;
return ;
}
mLaunchDialog = new LaunchDialog ( ) ;
mLaunchDialog . PopupWindow ( mMainWindow ) ;
mLaunchDialog . mOnClosed . Add ( new ( ) = > { mLaunchDialog = null ; } ) ;
}
void DoProfile ( )
{
if ( gApp . mProfilePanel . mUserProfiler ! = null )
{
ShowProfilePanel ( ) ;
gApp . mProfilePanel . StopProfiling ( ) ;
}
else
{
ShowProfilePanel ( ) ;
gApp . mProfilePanel . StartProfiling ( ) ;
}
}
[IDECommand]
void NavigateBackwards ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( ( sourceViewPanel ! = null ) & & ( sourceViewPanel . HasFocus ( ) ) )
{
var sourceEditWidgetContent = ( SourceEditWidgetContent ) sourceViewPanel . mEditWidget . mEditWidgetContent ;
if ( sourceEditWidgetContent . IsAtCurrentHistory ( ) )
{
mHistoryManager . PrevHistory ( ) ;
return ;
}
}
mHistoryManager . GoToCurrentHistory ( ) ;
}
[IDECommand]
void NavigateForwards ( )
{
mHistoryManager . NextHistory ( ) ;
}
void ExitTest ( )
{
sExitTest = true ;
Stop ( ) ;
}
void ToggleCheck ( IMenu menu , ref bool checkVal )
{
checkVal = ! checkVal ;
var sysMenu = ( SysMenu ) menu ;
sysMenu . Modify ( null , null , null , true , checkVal ? 1 : 0 ) ;
}
public bool AreTestsRunning ( )
{
return ( mTestManager ! = null ) ;
}
2019-12-13 14:25:15 -08:00
protected void RunTests ( bool includeIgnored , bool debug )
2019-08-23 11:56:54 -07:00
{
if ( mOutputPanel ! = null )
{
ShowPanel ( mOutputPanel , false ) ;
mOutputPanel . Clear ( ) ;
}
if ( AreTestsRunning ( ) )
{
2019-12-13 14:25:15 -08:00
OutputErrorLine ( "Tests already running" ) ;
2019-08-23 11:56:54 -07:00
return ;
}
if ( ( mDebugger ! = null ) & & ( mDebugger . mIsRunning ) )
{
2019-12-13 14:25:15 -08:00
OutputErrorLine ( "Tests cannot be run while program is executing" ) ;
2019-08-23 11:56:54 -07:00
return ;
}
String prevConfigName = scope String ( mConfigName ) ;
var workspaceOptions = GetCurWorkspaceOptions ( ) ;
if ( workspaceOptions . mBuildKind ! = . Test )
{
mMainFrame . mStatusBar . SelectConfig ( "Test" ) ;
}
workspaceOptions = GetCurWorkspaceOptions ( ) ;
if ( workspaceOptions . mBuildKind ! = . Test )
{
mMainFrame . mStatusBar . SelectConfig ( prevConfigName ) ;
2019-12-13 14:25:15 -08:00
OutputErrorLine ( "No valid Test workspace configuration exists" ) ;
2019-08-23 11:56:54 -07:00
return ;
}
mLastTestFailed = false ;
mTestManager = new TestManager ( ) ;
mTestManager . mPrevConfigName = new String ( prevConfigName ) ;
mTestManager . mDebug = debug ;
2019-12-13 14:25:15 -08:00
mTestManager . mIncludeIgnored = includeIgnored ;
2019-08-23 11:56:54 -07:00
if ( mOutputPanel ! = null )
mOutputPanel . Clear ( ) ;
OutputLine ( "Compiling for testing..." ) ;
if ( ! Compile ( . Test , null ) )
{
mTestManager . BuildFailed ( ) ;
}
2019-12-13 14:25:15 -08:00
if ( ! mTestManager . HasProjects )
{
OutputLineSmart ( "WARNING: No projects have a test configuration specified" ) ;
}
2019-08-23 11:56:54 -07:00
}
[IDECommand]
public void Cmd_TestEnableConsole ( )
{
let ideCommand = gApp . mCommands . mCommandMap [ "Test Enable Console" ] ;
ToggleCheck ( ideCommand . mMenuItem , ref mTestEnableConsole ) ;
}
public void CreateMenu ( )
{
scope AutoBeefPerf ( "IDEApp.CreateMenu" ) ;
SysMenu root = mMainWindow . mSysMenu ;
String keyStr = scope String ( ) ;
SysMenu AddMenuItem ( SysMenu menu , String dispString , String cmdName , MenuItemUpdateHandler menuItemUpdateHandler = null ,
SysBitmap bitmap = null , bool enabled = true , int32 checkState = - 1 , bool radioCheck = false )
{
let ideCommand = mCommands . mCommandMap [ cmdName ] ;
if ( ideCommand ! = null )
{
keyStr . Clear ( ) ;
ideCommand . ToString ( keyStr ) ;
keyStr . Insert ( 0 , "#" ) ;
}
let itemMenu = menu . AddMenuItem ( dispString , ( ideCommand ! = null ) ? keyStr : null , new ( evt ) = > ideCommand . mAction ( ) , menuItemUpdateHandler , bitmap , enabled , checkState , radioCheck ) ;
if ( ideCommand ! = null )
{
ideCommand . mMenuItem = itemMenu ;
}
return itemMenu ;
}
//////////
SysMenu subMenu = root . AddMenuItem ( "&File" ) ;
let newMenu = subMenu . AddMenuItem ( "&New" ) ;
AddMenuItem ( newMenu , "New &Workspace" , "New Workspace" ) ;
AddMenuItem ( newMenu , "New &Project" , "New Project" ) ;
AddMenuItem ( newMenu , "New &Debug Session" , "New Debug Session" ) ;
AddMenuItem ( newMenu , "New &File" , "New File" ) ;
let openMenu = subMenu . AddMenuItem ( "&Open" ) ;
//openMenu.AddMenuItem("&Open Workspace...", GetCmdKey("Open Workspace"), new (evt) => { OpenWorkspace(); } );
AddMenuItem ( openMenu , "Open &Workspace..." , "Open Workspace" ) ;
AddMenuItem ( openMenu , "Open &Project..." , "Open Project" ) ;
AddMenuItem ( openMenu , "Open &Debug Session..." , "Open Debug Session" ) ;
AddMenuItem ( openMenu , "Open &File..." , "Open File" ) ;
AddMenuItem ( openMenu , "&Open File in Workspace" , "Open File in Workspace" ) ;
AddMenuItem ( openMenu , "&Open Corresponding (cpp/h)" , "Open Corresponding" ) ;
AddMenuItem ( openMenu , "Open &Crash Dump..." , "Open Crash Dump" ) ;
let recentMenu = subMenu . AddMenuItem ( "Open &Recent" ) ;
mSettings . mRecentFiles . mRecents [ ( int ) RecentFiles . RecentKind . OpenedWorkspace ] . mMenu = recentMenu . AddMenuItem ( "Open Recent &Workspace" ) ;
mSettings . mRecentFiles . mRecents [ ( int ) RecentFiles . RecentKind . OpenedDebugSession ] . mMenu = recentMenu . AddMenuItem ( "Open Recent &Debug Session" ) ;
mSettings . mRecentFiles . mRecents [ ( int ) RecentFiles . RecentKind . OpenedFile ] . mMenu = recentMenu . AddMenuItem ( "Open Recent &File" ) ;
mSettings . mRecentFiles . mRecents [ ( int ) RecentFiles . RecentKind . OpenedCrashDump ] . mMenu = recentMenu . AddMenuItem ( "Open Recent &Crash Dump" ) ;
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" ) ;
AddMenuItem ( subMenu , "Close Workspace" , "Close Workspace" ) ;
AddMenuItem ( subMenu , "E&xit" , "Exit" ) ;
//////////
subMenu = root . AddMenuItem ( "&Edit" ) ;
AddMenuItem ( subMenu , "Quick &Find..." , "Find in Document" ) ;
AddMenuItem ( subMenu , "Quick &Replace..." , "Replace in Document" ) ;
AddMenuItem ( subMenu , "Find in &Files..." , "Find in Files" ) ;
AddMenuItem ( subMenu , "Replace in Files..." , "Replace in Files" ) ;
AddMenuItem ( subMenu , "Find Prev" , "Find Prev" ) ;
AddMenuItem ( subMenu , "Find Next" , "Find Next" ) ;
AddMenuItem ( subMenu , "Show &Current" , "Show Current" ) ;
AddMenuItem ( subMenu , "&Goto Line..." , "Goto Line" ) ;
AddMenuItem ( subMenu , "Goto &Method..." , "Goto Method" ) ;
AddMenuItem ( subMenu , "&Rename Symbol" , "Rename Symbol" ) ;
2019-09-23 14:55:26 -07:00
AddMenuItem ( subMenu , "Show Fi&xit" , "Show Fixit" ) ;
2019-08-23 11:56:54 -07:00
AddMenuItem ( subMenu , "Find &All References" , "Find All References" ) ;
AddMenuItem ( subMenu , "Find C&lass..." , "Find Class" ) ;
subMenu . AddMenuItem ( null ) ;
var encodingMenu = subMenu . AddMenuItem ( "Encoding" ) ;
var lineEndingMenu = encodingMenu . AddMenuItem ( "Line Ending" ) ;
void AddLineEndingKind ( String name , LineEndingKind lineEndingKind )
{
lineEndingMenu . AddMenuItem ( name , null ,
new ( menu ) = >
{
var sysMenu = ( SysMenu ) menu ;
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
if ( sourceViewPanel . mEditData . mLineEndingKind ! = lineEndingKind )
{
sourceViewPanel . EditWidget . Content . mData . mCurTextVersionId + + ;
sourceViewPanel . mEditData . mLineEndingKind = lineEndingKind ;
sysMenu . mParent . UpdateChildItems ( ) ;
}
}
} ,
new ( menu ) = >
{
var sysMenu = ( SysMenu ) menu ;
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
sysMenu . Modify ( null , null , null , true , ( sourceViewPanel . mEditData . mLineEndingKind = = lineEndingKind ) ? 1 : 0 , true ) ;
}
else
{
sysMenu . Modify ( null , null , null , false , 0 , true ) ;
}
} ) ;
}
AddLineEndingKind ( "Windows" , . CrLf ) ;
AddLineEndingKind ( "Unix" , . Lf ) ;
AddLineEndingKind ( "Mac OS 9" , . Cr ) ;
var bookmarkMenu = subMenu . AddMenuItem ( "Boo&kmarks" ) ;
AddMenuItem ( bookmarkMenu , "&Toggle Bookmark" , "Bookmark Toggle" ) ;
AddMenuItem ( bookmarkMenu , "&Next Bookmark" , "Bookmark Next" ) ;
AddMenuItem ( bookmarkMenu , "&Previous Bookmark" , "Bookmark Prev" ) ;
AddMenuItem ( bookmarkMenu , "&Clear Bookmarks" , "Bookmark Clear" ) ;
var advancedEditMenu = subMenu . AddMenuItem ( "Advanced" ) ;
AddMenuItem ( advancedEditMenu , "Make Uppercase" , "Make Uppercase" ) ;
AddMenuItem ( advancedEditMenu , "Make Lowercase" , "Make Lowercase" ) ;
mViewWhiteSpace . mMenu = AddMenuItem ( advancedEditMenu , "View White Space" , "View White Space" , null , null , true , mViewWhiteSpace . Bool ? 1 : 0 ) ;
AddMenuItem ( advancedEditMenu , "Reformat Document" , "Reformat Document" ) ;
2019-08-29 17:40:17 -07:00
if ( mSettings . mEnableDevMode )
{
subMenu . AddMenuItem ( null ) ;
var internalEditMenu = subMenu . AddMenuItem ( "Internal" ) ;
internalEditMenu . AddMenuItem ( "Hilight Cursor References" , null , new ( menu ) = > { ToggleCheck ( menu , ref gApp . mSettings . mEditorSettings . mHiliteCursorReferences ) ; } , null , null , true , gApp . mSettings . mEditorSettings . mHiliteCursorReferences ? 1 : 0 ) ;
internalEditMenu . AddMenuItem ( "Delayed Autocomplete" , null , new ( menu ) = > { ToggleCheck ( menu , ref gApp . mDbgDelayedAutocomplete ) ; } , null , null , true , gApp . mDbgDelayedAutocomplete ? 1 : 0 ) ;
}
2019-08-23 11:56:54 -07:00
//////////
subMenu = root . AddMenuItem ( "&View" ) ;
2020-01-06 13:49:35 -08:00
AddMenuItem ( subMenu , "A&utoComplete" , "Show Autocomplete Panel" ) ;
AddMenuItem ( subMenu , "&Auto Watches" , "Show Auto Watches" ) ;
AddMenuItem ( subMenu , "&Breakpoints" , "Show Breakpoints" ) ;
2019-08-23 11:56:54 -07:00
AddMenuItem ( subMenu , "&Call Stack" , "Show Call Stack" ) ;
2020-01-06 13:49:35 -08:00
AddMenuItem ( subMenu , "C&lass View" , "Show Class View" ) ;
AddMenuItem ( subMenu , "E&rrors" , "Show Errors" ) ;
AddMenuItem ( subMenu , "&Find Results" , "Show Find Results" ) ;
AddMenuItem ( subMenu , "&Immediate Window" , "Show Immediate" ) ;
2019-08-23 11:56:54 -07:00
AddMenuItem ( subMenu , "&Memory" , "Show Memory" ) ;
AddMenuItem ( subMenu , "Mo&dules" , "Show Modules" ) ;
AddMenuItem ( subMenu , "&Output" , "Show Output" ) ;
AddMenuItem ( subMenu , "&Profiler" , "Show Profiler" ) ;
2020-01-06 13:49:35 -08:00
AddMenuItem ( subMenu , "&Threads" , "Show Threads" ) ;
AddMenuItem ( subMenu , "&Watches" , "Show Watches" ) ;
AddMenuItem ( subMenu , "Work&space Explorer" , "Show Workspace Explorer" ) ;
2019-08-23 11:56:54 -07:00
subMenu . AddMenuItem ( null ) ;
AddMenuItem ( subMenu , "Next Document Panel" , "Next Document Panel" ) ;
AddMenuItem ( subMenu , "Navigate Backwards" , "Navigate Backwards" ) ;
AddMenuItem ( subMenu , "Navigate Forwards" , "Navigate Forwards" ) ;
//////////
subMenu = root . AddMenuItem ( "&Build" ) ;
AddMenuItem ( subMenu , "&Build Solution" , "Build Solution" ) ;
AddMenuItem ( subMenu , "&Clean" , "Clean" ) ;
AddMenuItem ( subMenu , "Clean Beef" , "Clean Beef" ) ;
//subMenu.AddMenuItem("Compile Current File", null, new (menu) => { CompileCurrentFile(); });
AddMenuItem ( subMenu , "Cancel Build" , "Cancel Build" , new ( menu ) = > { menu . SetDisabled ( ! IsCompiling ) ; } ) ;
2019-08-29 17:40:17 -07:00
if ( mSettings . mEnableDevMode )
{
var internalBuildMenu = subMenu . AddMenuItem ( "Internal" ) ;
internalBuildMenu . AddMenuItem ( "Autobuild (Debug)" , null , new ( menu ) = > { mDebugAutoBuild = ! mDebugAutoBuild ; } ) ;
internalBuildMenu . AddMenuItem ( "Autorun (Debug)" , null , new ( menu ) = > { mDebugAutoRun = ! mDebugAutoRun ; } ) ;
internalBuildMenu . AddMenuItem ( "Disable Compiling" , null , new ( menu ) = > { ToggleCheck ( menu , ref mDisableBuilding ) ; } , null , null , true , mDisableBuilding ? 1 : 0 ) ;
}
2019-08-23 11:56:54 -07:00
//////////
subMenu = root . AddMenuItem ( "&Debug" ) ;
AddMenuItem ( subMenu , "&Start Debugging" , "Start Debugging" ) ;
AddMenuItem ( subMenu , "Start Wit&hout Debugging" , "Start Without Debugging" ) ;
AddMenuItem ( subMenu , "&Launch Process..." , "Launch Process" ) ;
AddMenuItem ( subMenu , "&Attach to Process..." , "Attach to Process" ) ;
AddMenuItem ( subMenu , "&Stop Debugging" , "Stop Debugging" ) ;
AddMenuItem ( subMenu , "Break All" , "Break All" ) ;
AddMenuItem ( subMenu , "Remove All Breakpoints" , "Remove All Breakpoints" ) ;
AddMenuItem ( subMenu , "Show &Disassembly" , "Show Disassembly" ) ;
AddMenuItem ( subMenu , "&Quick Watch" , "Show QuickWatch" ) ;
AddMenuItem ( subMenu , "&Profile" , "Profile" ) ;
subMenu . AddMenuItem ( null ) ;
AddMenuItem ( subMenu , "Step Into" , "Step Into" ) ;
AddMenuItem ( subMenu , "Step Over" , "Step Over" ) ;
AddMenuItem ( subMenu , "Step Out" , "Step Out" ) ;
subMenu . AddMenuItem ( null ) ;
AddMenuItem ( subMenu , "To&ggle Breakpoint" , "Breakpoint Toggle" ) ;
AddMenuItem ( subMenu , "Toggle Thread Breakpoint" , "Breakpoint Toggle Thread" ) ;
var newBreakpointMenu = subMenu . AddMenuItem ( "New &Breakpoint" ) ;
AddMenuItem ( newBreakpointMenu , "&Memory Breakpoint..." , "Breakpoint Memory" ) ;
AddMenuItem ( newBreakpointMenu , "&Symbol Breakpoint..." , "Breakpoint Symbol" ) ;
2019-08-29 17:40:17 -07:00
if ( mSettings . mEnableDevMode )
{
var internalDebugMenu = subMenu . AddMenuItem ( "Internal" ) ;
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" ) ; } ) ;
2019-09-23 11:50:11 -07:00
internalDebugMenu . AddMenuItem ( "Show Welcome" , null , new ( menu ) = > { ShowWelcome ( ) ; } ) ;
2019-08-29 17:40:17 -07:00
internalDebugMenu . AddMenuItem ( "Exit Test" , null , new ( menu ) = > { ExitTest ( ) ; } ) ;
internalDebugMenu . AddMenuItem ( "Run Test" , null , new ( menu ) = > { mRunTest = ! mRunTest ; } ) ;
internalDebugMenu . AddMenuItem ( "GC Collect" , null , new ( menu ) = >
{
var profileId = Profiler . StartSampling ( ) . GetValueOrDefault ( ) ;
for ( int i < 10 )
GC . Collect ( false ) ;
if ( profileId ! = 0 )
profileId . Dispose ( ) ;
} ) ;
internalDebugMenu . AddMenuItem ( "Enable GC Collect" , null , new ( menu ) = > { ToggleCheck ( menu , ref mEnableGCCollect ) ; EnableGCCollect = mEnableGCCollect ; } , null , null , true , mEnableGCCollect ? 1 : 0 ) ;
internalDebugMenu . AddMenuItem ( "Fast Updating" , null , new ( menu ) = > { ToggleCheck ( menu , ref mDbgFastUpdate ) ; EnableGCCollect = mDbgFastUpdate ; } , null , null , true , mDbgFastUpdate ? 1 : 0 ) ;
internalDebugMenu . AddMenuItem ( "Alloc String" , null , new ( menu ) = > { new String ( "Alloc String" ) ; } ) ;
internalDebugMenu . AddMenuItem ( "Perform Long Update Checks" , null , new ( menu ) = >
{
bool wantsLongUpdateCheck = mLongUpdateProfileId ! = 0 ;
ToggleCheck ( menu , ref wantsLongUpdateCheck ) ;
mLastLongUpdateCheck = 0 ;
mLastLongUpdateCheckError = 0 ;
if ( wantsLongUpdateCheck )
mLongUpdateProfileId = Profiler . StartSampling ( "LongUpdate" ) ;
else
{
mLongUpdateProfileId . Dispose ( ) ;
mLongUpdateProfileId = 0 ;
}
} , null , null , true , ( mLongUpdateProfileId ! = 0 ) ? 1 : 0 ) ;
}
2019-08-23 11:56:54 -07:00
//////////
var testMenu = root . AddMenuItem ( "&Test" ) ;
var testRunMenu = testMenu . AddMenuItem ( "&Run" ) ;
2019-12-13 14:25:15 -08:00
AddMenuItem ( testRunMenu , "&Normal Tests" , "Run Normal Tests" ) ;
2019-08-23 11:56:54 -07:00
AddMenuItem ( testRunMenu , "&All Tests" , "Run All Tests" ) ;
var testDebugMenu = testMenu . AddMenuItem ( "&Debug" ) ;
2019-12-13 14:25:15 -08:00
AddMenuItem ( testDebugMenu , "&Normal Tests" , "Debug Normal Tests" ) ;
2019-08-23 11:56:54 -07:00
AddMenuItem ( testDebugMenu , "&All Tests" , "Debug All Tests" ) ;
AddMenuItem ( testMenu , "Enable Console" , "Test Enable Console" , null , null , true , mTestEnableConsole ? 1 : 0 ) ;
//////////
mWindowMenu = root . AddMenuItem ( "&Window" ) ;
AddMenuItem ( mWindowMenu , "&Close" , "Close Window" ) ;
AddMenuItem ( mWindowMenu , "&Close All" , "Close All Windows" ) ;
AddMenuItem ( mWindowMenu , "&Split View" , "Split View" ) ;
subMenu = root . AddMenuItem ( "&Help" ) ;
AddMenuItem ( subMenu , "&About" , "About" ) ;
}
IDETabbedView CreateTabbedView ( )
{
var tabbedView = new IDETabbedView ( ) ;
2019-09-29 07:44:23 -07:00
tabbedView . mSharedData . mOpenNewWindowDelegate . Add ( new ( fromTabbedView , newWindow ) = > SetupNewWindow ( newWindow , true ) ) ;
2019-08-23 11:56:54 -07:00
tabbedView . mSharedData . mTabbedViewClosed . Add ( new ( tabbedView ) = >
{
if ( tabbedView = = mActiveDocumentsTabbedView )
mActiveDocumentsTabbedView = null ;
} ) ;
return tabbedView ;
}
2019-09-29 07:44:23 -07:00
public void SetupNewWindow ( WidgetWindow window , bool isMainWindow )
2019-08-23 11:56:54 -07:00
{
window . mOnWindowKeyDown . Add ( new = > SysKeyDown ) ;
2019-09-29 07:44:23 -07:00
if ( isMainWindow )
window . mOnWindowCloseQuery . Add ( new = > SecondaryAllowClose ) ;
2019-08-23 11:56:54 -07:00
}
DarkTabbedView FindDocumentTabbedView ( )
{
for ( int32 windowIdx = 0 ; windowIdx < mWindows . Count ; windowIdx + + )
{
var window = mWindows [ windowIdx ] ;
var widgetWindow = window as WidgetWindow ;
if ( widgetWindow ! = null )
{
var darkDockingFrame = widgetWindow . mRootWidget as DarkDockingFrame ;
if ( widgetWindow = = mMainWindow )
darkDockingFrame = mDockingFrame ;
//DarkTabbedView documentTabbedView = null;
DarkTabbedView documentTabbedView = null ;
if ( darkDockingFrame ! = null )
{
darkDockingFrame . WithAllDockedWidgets ( scope [ & ] ( dockedWidget ) = >
{
bool hadSource = false ;
var tabbedView = dockedWidget as DarkTabbedView ;
if ( tabbedView ! = null )
{
tabbedView . WithTabs ( scope [ & ] ( tab ) = >
{
if ( documentTabbedView ! = null )
return ;
var content = tab . mContent ;
if ( ( content is SourceViewPanel ) | |
( content is DisassemblyPanel ) )
hadSource = true ;
} ) ;
}
if ( hadSource )
documentTabbedView = tabbedView ;
} ) ;
}
if ( documentTabbedView ! = null )
return documentTabbedView ;
}
}
return null ;
}
public DarkTabbedView GetDefaultDocumentTabbedView ( )
{
if ( ( mActiveDocumentsTabbedView = = null ) | | ( mActiveDocumentsTabbedView . mParent = = null ) )
{
mActiveDocumentsTabbedView = CreateTabbedView ( ) ;
mActiveDocumentsTabbedView . SetRequestedSize ( 150 , 150 ) ;
mActiveDocumentsTabbedView . mIsFillWidget = true ;
mActiveDocumentsTabbedView . mAutoClose = false ;
if ( ( mProjectPanel ! = null ) & & ( mProjectPanel . mWidgetWindow ! = null ) )
{
if ( var tabbedView = mProjectPanel . mParent as TabbedView )
{
if ( var dockingFrame = tabbedView . mParent as DockingFrame )
{
dockingFrame . AddDockedWidget ( mActiveDocumentsTabbedView , tabbedView , DockingFrame . WidgetAlign . Right ) ;
return mActiveDocumentsTabbedView ;
}
}
}
mDockingFrame . AddDockedWidget ( mActiveDocumentsTabbedView , null , DockingFrame . WidgetAlign . Right ) ;
}
return mActiveDocumentsTabbedView ;
}
void PopulateDocumentMenu ( DarkTabbedView tabbedView , Menu menu )
{
WithTabs ( scope ( tab ) = >
{
var menuItem = menu . AddItem ( tab . mLabel ) ;
menuItem . mOnMenuItemSelected . Add ( new ( selMenuItem ) = >
{
TabbedView . TabButton activateTab = tab ;
activateTab . Activate ( ) ;
} ) ;
} ) ;
}
public void WithDocumentTabbedViews ( Action < DarkTabbedView > func )
{
for ( int32 windowIdx = 0 ; windowIdx < mWindows . Count ; windowIdx + + )
{
var window = mWindows [ windowIdx ] ;
var widgetWindow = window as WidgetWindow ;
if ( widgetWindow ! = null )
{
var darkDockingFrame = widgetWindow . mRootWidget as DarkDockingFrame ;
if ( widgetWindow = = mMainWindow )
darkDockingFrame = mDockingFrame ;
if ( darkDockingFrame ! = null )
{
darkDockingFrame . WithAllDockedWidgets ( scope ( dockedWidget ) = >
{
var tabbedView = dockedWidget as DarkTabbedView ;
if ( tabbedView ! = null )
func ( tabbedView ) ;
} ) ;
}
}
}
}
public void EnsureDocumentArea ( )
{
GetDefaultDocumentTabbedView ( ) ;
}
public Widget GetActivePanel ( )
{
if ( mRunningTestScript )
return mLastActivePanel ;
for ( var window in mWindows )
{
if ( ! window . mHasFocus )
continue ;
var widgetWindow = window as WidgetWindow ;
if ( widgetWindow ! = null )
{
var focusWidget = widgetWindow . mFocusWidget ;
if ( ( focusWidget = = null ) & & ( var hoverWatch = widgetWindow . mRootWidget as HoverWatch ) )
{
return hoverWatch . mTextPanel ;
}
while ( ( focusWidget ! = null ) & & ( focusWidget . mParent ! = null ) )
{
if ( focusWidget . mParent is TabbedView )
return focusWidget ;
focusWidget = focusWidget . mParent ;
}
}
}
return null ;
}
2019-09-29 07:44:23 -07:00
public SourceEditWidgetContent GetActiveSourceEditWidgetContent ( )
{
let activeWindow = GetActiveWindow ( ) ;
if ( activeWindow . mFocusWidget ! = null )
{
if ( let editWidget = activeWindow . mFocusWidget as EditWidget )
{
let sewc = editWidget . mEditWidgetContent as SourceEditWidgetContent ;
if ( sewc ! = null )
return sewc ;
}
}
var activeTextPanel = GetActivePanel ( ) as TextPanel ;
if ( activeTextPanel ! = null )
{
return activeTextPanel . EditWidget . mEditWidgetContent as SourceEditWidgetContent ;
}
return null ;
}
2019-09-05 08:18:24 -07:00
public WidgetWindow GetActiveWindow ( )
2019-08-23 11:56:54 -07:00
{
for ( let window in mWindows )
if ( window . mHasFocus )
2019-09-05 08:18:24 -07:00
{
var result = window ;
while ( ( result . mWindowFlags . HasFlag ( . Modal ) ) & & ( result . mParent ! = null ) )
result = result . mParent ;
return result as WidgetWindow ;
}
2019-08-23 11:56:54 -07:00
return mMainWindow ;
}
public Widget GetActiveDocumentPanel ( )
{
var activePanel = GetActivePanel ( ) ;
if ( ( activePanel is SourceViewPanel ) | | ( activePanel is DisassemblyPanel ) )
return activePanel ;
return null ;
}
public void WithTabs ( Action < TabbedView . TabButton > func )
{
WithDocumentTabbedViews ( scope ( documentTabbedView ) = >
{
documentTabbedView . WithTabs ( func ) ;
} ) ;
}
public TabbedView . TabButton GetTab ( Widget content )
{
TabbedView . TabButton tab = null ;
WithTabs ( scope [ & ] ( checkTab ) = >
{
if ( checkTab . mContent = = content )
tab = checkTab ;
} ) ;
return tab ;
}
public void WithSourceViewPanels ( Action < SourceViewPanel > func )
{
WithTabs ( scope ( tab ) = >
{
var sourceViewPanel = tab . mContent as SourceViewPanel ;
if ( sourceViewPanel ! = null )
func ( sourceViewPanel ) ;
} ) ;
}
TabbedView . TabButton SetupTab ( TabbedView tabView , String name , float width , Widget content , bool ownsContent ) // 2
{
TabbedView . TabButton tabButton = tabView . AddTab ( name , width , content , ownsContent ) ;
if ( ( var panel = content as Panel ) & & ( var darkTabButton = tabButton as DarkTabbedView . DarkTabButton ) )
{
darkTabButton . mTabWidthOffset = panel . TabWidthOffset ;
}
tabButton . mCloseClickedEvent . Add ( new ( ) = > CloseDocument ( content ) ) ; // 1
return tabButton ;
}
public DisassemblyPanel ShowDisassemblyPanel ( bool clearData = false )
{
DisassemblyPanel disassemblyPanel = null ;
WithTabs ( scope [ & ] ( tab ) = >
{
if ( ( disassemblyPanel = = null ) & & ( tab . mContent is DisassemblyPanel ) )
{
disassemblyPanel = ( DisassemblyPanel ) tab . mContent ;
disassemblyPanel . ClearQueuedData ( ) ;
tab . Activate ( ) ;
}
} ) ;
if ( disassemblyPanel ! = null )
return disassemblyPanel ;
TabbedView tabbedView = GetDefaultDocumentTabbedView ( ) ;
disassemblyPanel = new DisassemblyPanel ( ) ;
//diassemblyPanel.Show(filePath);
var newTabButton = new SourceViewTab ( ) ;
newTabButton . Label = DisassemblyPanel . sPanelName ;
newTabButton . mWantWidth = newTabButton . GetWantWidth ( ) ;
newTabButton . mHeight = tabbedView . mTabHeight ;
newTabButton . mContent = disassemblyPanel ;
tabbedView . AddTab ( newTabButton ) ;
newTabButton . mCloseClickedEvent . Add ( new ( ) = > CloseDocument ( disassemblyPanel ) ) ;
newTabButton . Activate ( ) ;
//diassemblyPanel.FocusEdit();
mLastActivePanel = disassemblyPanel ;
return disassemblyPanel ;
}
public class SourceViewTab : DarkTabbedView . DarkTabButton
{
public float GetWantWidth ( )
{
return DarkTheme . sDarkTheme . mSmallFont . GetWidth ( mLabel ) + DarkTheme . GetScaled ( 40 ) ;
}
public override void Activate ( bool setFocus )
{
base . Activate ( setFocus ) ;
if ( ( mUpdateCnt > 0 ) & & ( mTabbedView . mUpdateCnt = = 0 ) & & ( mTabbedView . mTabs . Count = = 1 ) )
{
//bool isDocument = mContent;
// We were dropped onto a new tabbed view, mark it as a document frame
bool isFillWidget = false ;
if ( mContent is SourceViewPanel )
isFillWidget = true ;
if ( mContent is DisassemblyPanel )
isFillWidget = true ;
if ( isFillWidget )
{
mTabbedView . mIsFillWidget = true ;
mTabbedView . mHasFillWidget = true ;
}
}
}
public override void Draw ( Graphics g )
{
base . Draw ( g ) ;
if ( mWidth < mWantWidth / 2 )
return ;
var sourceViewPanel = mContent as SourceViewPanel ;
if ( sourceViewPanel ! = null )
{
if ( sourceViewPanel . HasUnsavedChanges ( ) )
{
g . SetFont ( IDEApp . sApp . mTinyCodeFont ) ;
g . DrawString ( "*" , mWantWidth - DarkTheme . sUnitSize + GS ! ( 2 ) , 0 ) ;
}
else if ( sourceViewPanel . mLoadFailed )
{
g . SetFont ( IDEApp . sApp . mCodeFont ) ;
using ( g . PushColor ( 0xFFFF8080 ) )
g . DrawString ( "!" , mWantWidth - DarkTheme . sUnitSize , 0 ) ;
}
}
else if ( let findResultsPanel = mContent as FindResultsPanel )
{
if ( findResultsPanel . IsSearching )
{
g . SetFont ( IDEApp . sApp . mTinyCodeFont ) ;
String rotChars = @"/-\|" ;
StringView sv = . ( rotChars , ( mUpdateCnt / 16 ) % 4 , 1 ) ;
g . DrawString ( sv , mWantWidth - DarkTheme . sUnitSize , 0 ) ;
}
}
else if ( let profilePanel = mContent as ProfilePanel )
{
if ( profilePanel . IsSamplingHidden )
{
//using (g.PushColor(((mUpdateCnt / 20) % 2 == 0) ? 0xFFF0F0F0 : 0xFFFFFFFF))
using ( g . PushColor ( 0x80FFFFFF ) )
g . Draw ( DarkTheme . sDarkTheme . GetImage ( . RedDot ) , GS ! ( 8 ) , GS ! ( 0 ) ) ;
}
}
}
public override void MouseDown ( float x , float y , int32 btn , int32 btnCount )
{
base . MouseDown ( x , y , btn , btnCount ) ;
if ( btn = = 1 )
{
Menu menu = new Menu ( ) ;
if ( var sourceViewPanel = mContent as SourceViewPanel )
{
var item = menu . AddItem ( "Copy Full Path" ) ;
item . mOnMenuItemSelected . Add ( new ( menu ) = >
{
gApp . SetClipboardText ( sourceViewPanel . mFilePath ) ;
} ) ;
item = menu . AddItem ( "Open Containing Folder" ) ;
item . mOnMenuItemSelected . Add ( new ( menu ) = >
{
let directory = scope String ( ) ;
Path . GetDirectoryPath ( sourceViewPanel . mFilePath , directory ) ;
ProcessStartInfo procInfo = scope ProcessStartInfo ( ) ;
procInfo . UseShellExecute = true ;
procInfo . SetFileName ( directory ) ;
let process = scope SpawnedProcess ( ) ;
process . Start ( procInfo ) . IgnoreError ( ) ;
} ) ;
}
if ( menu . mItems . Count > 0 )
{
SelfToRootTranslate ( x , mHeight , var windowX , var windowY ) ;
MenuWidget menuWidget = DarkTheme . sDarkTheme . CreateMenuWidget ( menu ) ;
menuWidget . Init ( mWidgetWindow . mRootWidget , windowX , windowY ) ;
}
else
delete menu ;
}
if ( ( mIsRightTab ) & & ( btn = = 0 ) & & ( btnCount > 1 ) )
{
IDEApp . sApp . MakeTabPermanent ( this ) ;
}
}
public override void Update ( )
{
base . Update ( ) ;
Point point ;
if ( DarkTooltipManager . CheckMouseover ( this , 25 , out point ) )
{
var sourceViewPanel = mContent as SourceViewPanel ;
if ( sourceViewPanel ! = null )
DarkTooltipManager . ShowTooltip ( sourceViewPanel . mFilePath , this , point . x , 14 ) ;
}
}
}
public SourceViewPanel FindSourceViewPanel ( String filePath )
{
if ( filePath = = null )
return null ;
String useFilePath = scope String ( filePath ) ;
if ( ! IDEUtils . FixFilePath ( useFilePath ) )
return null ;
SourceViewPanel sourceViewPanel = null ;
WithTabs ( scope [ & ] ( tabButton ) = >
{
if ( ( sourceViewPanel = = null ) & & ( tabButton . mContent is SourceViewPanel ) )
{
var checkedResourceViewPanel = ( SourceViewPanel ) tabButton . mContent ;
if ( Path . Equals ( checkedResourceViewPanel . mFilePath , useFilePath ) )
sourceViewPanel = checkedResourceViewPanel ;
}
} ) ;
return sourceViewPanel ;
}
void MakeTabPermanent ( DarkTabbedView . DarkTabButton tabButton )
{
tabButton . mDragHelper . mAllowDrag = false ;
tabButton . mTextColor = Color . White ;
tabButton . mIsRightTab = false ;
var darkTabbedView = ( DarkTabbedView ) tabButton . mTabbedView ;
darkTabbedView . SetRightTab ( null , false ) ;
darkTabbedView . AddTab ( tabButton ) ;
tabButton . Activate ( ) ;
}
public SourceEditWidget CreateSourceEditWidget ( SourceEditWidget refEditWidget = null )
{
var editWidget = new SourceEditWidget ( null , refEditWidget ) ;
editWidget . Content . mIsMultiline = true ;
editWidget . Content . mWordWrap = false ;
editWidget . InitScrollbars ( true , true ) ;
var editWidgetContent = ( SourceEditWidgetContent ) editWidget . Content ;
//mEditWidget.mVertScrollbar.mScrollIncrement = editWidgetContent.mFont.GetLineSpacing();
editWidgetContent . mHiliteColor = 0xFF384858 ;
editWidgetContent . mUnfocusedHiliteColor = 0x80384858 ;
return editWidget ;
}
2019-11-22 12:27:13 -08:00
public bool CreateEditDataEditWidget ( FileEditData editData )
2019-08-23 11:56:54 -07:00
{
if ( editData . mEditWidget ! = null )
return true ;
var text = scope String ( ) ;
if ( LoadTextFile ( editData . mFilePath , text , true , scope ( ) = >
{
for ( int i < text . Length )
{
char8 c = text [ i ] ;
if ( c = = '\r' )
{
2019-10-05 10:24:58 -07:00
char8 nextC = 0 ;
if ( i < text . Length - 1 )
{
nextC = text [ + + i ] ;
if ( nextC = = 0 )
{
if ( i < text . Length - 2 )
nextC = text [ + + i ] ;
}
}
if ( nextC = = '\n' )
2019-08-23 11:56:54 -07:00
editData . mLineEndingKind = . CrLf ;
else
editData . mLineEndingKind = . Cr ;
break ;
}
else if ( c = = '\n' )
{
editData . mLineEndingKind = . Lf ;
break ;
}
}
2019-11-22 12:27:13 -08:00
editData . BuildHash ( text ) ;
2019-08-23 11:56:54 -07:00
} ) case . Err )
return false ;
mFileWatcher . FileIsValid ( editData . mFilePath ) ;
using ( mMonitor . Enter ( ) )
{
if ( editData . mEditWidget ! = null )
return true ;
editData . mEditWidget = CreateSourceEditWidget ( ) ;
editData . mEditWidget . Content . AppendText ( text ) ;
editData . mOwnsEditWidget = true ;
editData . mLastFileTextVersion = editData . mEditWidget . Content . mData . mCurTextVersionId ;
editData . mEditWidgetCreatedEvent ( ) ;
}
mFileDataDataRevision + + ;
return true ;
}
2019-11-22 12:27:13 -08:00
public FileEditData GetEditData ( String filePath , bool createEditData = true , bool createEditDataWidget = true )
2019-08-23 11:56:54 -07:00
{
FileEditData editData ;
using ( mMonitor . Enter ( ) )
{
String fixedFilePath = scope String ( filePath ) ;
IDEUtils . FixFilePath ( fixedFilePath ) ;
if ( ! Environment . IsFileSystemCaseSensitive )
fixedFilePath . ToUpper ( ) ;
if ( ! mFileEditData . TryGetValue ( fixedFilePath , out editData ) )
{
if ( createEditData )
{
editData = new FileEditData ( ) ;
editData . mFilePath = new String ( filePath ) ;
mFileEditData . Add ( new String ( fixedFilePath ) , editData ) ;
}
}
}
if ( createEditDataWidget )
2019-11-22 12:27:13 -08:00
CreateEditDataEditWidget ( editData ) ;
2019-08-23 11:56:54 -07:00
return editData ;
}
public void RenameEditData ( String oldPath , String newPath )
{
using ( mMonitor . Enter ( ) )
{
String oldFixedFilePath = scope String ( oldPath ) ;
IDEUtils . FixFilePath ( oldFixedFilePath ) ;
if ( ! Environment . IsFileSystemCaseSensitive )
oldFixedFilePath . ToUpper ( ) ;
String newFixedFilePath = scope String ( newPath ) ;
IDEUtils . FixFilePath ( newFixedFilePath ) ;
if ( ! Environment . IsFileSystemCaseSensitive )
newFixedFilePath . ToUpper ( ) ;
String outKey ;
FileEditData editData ;
if ( mFileEditData . TryGetValue ( oldFixedFilePath , out outKey , out editData ) )
{
mFileEditData . Remove ( oldFixedFilePath ) ;
delete outKey ;
editData . mFilePath . Set ( newPath ) ;
String * newKeyPtr ;
FileEditData * newEditDataPtr ;
if ( mFileEditData . TryAdd ( newFixedFilePath , out newKeyPtr , out newEditDataPtr ) )
{
* newKeyPtr = new String ( newFixedFilePath ) ;
* newEditDataPtr = editData ;
}
else
{
let oldEditData = * newEditDataPtr ;
// This can happen if we rename a file to the name of a file that used to exist and is bound to
// another source view panel
WithTabs ( scope ( tab ) = >
{
if ( var sourceViewPanel = tab . mContent as SourceViewPanel )
{
if ( sourceViewPanel . mEditData = = oldEditData )
{
tab . mTabbedView . RemoveTab ( tab , true ) ;
}
}
} ) ;
for ( var projectSource in oldEditData . mProjectSources )
projectSource . mEditData = editData ;
gApp . ProcessDeferredDeletes ( ) ;
oldEditData . Deref ( ) ;
//editData.Deref();
* newEditDataPtr = editData ;
}
}
}
}
public void DeleteEditData ( FileEditData editData )
{
if ( editData . mOwnsEditWidget )
{
delete editData . mEditWidget ;
editData . mEditWidget = null ;
editData . mOwnsEditWidget = false ;
}
//mFileEditData.Remove(editData);
//delete editData;
}
public FileEditData GetEditData ( ProjectSource projectSource , bool createEditWidget = true , SourceHash . Kind hashKind = . MD5 )
{
using ( mMonitor . Enter ( ) )
{
if ( projectSource . mEditData = = null )
{
String filePath = scope String ( ) ;
projectSource . GetFullImportPath ( filePath ) ;
var editData = GetEditData ( filePath , true , false ) ;
if ( editData ! = null )
{
editData . mProjectSources . Add ( projectSource ) ;
editData . Ref ( ) ;
projectSource . mEditData = editData ;
}
}
/ * editData = CreateEditData ( filePath ) ;
/ * if ( projectSource . mSavedContent = = null )
{
editData = CreateEditData ( filePath ) ;
}
else
{
editData = new FileEditData ( ) ;
editData . mFilePath = new String ( filePath ) ;
editData . mEditWidget = CreateSourceEditWidget ( ) ;
editData . mEditWidget . Content . AppendText ( projectSource . mSavedContent ) ;
editData . mEditWidget . Content . mData . mTextIdData . DuplicateFrom ( projectSource . mSavedCharIdData ) ;
editData . mOwnsEditWidget = true ;
} * /
if ( editData ! = null )
{
editData . Ref ( ) ;
mFileEditData . Add ( editData ) ;
projectSource . mEditData = editData ;
projectSource . mEditData . mLastFileTextVersion = projectSource . mEditData . mEditWidget . Content . mData . mCurTextVersionId ;
}
}
return projectSource . mEditData ; * /
}
if ( createEditWidget )
CreateEditDataEditWidget ( projectSource . mEditData ) ;
return projectSource . mEditData ;
}
public SourceViewPanel ShowSourceFile ( String filePath , ProjectSource projectSource = null , SourceShowType showType = SourceShowType . ShowExisting , bool setFocus = true )
{
//TODO: PUT BACK!
//return null;
# unwarn
String useFilePath = filePath ;
var useProjectSource = projectSource ;
if ( ( useFilePath = = null ) & & ( useProjectSource ! = null ) )
{
useFilePath = scope : : String ( ) ;
useProjectSource . GetFullImportPath ( useFilePath ) ;
}
else if ( useFilePath ! = null )
{
useFilePath = scope : : String ( useFilePath ) ;
}
if ( ( useFilePath ! = null ) & & ( ! IDEUtils . FixFilePath ( useFilePath ) ) )
return null ;
if ( ( useFilePath = = null ) & ( showType ! = . New ) )
return null ;
SourceViewPanel sourceViewPanel = null ;
DarkTabbedView . DarkTabButton sourceViewPanelTab = null ;
if ( ( useProjectSource = = null ) & & ( useFilePath ! = null ) )
{
useProjectSource = FindProjectSourceItem ( useFilePath ) ;
if ( useProjectSource ! = null )
{
var projectSourcePath = scope : : String ( ) ;
useProjectSource . GetFullImportPath ( projectSourcePath ) ;
useFilePath = projectSourcePath ;
}
}
if ( showType ! = SourceShowType . New )
{
Action < TabbedView . TabButton > tabFunc = scope [ & ] ( tabButton ) = >
{
var darkTabButton = ( DarkTabbedView . DarkTabButton ) tabButton ;
if ( tabButton . mContent is SourceViewPanel )
{
var checkSourceViewPanel = ( SourceViewPanel ) tabButton . mContent ;
if ( checkSourceViewPanel . FileNameMatches ( useFilePath ) )
{
if ( sourceViewPanel ! = null )
{
// Already found one that matches our active tabbed view?
if ( sourceViewPanelTab . mTabbedView = = mActiveDocumentsTabbedView )
return ;
}
sourceViewPanel = checkSourceViewPanel ;
sourceViewPanelTab = darkTabButton ;
}
}
} ;
if ( ( showType = = . ShowExistingInActivePanel ) & & ( mActiveDocumentsTabbedView ! = null ) )
{
mActiveDocumentsTabbedView . WithTabs ( tabFunc ) ;
}
else
WithTabs ( tabFunc ) ;
if ( sourceViewPanelTab ! = null )
{
//matchedTabButton = tabButton;
if ( ( sourceViewPanelTab . mIsRightTab ) & & ( showType ! = SourceShowType . Temp ) )
{
MakeTabPermanent ( sourceViewPanelTab ) ;
}
if ( ( useProjectSource ! = null ) & &
( sourceViewPanel . mProjectSource ! = useProjectSource ) )
{
//TODO: Change project source in view
sourceViewPanel . AttachToProjectSource ( useProjectSource ) ;
//sourceViewPanel.mProjectSource = useProjectSource;
//sourceViewPanel.QueueFullRefresh(true);
}
2019-08-29 14:19:07 -07:00
if ( ( sourceViewPanel . mWidgetWindow ! = null ) & & ( ! HasModalDialogs ( ) ) & & ( ! mRunningTestScript ) )
2019-08-23 11:56:54 -07:00
sourceViewPanel . mWidgetWindow . SetForeground ( ) ;
sourceViewPanelTab . Activate ( setFocus ) ;
sourceViewPanelTab . mTabbedView . FinishTabAnim ( ) ;
if ( setFocus )
sourceViewPanel . FocusEdit ( ) ;
}
}
if ( sourceViewPanel ! = null )
return sourceViewPanel ;
//ShowSourceFile(filePath, projectSource, showTemp, setFocus);
DarkTabbedView tabbedView = GetDefaultDocumentTabbedView ( ) ;
sourceViewPanel = new SourceViewPanel ( ) ;
bool success ;
if ( useProjectSource ! = null )
{
success = sourceViewPanel . Show ( useProjectSource , ! mInitialized ) ;
}
else
success = sourceViewPanel . Show ( useFilePath , ! mInitialized ) ;
if ( ! success )
{
sourceViewPanel . Close ( ) ;
delete sourceViewPanel ;
return null ;
}
var newTabButton = new SourceViewTab ( ) ;
newTabButton . Label = "" ;
if ( useFilePath ! = null )
Path . GetFileName ( useFilePath , newTabButton . mLabel ) ;
else
newTabButton . mLabel . Set ( "untitled" ) ;
newTabButton . mWantWidth = newTabButton . GetWantWidth ( ) ;
newTabButton . mHeight = tabbedView . mTabHeight ;
newTabButton . mContent = sourceViewPanel ;
if ( showType = = SourceShowType . Temp )
{
2019-09-05 08:18:24 -07:00
let prevAutoClose = tabbedView . mAutoClose ;
defer { tabbedView . mAutoClose = prevAutoClose ; }
tabbedView . mAutoClose = false ;
2019-08-23 11:56:54 -07:00
if ( tabbedView . mRightTab ! = null )
{
CloseDocument ( tabbedView . mRightTab . mContent ) ;
Debug . Assert ( tabbedView . mRightTab = = null ) ;
}
newTabButton . mTextColor = 0xFFC8C8C8 ;
newTabButton . mIsRightTab = true ;
tabbedView . SetRightTab ( newTabButton ) ;
}
else
tabbedView . AddTab ( newTabButton ) ;
newTabButton . mCloseClickedEvent . Add ( new ( ) = > DocumentCloseClicked ( sourceViewPanel ) ) ;
newTabButton . Activate ( setFocus ) ;
if ( setFocus )
sourceViewPanel . FocusEdit ( ) ;
return sourceViewPanel ;
}
2019-12-21 05:48:44 -08:00
int GetRecentFilesIdx ( String filePath )
2019-08-23 11:56:54 -07:00
{
return mRecentlyDisplayedFiles . FindIndex ( scope ( item ) = > Path . Equals ( item , filePath ) ) ;
}
public void UpdateRecentFilesMenuItems ( List < String > filesList )
{
}
public void UpdateRecentDisplayedFilesMenuItems ( )
{
if ( mWindowMenu = = null )
return ;
RecentFiles . UpdateMenu ( mRecentlyDisplayedFiles , mWindowMenu , mRecentlyDisplayedFilesMenuItems , scope ( idx , sysMenu ) = >
{
sysMenu . mOnMenuItemSelected . Add ( new ( evt ) = > ShowRecentFile ( idx ) ) ;
} ) ;
}
public void UpdateRecentFileMenuItems ( RecentFiles . RecentKind recentKind )
{
let entry = mSettings . mRecentFiles . mRecents [ ( int ) recentKind ] ;
if ( entry . mMenu = = null )
return ;
RecentFiles . UpdateMenu ( entry . mList , entry . mMenu , entry . mMenuItems , scope ( idx , sysMenu ) = >
{
sysMenu . mOnMenuItemSelected . Add ( new ( evt ) = > ShowRecentFile ( recentKind , idx ) ) ;
} ) ;
}
public void UpdateRecentFileMenuItems ( )
{
if ( mWindowMenu = = null )
return ;
for ( RecentFiles . RecentKind recentKind = default ; recentKind < RecentFiles . RecentKind . COUNT ; recentKind + + )
{
UpdateRecentFileMenuItems ( recentKind ) ;
}
}
public void AddRecentFile ( RecentFiles . RecentKind recentKind , StringView file )
{
mSettings . mRecentFiles . Add ( recentKind , file ) ;
UpdateRecentFileMenuItems ( recentKind ) ;
}
public void AddToRecentDisplayedFilesList ( String path )
{
//int idx = mRecentFilesList.IndexOf(path);
RecentFiles . Add ( mRecentlyDisplayedFiles , path ) ;
UpdateRecentDisplayedFilesMenuItems ( ) ;
}
void ShowRecentFile ( int idx , bool setFocus = true )
{
String sourceFile = mRecentlyDisplayedFiles [ idx ] ;
if ( sourceFile = = DisassemblyPanel . sPanelName )
{
ShowDisassemblyPanel ( ) ;
return ;
}
ShowSourceFile ( sourceFile , null , SourceShowType . ShowExisting , setFocus ) ;
}
void ShowRecentFile ( RecentFiles . RecentKind recentKind , int idx , bool setFocus = true )
{
String filePath = mSettings . mRecentFiles . mRecents [ ( int ) recentKind ] . mList [ idx ] ;
switch ( recentKind )
{
case . OpenedFile :
ShowSourceFile ( filePath , null , SourceShowType . ShowExisting , setFocus ) ;
case . OpenedWorkspace :
var selectedPath = scope String ( ) . . AppendF ( filePath ) ;
selectedPath . Append ( Path . DirectorySeparatorChar ) ;
selectedPath . Append ( "BeefSpace.toml" ) ;
String . NewOrSet ! ( mDeferredOpenFileName , selectedPath ) ;
mDeferredOpen = . Workspace ;
case . OpenedCrashDump :
String . NewOrSet ! ( mDeferredOpenFileName , filePath ) ;
mDeferredOpen = . CrashDump ;
case . OpenedDebugSession :
String . NewOrSet ! ( mDeferredOpenFileName , filePath ) ;
mDeferredOpen = . DebugSession ;
default :
}
}
void DocumentCloseClicked ( Widget documentPanel )
{
var sourceViewPanel = documentPanel as SourceViewPanel ;
if ( sourceViewPanel = = null )
{
CloseDocument ( documentPanel ) ;
return ;
}
// This is a test
// This is a test
if ( ( ! sourceViewPanel . HasUnsavedChanges ( ) ) | | ( ! sourceViewPanel . IsLastViewOfData ( ) ) )
{
CloseDocument ( sourceViewPanel ) ;
return ;
}
// This is a test
String fileName = scope String ( ) ;
if ( sourceViewPanel . mFilePath ! = null )
Path . GetFileName ( sourceViewPanel . mFilePath , fileName ) ;
else
fileName . Append ( "untitled" ) ;
Dialog aDialog = ThemeFactory . mDefault . CreateDialog ( "Save file?" , StackStringFormat ! ( "Save changes to '{0}' before closing?" , fileName ) , DarkTheme . sDarkTheme . mIconWarning ) ;
aDialog . mDefaultButton = aDialog . AddButton ( "Save" , new ( evt ) = > { SaveFile ( sourceViewPanel ) ; CloseDocument ( sourceViewPanel ) ; } ) ;
aDialog . AddButton ( "Don't Save" , new ( evt ) = > CloseDocument ( sourceViewPanel ) ) ;
aDialog . mEscButton = aDialog . AddButton ( "Cancel" ) ;
aDialog . PopupWindow ( mMainWindow ) ;
}
public void CloseDocument ( Widget documentPanel )
{
bool hasFocus = false ;
var sourceViewPanel = documentPanel as SourceViewPanel ;
if ( ( documentPanel . mWidgetWindow ! = null ) & & ( documentPanel . mWidgetWindow . mFocusWidget ! = null ) )
{
if ( documentPanel . mWidgetWindow . mFocusWidget . HasParent ( documentPanel ) )
hasFocus = true ;
}
/ * if ( sourceViewPanel ! = null )
hasFocus = sourceViewPanel . mEditWidget . mHasFocus ; * /
if ( ( sourceViewPanel ! = null ) & & ( sourceViewPanel . HasUnsavedChanges ( ) ) )
{
// When we close a Beef file that has modified text, we need to revert by
// reparsing from the actual source file
if ( sourceViewPanel . mIsBeefSource )
{
mBfResolveHelper . DeferReparse ( sourceViewPanel . mFilePath , null ) ;
//mBfResolveHelper.DeferRefreshVisibleViews(null);
}
var projectSource = sourceViewPanel . mProjectSource ;
if ( projectSource ! = null )
{
var editData = GetEditData ( projectSource , true ) ;
if ( editData ! = null )
{
var editWidgetContent = editData . mEditWidget . mEditWidgetContent ;
//TODO: Verify this, once we have multiple panes allowed within a single SourceViewContent
if ( editWidgetContent . mData . mUsers . Count = = 1 ) // Is last view of data...
{
if ( ( editData ! = null ) & & ( editData . mHadRefusedFileChange ) )
{
// If we didn't take an external file change then closing the file means we want to revert
// our data to the version on disk
sourceViewPanel . Reload ( ) ;
}
else
{
// Undo until we either get to whatever the last saved state was, or until we
// get to a global action like renaming a symbol - we need to leave those
// so the global undo actually works if invoked from another file
while ( editData . HasTextChanged ( ) )
{
var nextUndoAction = editWidgetContent . mData . mUndoManager . GetLastUndoAction ( ) ;
if ( nextUndoAction = = null )
break ;
if ( nextUndoAction is UndoBatchEnd )
{
var undoBatchEnd = ( UndoBatchEnd ) nextUndoAction ;
if ( undoBatchEnd . Name . StartsWith ( "#" ) )
{
break ;
}
}
editWidgetContent . mData . mUndoManager . Undo ( ) ;
}
editWidgetContent . mData . mTextIdData . Prepare ( ) ;
}
}
}
}
}
DarkTabbedView tabbedView = null ;
DarkTabbedView . DarkTabButton tabButton = null ;
WithTabs ( scope [ & ] ( tab ) = >
{
if ( tab . mContent = = documentPanel )
{
tabbedView = ( DarkTabbedView ) tab . mTabbedView ;
tabButton = ( DarkTabbedView . DarkTabButton ) tab ;
}
} ) ;
Debug . Assert ( tabbedView ! = null ) ;
if ( tabbedView = = null )
return ;
2019-12-21 05:48:44 -08:00
int recentFileIdx = - 1 ;
2019-08-23 11:56:54 -07:00
if ( sourceViewPanel ! = null )
{
sourceViewPanel . Dispose ( ) ;
if ( sourceViewPanel . mFilePath ! = null )
recentFileIdx = GetRecentFilesIdx ( sourceViewPanel . mFilePath ) ;
}
/ * if ( tabButton . mIsRightTab )
tabbedView . SetRightTab ( null ) ;
else * /
if ( documentPanel is DisassemblyPanel )
recentFileIdx = GetRecentFilesIdx ( DisassemblyPanel . sPanelName ) ;
//mRecentFilesList.Remove(DisassemblyPanel.sPanelName);
if ( recentFileIdx ! = - 1 )
{
delete mRecentlyDisplayedFiles [ recentFileIdx ] ;
mRecentlyDisplayedFiles . RemoveAt ( recentFileIdx ) ;
UpdateRecentDisplayedFilesMenuItems ( ) ;
}
TabbedView . TabButton nextTab = null ;
bool foundRemovedTab = false ;
// Select the previous tab or the next one (if this is the first)
tabbedView . WithTabs ( scope [ & ] ( checkTab ) = >
{
if ( checkTab = = tabButton )
foundRemovedTab = true ;
else if ( ( ! foundRemovedTab ) | | ( nextTab = = null ) )
nextTab = checkTab ;
} ) ;
tabbedView . RemoveTab ( tabButton ) ;
if ( nextTab ! = null )
{
nextTab . Activate ( hasFocus ) ;
}
else if ( tabbedView . mAutoClose )
{
tabbedView . mParentDockingFrame . RemoveDockedWidget ( tabbedView ) ;
gApp . DeferDelete ( tabbedView ) ;
var documentTabbedView = FindDocumentTabbedView ( ) ;
if ( documentTabbedView ! = null )
{
Debug . Assert ( documentTabbedView ! = tabbedView ) ;
// If there is some OTHER document window them show that and remove this empty one
documentTabbedView . GetActiveTab ( ) . Activate ( ) ;
}
}
//var intDict = scope Dictionary<String, int>();
/ * if ( mRecentFilesList . Count > = 1 )
{
// Show second-last file
ShowRecentFile ( 0 , hasFocus ) ;
} * /
//var newActiveTab = tabbedView.GetActiveTab();
//if (newActiveTab != null)
//newActiveTab.mContent.SetFocus();
}
void TryCloseCurrentDocument ( )
{
var activeDocumentPanel = GetActiveDocumentPanel ( ) ;
if ( activeDocumentPanel ! = null )
{
if ( activeDocumentPanel is SourceViewPanel )
{
var sourceViewPanel = ( SourceViewPanel ) activeDocumentPanel ;
DocumentCloseClicked ( sourceViewPanel ) ;
return ;
}
CloseDocument ( activeDocumentPanel ) ;
return ;
}
var activePanel = GetActivePanel ( ) ;
if ( activePanel ! = null )
CloseDocument ( activePanel ) ;
}
void TryCloseAllDocuments ( )
{
var docPanels = scope List < Widget > ( ) ;
WithTabs ( scope [ & ] ( tab ) = >
{
if ( ( tab . mContent is SourceViewPanel ) | | ( tab . mTabbedView . mIsFillWidget ) )
{
docPanels . Add ( tab . mContent ) ;
}
} ) ;
for ( var docPanel in docPanels )
DocumentCloseClicked ( docPanel ) ;
}
void SplitView ( )
{
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel ! = null )
{
sourceViewPanel . SplitView ( ) ;
}
}
[IDECommand]
void CloseCurrentDocument ( )
{
var activeDocumentPanel = GetActiveDocumentPanel ( ) ;
if ( activeDocumentPanel ! = null )
CloseDocument ( activeDocumentPanel ) ;
}
public SourceViewPanel ShowProjectItem ( ProjectItem projectItem , bool showTemp = true , bool setFocus = true )
{
if ( projectItem is ProjectSource )
{
var projectSource = ( ProjectSource ) projectItem ;
var fullPath = scope String ( ) ;
projectSource . GetFullImportPath ( fullPath ) ;
return ShowSourceFile ( fullPath , projectSource , showTemp ? SourceShowType . Temp : SourceShowType . ShowExistingInActivePanel , setFocus ) ;
}
return null ;
}
public SourceViewPanel ShowSourceFileLocation ( String filePath , int showHotIdx , int refHotIdx , int line , int column , LocatorType hilitePosition , bool showTemp = false )
{
var sourceViewPanel = ShowSourceFile ( filePath , null , showTemp ? SourceShowType . Temp : SourceShowType . ShowExisting ) ;
if ( sourceViewPanel = = null )
return null ;
sourceViewPanel . ShowHotFileIdx ( showHotIdx ) ;
sourceViewPanel . ShowFileLocation ( refHotIdx , Math . Max ( 0 , line ) , Math . Max ( 0 , column ) , hilitePosition ) ;
return sourceViewPanel ;
}
public SourceViewPanel ShowSourceFileLocation ( String filePath , int32 cursorIdx , LocatorType hilitePosition )
{
var sourceViewPanel = ShowSourceFile ( filePath ) ;
sourceViewPanel . ShowFileLocation ( cursorIdx , hilitePosition ) ;
return sourceViewPanel ;
}
public void ShowPCLocation ( int32 stackIdx , bool onlyShowCurrent = false , bool wantShowSource = false , bool wantShowDisassembly = false , bool setFocus = true )
{
if ( stackIdx = = - 1 )
return ;
ClearDeferredUserRequest ( ) ;
int addr ;
String filePath = scope String ( ) ;
int hotIdx ;
int defLineStart ;
int defLineEnd ;
int line ;
int column ;
int language ;
int stackSize ;
mDebugger . CheckCallStack ( ) ;
String entryName = scope String ( ) ;
DebugManager . FrameFlags frameFlags ;
for ( int pass < 2 )
{
mDebugger . GetStackFrameInfo ( stackIdx , entryName , out addr , filePath , out hotIdx , out defLineStart , out defLineEnd , out line , out column , out language , out stackSize , out frameFlags ) ;
if ( ! frameFlags . HasFlag ( . HasPendingDebugInfo ) )
break ;
int bangPos = entryName . IndexOf ( '!' ) ;
if ( bangPos = = - 1 )
break ;
String moduleName = scope String ( entryName , 0 , bangPos ) ;
int result = mDebugger . LoadDebugInfoForModule ( moduleName ) ;
if ( result = = 0 )
break ;
// If we are backgrounding the load then we'll try to open this up afterward
if ( result = = 2 )
{
SetDeferredUserRequest ( new DeferredShowPCLocation ( stackIdx ) ) ;
return ;
}
// Try again on result == 1
filePath . Clear ( ) ;
entryName . Clear ( ) ;
mCallStackPanel . MarkCallStackDirty ( ) ;
mThreadPanel . MarkThreadsDirty ( ) ;
}
bool useWantShowDisassembly = wantShowDisassembly ;
for ( var breakpoint in mDebugger . mBreakpointList )
{
if ( ( ( breakpoint . mAddressRequested ) | | ( breakpoint . mInstrOffset ! = - 1 ) ) & &
( breakpoint . ContainsAddress ( addr ) ) )
useWantShowDisassembly = true ;
}
String aliasFilePath = null ;
String loadCmd = null ;
SourceHash hash = default ;
int hashPos = filePath . IndexOf ( '#' ) ;
2019-09-20 09:21:29 -07:00
bool checkForOldFileInfo = false ;
2019-08-23 11:56:54 -07:00
if ( hashPos ! = - 1 )
{
let hashStr = StringView ( filePath , hashPos + 1 ) ;
2019-11-22 12:27:13 -08:00
hash = SourceHash . Create ( hashStr ) ;
2019-08-23 11:56:54 -07:00
filePath . RemoveToEnd ( hashPos ) ;
if ( frameFlags . HasFlag ( . CanLoadOldVersion ) )
{
aliasFilePath = scope : : String ( filePath ) ;
String fileText = scope String ( ) ;
SourceHash fileHash = default ;
var hashKind = hash . GetKind ( ) ;
if ( hashKind = = . None )
hashKind = . MD5 ;
2019-09-20 09:21:29 -07:00
LoadTextFile ( filePath , fileText , false , scope [ & ] ( ) = > { fileHash = SourceHash . Create ( hashKind , fileText ) ; } ) . IgnoreError ( ) ;
2019-08-23 11:56:54 -07:00
if ( fileHash ! = hash )
2019-09-20 09:21:29 -07:00
checkForOldFileInfo = true ;
}
}
else
{
if ( ! File . Exists ( filePath ) )
checkForOldFileInfo = true ;
}
2019-08-23 11:56:54 -07:00
2019-09-20 09:21:29 -07:00
if ( checkForOldFileInfo )
{
String outFileInfo = scope String ( ) ;
mDebugger . GetStackFrameOldFileInfo ( mDebugger . mActiveCallStackIdx , outFileInfo ) ;
var args = outFileInfo . Split ! ( '\n' ) ;
if ( args . Count = = 3 )
{
2019-09-23 13:48:11 -07:00
aliasFilePath = scope : : String ( filePath ) ;
2019-09-20 09:21:29 -07:00
filePath . Set ( args [ 0 ] ) ;
loadCmd = scope : : String ( args [ 1 ] ) ;
2019-08-23 11:56:54 -07:00
}
}
// If we attach to an executable and we happen to have the Diassembly panel shown, STILL just show the source instead of the disassembly at first
if ( mIsAttachPendingSourceShow )
{
mInDisassemblyView = false ;
mIsAttachPendingSourceShow = false ;
}
bool hasSource = filePath . Length ! = 0 ;
if ( ( IsInDisassemblyMode ( wantShowSource ) ) | | ( ! hasSource ) | | ( useWantShowDisassembly ) )
{
if ( frameFlags . HasFlag ( . HasPendingDebugInfo ) )
{
SetDeferredUserRequest ( new DeferredShowPCLocation ( stackIdx ) ) ;
}
else
{
var disassemblyPanel = ShowDisassemblyPanel ( true ) ;
if ( aliasFilePath ! = null )
String . NewOrSet ! ( disassemblyPanel . mAliasFilePath , aliasFilePath ) ;
disassemblyPanel . Show ( addr , filePath , line , column , hotIdx , defLineStart , defLineEnd ) ;
disassemblyPanel . mSourceHash = hash ;
}
}
else if ( filePath . Length > 0 )
{
if ( ( IsCrashDump ) & & ( ! mShowedFirstDocument ) )
{
mShowedFirstDocument = true ;
ShowCallstack ( ) ;
}
var sourceViewPanel = ShowSourceFile ( filePath , null , SourceShowType . ShowExisting , setFocus ) ;
if ( sourceViewPanel ! = null )
{
sourceViewPanel . mIsSourceCode = true ; // It's always source code, even if there is no extension (ie: stl types like "vector")
if ( ( aliasFilePath ! = null ) & & ( sourceViewPanel . mAliasFilePath = = null ) )
String . NewOrSet ! ( sourceViewPanel . mAliasFilePath , aliasFilePath ) ;
if ( sourceViewPanel . mLoadFailed )
{
2019-11-22 12:27:13 -08:00
sourceViewPanel . mWantHash = hash ;
2019-08-23 11:56:54 -07:00
if ( loadCmd ! = null )
{
sourceViewPanel . SetLoadCmd ( loadCmd ) ;
}
}
2019-11-22 12:27:13 -08:00
else if ( ( hash ! = . None ) & & ( sourceViewPanel . mEditData ! = null ) & & ( ! sourceViewPanel . mEditData . CheckHash ( hash ) ) )
2019-09-24 08:58:04 -07:00
{
sourceViewPanel . ShowWrongHash ( ) ;
}
2019-08-23 11:56:54 -07:00
int showHotIdx = - 1 ;
if ( ! onlyShowCurrent )
{
bool checkForChange = false ;
if ( frameFlags . HasFlag ( . WasHotReplaced ) )
checkForChange = true ;
else
{
// If we make a trivial change (ie: characters in a comment) then we won't actually generate a new method
// So don't show as an "old file" if we don't actually have any file changes and we're on the current hot version
if ( ( sourceViewPanel . mProjectSource ! = null ) & & ( sourceViewPanel . mProjectSource . mHasChangedSinceLastSuccessfulCompile ) )
checkForChange = true ;
}
if ( checkForChange )
{
if ( sourceViewPanel . HasTextChangedSinceCompile ( defLineStart , defLineEnd , hotIdx ) )
showHotIdx = hotIdx ;
}
/ * else
{
if ( sourceViewPanel . HasTextChangedSinceCompile ( defLineStart , defLineEnd , - 1 ) )
showHotIdx = mWorkspace . GetHighestCompileIdx ( ) ;
} * /
}
sourceViewPanel . ShowHotFileIdx ( showHotIdx ) ;
sourceViewPanel . ShowFileLocation ( hotIdx , Math . Max ( 0 , line ) , Math . Max ( 0 , column ) , LocatorType . Smart ) ;
}
var disassemblyPanel = TryGetDisassemblyPanel ( false ) ;
if ( disassemblyPanel ! = null )
disassemblyPanel . Show ( addr , filePath , line , column , hotIdx , defLineStart , defLineEnd ) ;
}
}
public override void UnhandledCommandLine ( String key , String value )
{
Fail ( StackStringFormat ! ( "Unhandled command line param: {0}" , key ) ) ;
}
public override bool HandleCommandLineParam ( String key , String value )
{
if ( mLaunchData ! = null )
{
if ( mLaunchData . mArgs ! = null )
{
if ( ! mLaunchData . mArgs . IsEmpty )
mLaunchData . mArgs . Append ( " " ) ;
mLaunchData . mArgs . Append ( key ) ;
if ( value ! = null )
mLaunchData . mArgs . Append ( "=" , value ) ;
return true ;
}
if ( ( key = = "--" ) & & ( value = = null ) )
{
mLaunchData . mArgs = new . ( ) ;
return true ;
}
}
if ( base . HandleCommandLineParam ( key , value ) )
return true ;
if ( value = = null )
{
switch ( key )
{
case "-autoshutdown" :
mDebugAutoShutdownCounter = 200 ;
case "-new" :
mVerb = . New ;
case "-testNoExit" :
mExitWhenTestScriptDone = false ;
2019-10-05 10:24:58 -07:00
case "-firstRun" :
mForceFirstRun = true ;
mIsFirstRun = true ;
2019-08-23 11:56:54 -07:00
case "-clean" :
mWantsClean = true ;
case "-dbgCompileDump" :
mDbgCompileDump = true ;
2019-11-28 09:12:49 -08:00
case "-launch" :
if ( mLaunchData = = null )
mLaunchData = new . ( ) ;
2019-08-23 11:56:54 -07:00
case "-launchPaused" :
if ( mLaunchData ! = null )
mLaunchData . mPaused = true ;
else
Fail ( "'-launchPaused' can only be used after '-launch'" ) ;
default :
return false ;
}
return true ;
}
else
{
switch ( key )
{
#if BF_PLATFORM_WINDOWS
case "-attachHandle" :
mProcessAttachHandle = ( Windows . EventHandle ) int32 . Parse ( value ) . GetValueOrDefault ( ) ;
#endif
case "-attachId" :
mProcessAttachId = int32 . Parse ( value ) . GetValueOrDefault ( ) ;
case "-config" :
2019-10-15 14:39:47 -07:00
if ( mSetConfigName = = null )
mSetConfigName = new String ( ) ;
mSetConfigName . Set ( value ) ;
2019-08-23 11:56:54 -07:00
case "-launch" :
if ( mLaunchData = = null )
mLaunchData = new . ( ) ;
2019-11-28 09:12:49 -08:00
String . NewOrSet ! ( mLaunchData . mTargetPath , value ) ;
case "-launchDir" :
if ( mLaunchData ! = null )
String . NewOrSet ! ( mLaunchData . mWorkingDir , value ) ;
else
Fail ( "'-launchDir' can only be used after '-launch'" ) ;
2019-08-23 11:56:54 -07:00
#if BF_PLATFORM_WINDOWS
case "-minidump" :
String . NewOrSet ! ( mCrashDumpPath , value ) ;
#endif
case "-platform" :
2019-10-15 14:39:47 -07:00
if ( mSetPlatformName = = null )
mSetPlatformName = new String ( ) ;
mSetPlatformName . Set ( value ) ;
2019-08-23 11:56:54 -07:00
case "-test" :
Runtime . SetCrashReportKind ( . PrintOnly ) ;
String absTestPath = scope String ( ) ;
if ( mWorkspace . mDir ! = null )
Path . GetAbsolutePath ( value , mWorkspace . mDir , absTestPath ) ;
else
Path . GetFullPath ( value , absTestPath ) ;
mWantsClean = true ;
mRunningTestScript = true ;
mScriptManager . SetTimeoutMS ( 20 * 60 * 1000 ) ; // 20 minute timeout
mScriptManager . QueueCommandFile ( absTestPath ) ;
case "-verbosity" :
if ( value = = "quiet" )
mVerbosity = . Quiet ;
else if ( value = = "minimal" )
mVerbosity = . Minimal ;
else if ( value = = "normal" )
mVerbosity = . Normal ;
else if ( value = = "detailed" )
mVerbosity = . Detailed ;
2019-09-04 07:00:38 -07:00
else if ( value = = "diagnostic" )
mVerbosity = . Diagnostic ;
2019-09-04 10:27:37 -07:00
else
Fail ( scope String ( ) . . AppendF ( "Invalid verbosity option: {}" , value ) ) ;
2019-08-23 11:56:54 -07:00
case "-workspace" , "-proddir" :
var relDir = scope String ( value ) ;
if ( ( relDir . EndsWith ( "\\" ) ) | | relDir . EndsWith ( "\"" ) )
relDir . RemoveToEnd ( relDir . Length - 1 ) ;
IDEUtils . FixFilePath ( relDir ) ;
String fullDir = new String ( ) ;
Path . GetFullPath ( relDir , fullDir ) ;
if ( ( File . Exists ( fullDir ) ) | | ( IsBeefFile ( fullDir ) ) )
{
mWorkspace . mCompositeFile = new CompositeFile ( fullDir ) ;
delete fullDir ;
}
else
mWorkspace . mDir = fullDir ;
2019-09-29 07:44:23 -07:00
case "-file" :
2019-08-27 08:04:41 -07:00
String . NewOrSet ! ( mDeferredOpenFileName , value ) ;
if ( mDeferredOpenFileName . EndsWith ( ".bfdbg" , . OrdinalIgnoreCase ) )
mDeferredOpen = . DebugSession ;
else if ( mDeferredOpenFileName . EndsWith ( ".dmp" , . OrdinalIgnoreCase ) )
mDeferredOpen = . CrashDump ;
else
mDeferredOpen = . File ;
2019-08-23 11:56:54 -07:00
default :
return false ;
}
return true ;
}
}
class Board : Widget
{
public override void Draw ( Graphics g )
{
base . Draw ( g ) ;
using ( g . PushColor ( 0xFFFFFFFF ) )
g . FillRect ( 0 , 0 , 80 , 80 ) ;
}
}
public void Output ( String outStr )
{
#if CLI
Console . Write ( outStr ) ;
return ;
#endif
# unwarn
outStr . Replace ( "\r" , "" ) ;
mOutputPanel . Write ( outStr ) ;
}
public void OutputSmart ( String outStr )
{
#if CLI
Console . Write ( outStr ) ;
return ;
#endif
# unwarn
if ( outStr . Contains ( '\r' ) )
{
let newStr = scope String ( ) . . Append ( outStr ) ;
newStr . Replace ( "\r" , "" ) ;
mOutputPanel . WriteSmart ( newStr ) ;
}
else
mOutputPanel . WriteSmart ( outStr ) ;
}
public void Output ( String format , params Object [ ] args )
{
String outStr = format ;
if ( args . Count > 0 )
{
outStr = scope : : String ( ) ;
outStr . AppendF ( outStr , params args ) ;
}
else
outStr = scope : : String ( format ) ;
outStr . Replace ( "\r" , "" ) ;
mOutputPanel . Write ( outStr ) ;
}
2019-10-29 04:56:42 -07:00
public void CompilerLog ( String format , params Object [ ] args )
{
var str = scope String ( ) ;
str . . AppendF ( format , params args ) ;
if ( mBfBuildSystem ! = null )
mBfBuildSystem . Log ( str ) ;
if ( mBfResolveSystem ! = null )
mBfResolveSystem . Log ( str ) ;
}
2019-08-23 11:56:54 -07:00
public void OutputLine ( String format , params Object [ ] args )
{
String outStr ;
if ( args . Count > 0 )
{
outStr = scope : : String ( ) ;
outStr . AppendF ( format , params args ) ;
}
else
outStr = scope : : String ( format ) ;
outStr . Replace ( "\r" , "" ) ;
if ( mRunningTestScript )
Console . WriteLine ( outStr ) ;
#if CLI
Console . WriteLine ( outStr ) ;
#else
outStr . Append ( "\n" ) ;
mOutputPanel . Write ( outStr ) ;
#endif
}
public void OutputErrorLine ( String format , params Object [ ] args )
{
var errStr = scope String ( ) ;
errStr . Append ( "ERROR: " , format ) ;
OutputLineSmart ( errStr , params args ) ;
}
2019-09-22 08:25:38 -07:00
public void OutputWarnLine ( String format , params Object [ ] args )
{
var warnStr = scope String ( ) ;
warnStr . AppendF ( format , params args ) ;
#if CLI
var outStr = warnStr ;
#else
var outStr = scope String ( ) ;
outStr . AppendF ( "{0}{1}{2}" , Font . EncodeColor ( 0xfffef860 ) , warnStr , Font . EncodePopColor ( ) ) ;
#endif
OutputLine ( outStr ) ;
}
2019-08-23 11:56:54 -07:00
public void OutputLineSmart ( String format , params Object [ ] args )
{
String outStr ;
if ( args . Count > 0 )
{
outStr = scope : : String ( ) ;
outStr . AppendF ( format , params args ) ;
}
else
outStr = scope : : String ( format ) ;
outStr . Replace ( "\r" , "" ) ;
#if CLI
2020-01-12 09:21:50 -08:00
if ( outStr . StartsWith ( "ERROR:" ) )
mFailed = true ;
2019-08-23 11:56:54 -07:00
Console . WriteLine ( outStr ) ;
#else
outStr . Append ( "\n" ) ;
if ( mOutputPanel ! = null )
mOutputPanel . WriteSmart ( outStr ) ;
#endif
}
public void OutputFormatted ( String str , bool isDbgEvalOutput = false )
{
#if CLI
Console . Write ( str ) ;
return ;
#endif
# unwarn
String useStr = str ;
while ( true )
{
if ( mDebugger . GetRunState ( ) ! = . NotStarted )
{
int locPos = useStr . IndexOf ( "^loc:" ) ;
if ( locPos ! = - 1 )
{
String addrSB = scope String ( ) ;
int i = locPos + 5 ;
for ( ; i < useStr . Length ; i + + )
{
char8 c = useStr [ i ] ;
if ( ( c = = 'x' ) | | ( ( c > = '0' ) & & ( c < = '9' ) ) | | ( ( c > = 'a' ) & & ( c < = 'z' ) ) | | ( ( c > = 'A' ) & & ( c < = 'Z' ) ) )
{
addrSB . Append ( c ) ;
}
else if ( c = = '\'' )
{
// Allow
}
else
break ;
}
int64 memoryAddress = int64 . Parse ( addrSB , . HexNumber ) ;
String srcLocation = scope String ( ) ;
mDebugger . GetAddressSourceLocation ( ( int ) memoryAddress , srcLocation ) ;
var newStr = scope : : String ( ) ;
newStr . Append ( useStr , 0 , locPos ) ;
newStr . Append ( srcLocation ) ;
newStr . Append ( useStr , i ) ;
useStr = newStr ;
continue ;
}
}
break ;
}
if ( ( isDbgEvalOutput ) & & ( mIsImmediateDebugExprEval ) )
mImmediatePanel . WriteResult ( useStr ) ;
OutputSmart ( useStr ) ;
}
public void SetScale ( float scale , bool force = false )
{
var prevScale = DarkTheme . sScale ;
2019-09-30 12:23:27 -07:00
float useScale = Math . Clamp ( scale , 0.5f , 4.0f ) ;
2019-08-23 11:56:54 -07:00
if ( ( prevScale = = useScale ) & & ( ! force ) )
return ;
DarkTheme . SetScale ( useScale ) ;
RehupScale ( ) ;
for ( int32 windowIdx = 0 ; windowIdx < mWindows . Count ; windowIdx + + )
{
var window = mWindows [ windowIdx ] ;
var widgetWindow = window as WidgetWindow ;
if ( widgetWindow ! = null )
{
widgetWindow . mRootWidget . RehupScale ( prevScale , DarkTheme . sScale ) ;
var darkDockingFrame = widgetWindow . mRootWidget as DarkDockingFrame ;
if ( widgetWindow = = mMainWindow )
darkDockingFrame = mDockingFrame ;
if ( darkDockingFrame ! = null )
{
darkDockingFrame . WithAllDockedWidgets ( scope ( dockedWidget ) = >
{
var tabbedView = dockedWidget as DarkTabbedView ;
if ( tabbedView ! = null )
{
tabbedView . WithTabs ( scope ( tab ) = >
{
var panel = tab . mContent as Panel ;
if ( ( panel ! = null ) & & ( panel . mWidgetWindow = = null ) )
{
panel . RehupScale ( prevScale , DarkTheme . sScale ) ;
}
} ) ;
}
} ) ;
}
widgetWindow . mRootWidget . RehupSize ( ) ;
}
widgetWindow . mIsDirty = true ;
}
}
void SysKeyDown ( KeyDownEvent evt )
{
2019-11-22 12:27:13 -08:00
if ( evt . mHandled )
2019-09-29 07:44:23 -07:00
return ;
2019-08-23 11:56:54 -07:00
var window = ( WidgetWindow ) evt . mSender ;
2019-09-29 07:44:23 -07:00
IDECommand . ContextFlags useFlags = . None ;
var activeWindow = GetActiveWindow ( ) ;
bool isMainWindow = activeWindow . mRootWidget is MainFrame ;
var activePanel = GetActivePanel ( ) as Panel ;
if ( activePanel is SourceViewPanel )
useFlags | = . Editor ;
else if ( activePanel is DisassemblyPanel )
useFlags | = . Editor ;
if ( isMainWindow )
useFlags | = . MainWindow ;
2019-08-23 11:56:54 -07:00
if ( evt . mKeyCode = = . Tab )
{
if ( activePanel ! = null )
{
if ( activePanel . HandleTab ( window . IsKeyDown ( . Shift ) ? - 1 : 1 ) )
return ;
}
}
var keyState = scope KeyState ( ) ;
keyState . mKeyCode = evt . mKeyCode ;
keyState . mKeyFlags = evt . mKeyFlags ;
var curKeyMap = mCommands . mKeyMap ;
bool hadChordState = mKeyChordState ! = null ;
if ( mKeyChordState ! = null )
curKeyMap = mKeyChordState . mCommandMap ;
DeleteAndNullify ! ( mKeyChordState ) ;
KeyState matchedKey ;
IDECommandBase commandBase ;
if ( curKeyMap . mMap . TryGetValue ( keyState , out matchedKey , out commandBase ) )
{
if ( var commandMap = commandBase as CommandMap )
{
mKeyChordState = new . ( ) ;
mKeyChordState . mCommandMap = commandMap ;
mKeyChordState . mKeyState = matchedKey ;
evt . mHandled = true ;
return ;
}
else if ( var command = commandBase as IDECommand )
{
bool foundMatch = false ;
if ( useFlags ! = . None )
{
var checkCommand = command ;
while ( checkCommand ! = null )
{
2019-09-29 07:44:23 -07:00
bool matches = checkCommand . mContextFlags = = . None ;
if ( checkCommand . mContextFlags . HasFlag ( . Editor ) )
matches | = useFlags . HasFlag ( . Editor ) ;
if ( checkCommand . mContextFlags . HasFlag ( . MainWindow ) )
matches | = useFlags . HasFlag ( . MainWindow ) ;
if ( matches )
2019-08-23 11:56:54 -07:00
{
checkCommand . mAction ( ) ;
foundMatch = true ;
}
checkCommand = checkCommand . mNext ;
}
}
if ( ! foundMatch )
{
var checkCommand = command ;
while ( checkCommand ! = null )
{
if ( checkCommand . mContextFlags = = . None )
{
checkCommand . mAction ( ) ;
foundMatch = true ;
}
checkCommand = checkCommand . mNext ;
}
}
if ( foundMatch )
{
evt . mHandled = true ;
return ;
}
}
}
else
{
// Not found
if ( hadChordState )
{
Beep ( . Error ) ;
evt . mHandled = true ;
return ;
}
}
SourceViewPanel sourceViewPanel = null ;
Widget focusWidget = window . mFocusWidget ;
if ( focusWidget is EditWidget )
focusWidget = focusWidget . mParent ;
if ( focusWidget is SourceViewPanel )
sourceViewPanel = ( SourceViewPanel ) focusWidget ;
//if (focusWidget is DisassemblyPanel)
//break;
if ( evt . mKeyFlags = = 0 ) // No ctrl/shift/alt
{
switch ( evt . mKeyCode )
{
case KeyCode . F2 :
if ( sourceViewPanel ! = null )
{
mBookmarkManager . NextBookmark ( ) ;
}
else if ( focusWidget is ProjectPanel )
{
var projectPanel = ( ProjectPanel ) focusWidget ;
projectPanel . TryRenameItem ( ) ;
}
break ;
default :
//OutputLine("Unknown key: {0}", (int)evt.mKeycode);
break ;
}
}
}
void ShowOpenFileInSolutionDialog ( )
{
var widgetWindow = GetCurrentWindow ( ) ;
if ( widgetWindow ! = null )
{
var openFileInSolutionDialog = new OpenFileInSolutionDialog ( ) ;
openFileInSolutionDialog . PopupWindow ( mMainWindow ) ;
}
}
void ChangeCase ( bool toUpper )
{
let sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( sourceViewPanel = = null )
return ;
var ewc = sourceViewPanel . mEditWidget . mEditWidgetContent ;
if ( ! ewc . HasSelection ( ) )
return ;
/ * ewc . mSelection . Value . GetAsForwardSelect ( var startPos , var endPos ) ;
for ( int i = startPos ; i < endPos ; i + + )
{
var c = ref ewc . mData . mText [ i ] . mChar ;
if ( toUpper )
c = c . ToUpper ;
else
c = c . ToLower ;
} * /
var prevSel = ewc . mSelection . Value ;
var str = scope String ( ) ;
ewc . GetSelectionText ( str ) ;
var prevStr = scope String ( ) ;
prevStr . Append ( str ) ;
if ( toUpper )
str . ToUpper ( ) ;
else
str . ToLower ( ) ;
if ( str = = prevStr )
return ;
ewc . InsertAtCursor ( str ) ;
ewc . mSelection = prevSel ;
}
public bool IsFilteredOut ( String fileName )
{
if ( fileName . Contains ( '~' ) )
return true ;
if ( fileName . EndsWith ( ".TMP" , . OrdinalIgnoreCase ) )
return true ;
return false ;
}
public static bool IsBeefFile ( String fileName )
{
return fileName . EndsWith ( ".cs" , StringComparison . OrdinalIgnoreCase ) | | fileName . EndsWith ( ".bf" , StringComparison . OrdinalIgnoreCase ) ;
}
public static bool IsClangSourceFile ( String fileName )
{
#if IDE_C_SUPPORT
return fileName . EndsWith ( ".cpp" , StringComparison . OrdinalIgnoreCase ) | | fileName . EndsWith ( ".c" , StringComparison . OrdinalIgnoreCase ) | | fileName . EndsWith ( ".cc" , StringComparison . OrdinalIgnoreCase ) ;
#else
return false ;
#endif
}
public static bool IsSourceCode ( String fileName )
{
return fileName . EndsWith ( ".cs" , StringComparison . OrdinalIgnoreCase ) | | fileName . EndsWith ( ".bf" , StringComparison . OrdinalIgnoreCase ) | |
fileName . EndsWith ( ".h" , StringComparison . OrdinalIgnoreCase ) | | fileName . EndsWith ( ".cpp" , StringComparison . OrdinalIgnoreCase ) | |
fileName . EndsWith ( ".c" , StringComparison . OrdinalIgnoreCase ) | | fileName . EndsWith ( ".cc" , StringComparison . OrdinalIgnoreCase ) | |
fileName . EndsWith ( ".hpp" , StringComparison . OrdinalIgnoreCase ) ;
}
public static bool IsClangSourceHeader ( String fileName )
{
return fileName . EndsWith ( ".h" , StringComparison . OrdinalIgnoreCase ) | | fileName . EndsWith ( ".hpp" , StringComparison . OrdinalIgnoreCase ) ;
}
2019-10-01 12:46:38 -07:00
public void GetBeefPreprocessorMacros ( DefinesSet macroList )
2019-08-23 11:56:54 -07:00
{
2019-10-01 12:46:38 -07:00
let platform = Workspace . PlatformType . GetFromName ( mPlatformName ) ;
if ( platform ! = . Unknown )
{
String def = scope . ( ) ;
def . Append ( "BF_PLATFORM_" ) ;
platform . ToString ( def ) ;
def . ToUpper ( ) ;
macroList . Add ( def ) ;
}
2019-08-23 11:56:54 -07:00
var workspaceOptions = GetCurWorkspaceOptions ( ) ;
if ( workspaceOptions . mRuntimeChecks )
macroList . Add ( "BF_RUNTIME_CHECKS" ) ;
if ( workspaceOptions . mEnableObjectDebugFlags )
macroList . Add ( "BF_ENABLE_OBJECT_DEBUG_FLAGS" ) ;
if ( workspaceOptions . mAllowHotSwapping )
macroList . Add ( "BF_ALLOW_HOT_SWAPPING" ) ;
2019-10-14 17:49:10 -07:00
bool is64Bits = Workspace . PlatformType . GetPtrSizeByName ( gApp . mPlatformName ) = = 8 ;
2019-08-23 11:56:54 -07:00
if ( is64Bits )
{
if ( workspaceOptions . mLargeStrings )
macroList . Add ( "BF_LARGE_STRINGS" ) ;
if ( workspaceOptions . mLargeCollections )
macroList . Add ( "BF_LARGE_COLLECTIONS" ) ;
}
// Only supported on Windows at the moment
bool hasLeakCheck = false ;
#if BF_PLATFORM_WINDOWS
if ( workspaceOptions . mEnableRealtimeLeakCheck & & workspaceOptions . mEnableObjectDebugFlags )
{
hasLeakCheck = true ;
macroList . Add ( "BF_ENABLE_REALTIME_LEAK_CHECK" ) ;
}
#endif
if ( ( workspaceOptions . mAllocType = = . Debug ) | | ( hasLeakCheck ) )
macroList . Add ( "BF_DEBUG_ALLOC" ) ;
if ( workspaceOptions . mEmitDynamicCastCheck )
macroList . Add ( "BF_DYNAMIC_CAST_CHECK" ) ;
if ( workspaceOptions . mBuildKind = = . Test )
macroList . Add ( "BF_TEST_BUILD" ) ;
macroList . Add ( "BF_LITTLE_ENDIAN" ) ;
if ( is64Bits )
macroList . Add ( "BF_64_BIT" ) ;
else
macroList . Add ( "BF_32_BIT" ) ;
//if (workspaceOptions.mE)
macroList . Add ( "BF_HAS_VDATA_EXTENDER" ) ;
}
public void GetClangResolveArgs ( Project project , List < String > outResolveArgs )
{
using ( project . mMonitor . Enter ( ) )
{
//List<string> argsList = new List<string>();
var options = GetCurProjectOptions ( project ) ;
if ( options = = null )
return ;
outResolveArgs . Add ( new String ( "-std=c++11" ) ) ;
if ( options . mCOptions . mEnableBeefInterop )
{
2019-10-01 12:46:38 -07:00
var beefPreprocMacros = scope DefinesSet ( ) ;
2019-08-23 11:56:54 -07:00
GetBeefPreprocessorMacros ( beefPreprocMacros ) ;
2019-10-01 12:46:38 -07:00
for ( var beefPreprocMacro in beefPreprocMacros . mDefines )
2019-08-23 11:56:54 -07:00
{
outResolveArgs . Add ( new String ( "-D" , beefPreprocMacro ) ) ;
}
}
for ( var preprocMacro in options . mCOptions . mPreprocessorMacros )
outResolveArgs . Add ( new String ( "-D" , preprocMacro ) ) ;
for ( var includePath in options . mCOptions . mIncludePaths )
{
//outResolveArgs.Add(new String("-I", includePath));
var fullIncludePath = scope String ( ) ;
project . GetProjectFullPath ( includePath , fullIncludePath ) ;
outResolveArgs . Add ( new String ( "-I" , fullIncludePath ) ) ;
}
String llvmDir = scope String ( IDEApp . sApp . mInstallDir ) ;
IDEUtils . FixFilePath ( llvmDir ) ;
llvmDir . Append ( "llvm/" ) ;
outResolveArgs . Add ( new String ( "-I" , llvmDir , "lib/gcc/i686-w64-mingw32/5.2.0/include" ) ) ;
outResolveArgs . Add ( new String ( "-I" , llvmDir , "lib/gcc/i686-w64-mingw32/5.2.0/include-fixed" ) ) ;
outResolveArgs . Add ( new String ( "-I" , llvmDir , "i686-w64-mingw32/include" ) ) ;
outResolveArgs . Add ( new String ( "-I" , llvmDir , "i686-w64-mingw32/include/c++" ) ) ;
outResolveArgs . Add ( new String ( "-I" , llvmDir , "i686-w64-mingw32/include/c++/i686-w64-mingw32" ) ) ;
outResolveArgs . Add ( new String ( "-I" , llvmDir , "i686-w64-mingw32/include/c++/backward" ) ) ;
outResolveArgs . Add ( new String ( "-I" , llvmDir , "bin/../lib/clang/3.7.0/include" ) ) ;
outResolveArgs . Add ( new String ( "-I" , llvmDir , "i686-w64-mingw32/include" ) ) ;
outResolveArgs . Add ( new String ( "-cc1" ) ) ;
outResolveArgs . Add ( new String ( "-std=c++11" ) ) ;
outResolveArgs . Add ( new String ( "-x" ) ) ;
outResolveArgs . Add ( new String ( "c++" ) ) ;
/ * outResolveArgs . Add ( new String ( "-triple" ) ) ;
outResolveArgs . Add ( new String ( "x86_64-pc-windows-gnu" ) ) ;
outResolveArgs . Add ( new String ( "-target-cpu" ) ) ;
outResolveArgs . Add ( new String ( "x86-64" ) ) ;
outResolveArgs . Add ( new String ( "-target-feature" ) ) ;
outResolveArgs . Add ( new String ( "+sse2" ) ) ; * /
}
}
public CompilerBase GetProjectCompilerForFile ( String fileName )
{
if ( IsBeefFile ( fileName ) )
return mBfResolveCompiler ;
#if IDE_C_SUPPORT
if ( IsClangSourceFile ( fileName ) )
return mDepClang ;
#endif
return null ;
}
public CompilerBase GetResolveCompilerForFile ( String fileName )
{
if ( IsBeefFile ( fileName ) )
return mBfResolveCompiler ;
#if IDE_C_SUPPORT
if ( IsClangSourceFile ( fileName ) )
return mResolveClang ;
#endif
return null ;
}
2019-08-27 08:04:41 -07:00
public void GetClangFiles ( ProjectFolder projectFolder , List < ProjectSource > clangFiles )
2019-08-23 11:56:54 -07:00
{
for ( var item in projectFolder . mChildItems )
{
if ( item is ProjectSource )
{
var projectSource = ( ProjectSource ) item ;
if ( ! IsClangSourceFile ( projectSource . mPath ) )
continue ;
clangFiles . Add ( projectSource ) ;
}
if ( item is ProjectFolder )
{
var innerProjectFolder = ( ProjectFolder ) item ;
GetClangFiles ( innerProjectFolder , clangFiles ) ;
}
}
}
/ * void StopExecutionInstance ( )
{
if ( mExecutionInstance ! = null )
{
try
{
mExecutionInstance . mProcess . Kill ( ) ;
}
catch ( Exception )
{
}
}
} * /
const int cArgFileThreshold = 0x7800 ;
2019-08-27 08:04:41 -07:00
public ExecutionQueueCmd QueueRun ( String fileName , String args , String workingDir , ArgsFileKind argsFileKind = . None )
2019-08-23 11:56:54 -07:00
{
var executionQueueCmd = new ExecutionQueueCmd ( ) ;
executionQueueCmd . mFileName = new String ( fileName ) ;
executionQueueCmd . mArgs = new String ( args ) ;
executionQueueCmd . mWorkingDir = new String ( workingDir ) ;
if ( args . Length > cArgFileThreshold )
{
// Only use UTF16 if we absolutely need to
if ( ( argsFileKind = = . UTF16WithBom ) & & ( ! args . HasMultibyteChars ( ) ) )
executionQueueCmd . mUseArgsFile = . UTF8 ;
else
executionQueueCmd . mUseArgsFile = argsFileKind ;
}
mExecutionQueue . Add ( executionQueueCmd ) ;
return executionQueueCmd ;
}
void GotExecutionOutputLine ( ExecutionInstance executionInstance , String str )
{
if ( ! String . IsNullOrEmpty ( str ) )
{
using ( mMonitor . Enter ( ) )
{
executionInstance . mDeferredOutput . Add ( new String ( str ) ) ;
}
}
}
2019-10-23 07:12:36 -07:00
static void WriteInputThread ( Object obj )
{
ExecutionInstance executionInstance = ( ExecutionInstance ) obj ;
FileStream fileStream = scope FileStream ( ) ;
if ( executionInstance . mProcess . AttachStandardInput ( fileStream ) case . Err )
return ;
while ( ! executionInstance . mStdInData . IsEmpty )
{
switch ( fileStream . TryWrite ( . ( ( . ) executionInstance . mStdInData . Ptr , executionInstance . mStdInData . Length ) ) )
{
case . Ok ( int len ) :
executionInstance . mStdInData . Remove ( 0 , len ) ;
case . Err :
break ;
}
}
}
2019-08-23 11:56:54 -07:00
static void ReadOutputThread ( Object obj )
{
ExecutionInstance executionInstance = ( ExecutionInstance ) obj ;
FileStream fileStream = scope FileStream ( ) ;
if ( executionInstance . mProcess . AttachStandardOutput ( fileStream ) case . Err )
return ;
StreamReader streamReader = scope StreamReader ( fileStream , null , false , 4096 ) ;
while ( true )
{
var buffer = scope String ( ) ;
if ( streamReader . ReadLine ( buffer ) case . Err )
break ;
using ( IDEApp . sApp . mMonitor . Enter ( ) )
executionInstance . mDeferredOutput . Add ( new String ( buffer ) ) ;
}
}
static void ReadErrorThread ( Object obj )
{
ExecutionInstance executionInstance = ( ExecutionInstance ) obj ;
FileStream fileStream = scope FileStream ( ) ;
if ( executionInstance . mProcess . AttachStandardError ( fileStream ) case . Err )
return ;
StreamReader streamReader = scope StreamReader ( fileStream , null , false , 4096 ) ;
while ( true )
{
var buffer = scope String ( ) ;
if ( streamReader . ReadLine ( buffer ) case . Err )
break ;
using ( IDEApp . sApp . mMonitor . Enter ( ) )
executionInstance . mDeferredOutput . Add ( new String ( buffer ) ) ;
}
}
2020-01-23 07:44:09 -08:00
public enum RunFlags
{
None ,
ShellCommand = 1
}
public ExecutionInstance DoRun ( String inFileName , String args , String workingDir , ArgsFileKind useArgsFile , Dictionary < String , String > envVars = null , String stdInData = null , RunFlags runFlags = . None )
2019-08-23 11:56:54 -07:00
{
//Debug.Assert(executionInstance == null);
String fileName = scope String ( inFileName ? ? "" ) ;
QuoteIfNeeded ( fileName ) ;
ProcessStartInfo startInfo = scope ProcessStartInfo ( ) ;
startInfo . UseShellExecute = false ;
if ( ! fileName . IsEmpty )
startInfo . SetFileName ( fileName ) ;
startInfo . SetWorkingDirectory ( workingDir ) ;
startInfo . SetArguments ( args ) ;
startInfo . RedirectStandardOutput = true ;
startInfo . RedirectStandardError = true ;
2019-10-23 07:12:36 -07:00
if ( stdInData ! = null )
startInfo . RedirectStandardInput = true ;
2019-08-23 11:56:54 -07:00
startInfo . CreateNoWindow = true ;
2020-01-23 07:44:09 -08:00
if ( runFlags . HasFlag ( . ShellCommand ) )
{
String shellArgs = scope . ( ) ;
shellArgs . Append ( "/c " ) ;
IDEUtils . AppendWithOptionalQuotes ( shellArgs , fileName ) ;
shellArgs . Append ( " " ) ;
shellArgs . Append ( args ) ;
startInfo . SetFileName ( "cmd.exe" ) ;
startInfo . SetArguments ( shellArgs ) ;
}
2019-08-23 11:56:54 -07:00
if ( envVars ! = null )
{
for ( var envKV in envVars )
startInfo . AddEnvironmentVariable ( envKV . key , envKV . value ) ;
}
var executionInstance = new ExecutionInstance ( ) ;
mExecutionInstances . Add ( executionInstance ) ;
if ( useArgsFile ! = . None )
{
String tempFileName = scope String ( ) ;
Path . GetTempFileName ( tempFileName ) ;
Encoding encoding = Encoding . UTF8 ;
if ( useArgsFile = = . UTF16WithBom )
encoding = Encoding . UTF16WithBOM ;
var result = File . WriteAllText ( tempFileName , args , encoding ) ;
if ( result case . Err )
OutputLine ( "Failed to create temporary param file" ) ;
String arguments = scope String ( ) ;
arguments . Concat ( "@" , tempFileName ) ;
startInfo . SetArguments ( arguments ) ;
executionInstance . mTempFileName = new String ( tempFileName ) ;
}
if ( mVerbosity > = . Detailed )
{
String showArgs = startInfo . mArguments ;
if ( ( mRunningTestScript ) & & ( showArgs . Length > 1024 ) )
{
showArgs = scope : : String ( showArgs , 0 , 1024 ) ;
showArgs . Append ( "..." ) ;
}
if ( ! startInfo . mFileName . IsEmpty )
2019-10-15 17:27:09 -07:00
{
OutputLine ( "Executing: {0} {1}" , startInfo . mFileName , showArgs ) ;
if ( ( mVerbosity > = . Diagnostic ) & & ( useArgsFile ! = . None ) )
OutputLine ( "Arg file contents: {0}" , args ) ;
}
2019-08-23 11:56:54 -07:00
else
OutputLine ( "Executing: {0}" , showArgs ) ;
}
//if (useArgsFile)
{
//if (mVerbosity >= .Detailed)
//OutputLine(" Args: {0}", args);
}
/ * var processResult = Process . Start ( startInfo ) ;
if ( case . Err = processResult )
{
OutputLine ( "Failed to execute \"{0}\"" , fileName ) ;
return executionInstance ;
} * /
SpawnedProcess process = new SpawnedProcess ( ) ;
if ( process . Start ( startInfo ) case . Err )
{
OutputLine ( "Failed to execute \"{0}\"" , inFileName ) ;
delete process ;
return executionInstance ;
}
executionInstance . mStopwatch . Start ( ) ;
executionInstance . mProcess = process ;
executionInstance . mOutputThread = new Thread ( new = > ReadOutputThread ) ;
executionInstance . mOutputThread . Start ( executionInstance , false ) ;
executionInstance . mErrorThread = new Thread ( new = > ReadErrorThread ) ;
executionInstance . mErrorThread . Start ( executionInstance , false ) ;
2019-10-23 07:12:36 -07:00
if ( stdInData ! = null )
{
executionInstance . mStdInData = new String ( stdInData ) ;
executionInstance . mInputThread = new Thread ( new = > WriteInputThread ) ;
executionInstance . mInputThread . Start ( executionInstance , false ) ;
}
2019-08-23 11:56:54 -07:00
return executionInstance ;
}
protected virtual void BeefCompileStarted ( )
{
}
protected virtual void BeefCompileDone ( )
{
}
protected virtual void CompileDone ( bool succeeded )
{
}
BuildCompletedCmd GetBuildCompletedCmd ( )
{
for ( int idx = mExecutionQueue . Count - 1 ; idx > = 0 ; idx - - )
{
if ( var buildCompletedCmd = mExecutionQueue [ idx ] as BuildCompletedCmd )
return buildCompletedCmd ;
}
return null ;
}
void UpdateExecution ( )
{
if ( mExecutionInstances . Count > 0 )
{
var executionInstance = mExecutionInstances [ 0 ] ;
bool failed = false ;
bool isDone = false ;
using ( mMonitor . Enter ( ) )
{
for ( var str in executionInstance . mDeferredOutput )
{
OutputLine ( str ) ;
delete str ;
}
executionInstance . mDeferredOutput . Clear ( ) ;
}
if ( executionInstance . mProcess = = null )
{
// Didn't even get off the ground
isDone = true ;
failed = true ;
executionInstance . mExitCode = - 1 ;
}
else if ( executionInstance . mProcess . HasExited )
{
isDone = true ;
if ( executionInstance . mOutputThread ! = null )
{
if ( ! executionInstance . mOutputThread . Join ( 0 ) )
isDone = false ;
}
if ( executionInstance . mErrorThread ! = null )
{
if ( ! executionInstance . mErrorThread . Join ( 0 ) )
isDone = false ;
}
if ( isDone )
{
executionInstance . mExitCode = executionInstance . mProcess . ExitCode ;
if ( executionInstance . mProcess . ExitCode ! = 0 )
failed = true ;
executionInstance . mProcess . WaitFor ( - 1 ) ;
executionInstance . mProcess . Close ( ) ;
executionInstance . mStopwatch . Stop ( ) ;
2019-09-22 08:25:38 -07:00
if ( executionInstance . mIsTargetRun )
{
mTargetExitCode = executionInstance . mExitCode ;
2019-08-23 11:56:54 -07:00
}
2019-09-22 08:25:38 -07:00
else
{
if ( executionInstance . mParallelGroup = = - 1 )
{
if ( mVerbosity > = . Detailed )
OutputLine ( "Execution time: {0:0.00}s" , executionInstance . mStopwatch . ElapsedMilliseconds / 1000.0f ) ;
}
2019-08-23 11:56:54 -07:00
2019-09-22 08:25:38 -07:00
if ( executionInstance . mCanceled )
OutputLine ( "Execution Canceled" ) ;
else if ( failed )
OutputLine ( "Execution Failed" ) ;
}
2019-08-23 11:56:54 -07:00
if ( executionInstance . mTempFileName ! = null )
{
File . Delete ( executionInstance . mTempFileName ) . IgnoreError ( ) ;
}
}
}
if ( failed )
{
if ( mExecutionQueue . Count > 0 )
{
var buildCompletedCmd = GetBuildCompletedCmd ( ) ;
if ( buildCompletedCmd ! = null )
buildCompletedCmd . mFailed = true ;
}
}
if ( isDone )
{
mExecutionInstances . RemoveAt ( 0 ) ;
if ( executionInstance . mAutoDelete )
delete executionInstance ;
}
/ * if ( failed )
{
OutputLine ( "COMPILATION FAILED" ) ;
mExecutionQueue . Clear ( ) ;
}
if ( ( executionInstance = = null ) & & ( mExecutionQueue . Count = = 0 ) )
{
OutputLine ( "Compilation finished." ) ;
} * /
}
2019-08-29 14:19:07 -07:00
bool buildFailed = false ;
if ( ( mBuildContext ! = null ) & & ( mBuildContext . Failed ) )
buildFailed = true ;
let buildCompleteCmd = GetBuildCompletedCmd ( ) ;
if ( ( buildCompleteCmd ! = null ) & & ( buildCompleteCmd . mFailed ) )
buildFailed = true ;
2019-08-23 11:56:54 -07:00
bool canExecuteNext = false ;
int32 parallelExecutionCount = 16 ;
if ( ( mExecutionQueue . Count > 0 ) & & ( mExecutionInstances . Count < parallelExecutionCount ) )
{
var executionQueueCmd = mExecutionQueue [ 0 ] as ExecutionQueueCmd ;
if ( executionQueueCmd ! = null )
{
if ( mExecutionInstances . Count > 0 )
{
var executionInstance = mExecutionInstances [ 0 ] ;
if ( ( executionQueueCmd . mParallelGroup ! = - 1 ) & &
( executionQueueCmd . mParallelGroup = = executionInstance . mParallelGroup ) )
canExecuteNext = true ;
}
else
canExecuteNext = true ;
}
else if ( mExecutionInstances . Count = = 0 )
canExecuteNext = true ;
}
if ( canExecuteNext )
{
var next = mExecutionQueue [ 0 ] ;
bool waitForBuildClang = false ;
#if IDE_C_SUPPORT
waitForBuildClang = ( mDepClang . mCompileWaitsForQueueEmpty ) & & ( mDepClang . HasQueuedCommands ( ) ) ;
#endif
if ( ( next is ProcessBfCompileCmd ) & & ( mBfBuildCompiler . HasQueuedCommands ( ) | | ( waitForBuildClang ) ) )
return ;
2019-08-29 14:19:07 -07:00
2019-08-27 08:04:41 -07:00
/ * if ( next is BuildCompletedCmd )
{
if ( mBuildContext ! = null )
return ;
} * /
if ( let targetCompletedCmd = next as TargetCompletedCmd )
{
if ( ( mBuildContext = = null ) | | ( ! mBuildContext . Failed ) )
{
if ( ! targetCompletedCmd . mIsReady )
return ;
}
}
defer delete next ;
2019-08-23 11:56:54 -07:00
mExecutionQueue . RemoveAt ( 0 ) ;
bool ignoreCommand = false ;
if ( next . mOnlyIfNotFailed )
{
if ( mExecutionQueue . Count > 0 )
{
var buildCompletedCmd = GetBuildCompletedCmd ( ) ;
if ( ( buildCompletedCmd ! = null ) & & ( buildCompletedCmd . mFailed ) )
ignoreCommand = true ;
}
}
if ( ignoreCommand )
{
// Nothing
2019-09-28 09:48:37 -07:00
if ( let targetCompletedCmd = next as TargetCompletedCmd )
{
String projectBuildDir = scope String ( ) ;
gApp . GetProjectBuildDir ( targetCompletedCmd . mProject , projectBuildDir ) ;
gApp . mBfBuildCompiler . SetBuildValue ( projectBuildDir , "Link" , "FAILED" ) ;
gApp . mBfBuildCompiler . WriteBuildCache ( projectBuildDir ) ;
}
2019-08-23 11:56:54 -07:00
}
else if ( next is ProcessBfCompileCmd )
{
var processCompileCmd = ( ProcessBfCompileCmd ) next ;
mCompilingBeef = false ;
BeefCompileDone ( ) ;
//processCompileCmd.mStopwatch.Stop();
if ( ( processCompileCmd . mHadBeef ) & & ( mVerbosity > = . Normal ) )
OutputLine ( "Beef compilation time: {0:0.00}s" , processCompileCmd . mStopwatch . ElapsedMilliseconds / 1000.0f ) ;
var compileInstance = mWorkspace . mCompileInstanceList . Back ;
compileInstance . mCompileResult = . Failure ;
if ( processCompileCmd . mBfPassInstance . mCompileSucceeded )
{
//foreach (var sourceViewPanel in GetSourceViewPanels())
WithSourceViewPanels ( scope ( sourceViewPanel ) = >
{
sourceViewPanel . mHasChangedSinceLastCompile = false ;
} ) ;
compileInstance . mCompileResult = . Success ;
}
else
{
compileInstance . mCompileResult = . Failure ;
}
ProcessBeefCompileResults ( processCompileCmd . mBfPassInstance , processCompileCmd . mRunAfter , processCompileCmd . mHotProject , processCompileCmd . mStopwatch ) ;
if ( mHotResolveState ! = . None )
{
if ( compileInstance . mCompileResult = = . Success )
compileInstance . mCompileResult = . PendingHotLoad ;
}
if ( processCompileCmd . mProfileCmd ! = null )
{
mExecutionQueue . Add ( processCompileCmd . mProfileCmd ) ;
processCompileCmd . mProfileCmd = null ;
}
delete processCompileCmd . mStopwatch ;
processCompileCmd . mStopwatch = null ;
}
else if ( next is TargetCompletedCmd )
{
2019-08-29 14:19:07 -07:00
if ( ! buildFailed )
{
var targetCompletedCmd = ( TargetCompletedCmd ) next ;
targetCompletedCmd . mProject . mNeedsTargetRebuild = false ;
targetCompletedCmd . mProject . mForceCustomCommands = false ;
}
2019-08-23 11:56:54 -07:00
}
else if ( next is StartDebugCmd )
{
2019-08-29 14:19:07 -07:00
if ( ! buildFailed )
{
var startDebugCmd = ( StartDebugCmd ) next ;
if ( DebugProject ( startDebugCmd . mWasCompiled ) )
{
OutputLine ( "Debugger started" ) ;
}
else
OutputLine ( "Failed to start debugger" ) ;
}
2019-08-23 11:56:54 -07:00
}
else if ( next is ExecutionQueueCmd )
{
var executionQueueCmd = ( ExecutionQueueCmd ) next ;
2019-10-23 07:12:36 -07:00
var executionInstance = DoRun ( executionQueueCmd . mFileName , executionQueueCmd . mArgs , executionQueueCmd . mWorkingDir , executionQueueCmd . mUseArgsFile , executionQueueCmd . mEnvVars , executionQueueCmd . mStdInData ) ;
2019-08-23 11:56:54 -07:00
executionInstance . mParallelGroup = executionQueueCmd . mParallelGroup ;
2019-09-22 08:25:38 -07:00
executionInstance . mIsTargetRun = executionQueueCmd . mIsTargetRun ;
2019-08-23 11:56:54 -07:00
}
else if ( next is BuildCompletedCmd )
{
var buildCompletedCmd = ( BuildCompletedCmd ) next ;
#if IDE_C_SUPPORT
mWorkspace . WithProjectItems ( scope ( projectItem ) = >
{
var projectSource = projectItem as ProjectSource ;
if ( projectItem ! = null )
{
String fullPath = scope String ( ) ;
projectSource . GetFullImportPath ( fullPath ) ;
if ( completedCompileCmd . mClangCompiledFiles . Contains ( fullPath ) )
{
mDepClang . QueueCheckDependencies ( projectSource , ClangCompiler . DepCheckerType . Clang ) ;
}
}
} ) ;
if ( ! completedCompileCmd . mFailed )
mDepClang . mDoDependencyCheck = false ;
#endif
2019-08-29 14:19:07 -07:00
if ( buildFailed )
buildCompletedCmd . mFailed = true ;
2019-08-23 11:56:54 -07:00
CompileResult ( buildCompletedCmd . mHotProjectName , ! buildCompletedCmd . mFailed ) ;
if ( buildCompletedCmd . mFailed )
OutputLineSmart ( "ERROR: BUILD FAILED" ) ;
if ( ( mVerbosity > = . Detailed ) & & ( buildCompletedCmd . mStopwatch ! = null ) )
OutputLine ( "Total build time: {0:0.00}s" , buildCompletedCmd . mStopwatch . ElapsedMilliseconds / 1000.0f ) ;
CompileDone ( ! buildCompletedCmd . mFailed ) ;
if ( mTestManager ! = null )
{
if ( buildCompletedCmd . mFailed )
mTestManager . BuildFailed ( ) ;
else
mTestManager . Start ( ) ;
}
}
else if ( var profileCmd = next as ProfileCmd )
{
if ( gApp . mDebugger . mIsRunning )
mProfilePanel . StartProfiling ( profileCmd . mThreadId , profileCmd . mDesc , profileCmd . mSampleRate ) ;
}
else
{
Runtime . FatalError ( "Unknown command" ) ;
}
}
}
public bool ParseSourceFile ( BfSystem bfSystem , BfPassInstance passInstance , ProjectSource projectSource )
{
bool worked = true ;
if ( ! IsBeefFile ( projectSource . mPath ) )
return true ;
var fullPath = scope String ( ) ;
projectSource . GetFullImportPath ( fullPath ) ;
String data = scope String ( ) ;
LoadTextFile ( fullPath , data ) ;
if ( data = = null )
{
OutputErrorLine ( "FAILED TO LOAD FILE: {0}" , fullPath ) ;
return true ;
}
mFileWatcher . FileIsValid ( fullPath ) ;
var bfParser = bfSystem . CreateParser ( projectSource ) ;
bfParser . SetSource ( data , fullPath ) ;
worked & = bfParser . Parse ( passInstance , false ) ;
worked & = bfParser . Reduce ( passInstance ) ;
worked & = bfParser . BuildDefs ( passInstance , null , false ) ;
return worked ;
}
public bool FindProjectSourceContent ( ProjectSource projectSource , out IdSpan char8IdData , bool loadOnFail , String sourceContent )
{
char8IdData = IdSpan ( ) ;
var fullPath = scope String ( ) ;
projectSource . GetFullImportPath ( fullPath ) ;
//SourceViewPanel sourceViewPanel = null;
using ( mMonitor . Enter ( ) )
{
if ( projectSource . mEditData ! = null )
{
if ( projectSource . mEditData . IsFileDeleted ( ) )
{
return false ;
}
if ( projectSource . mEditData . mEditWidget ! = null )
{
var idData = ref projectSource . mEditData . mEditWidget . Content . mData . mTextIdData ;
idData . Prepare ( ) ;
if ( ! projectSource . mEditData . mSavedCharIdData . Equals ( idData ) )
{
char8IdData = projectSource . mEditData . mEditWidget . mEditWidgetContent . mData . mTextIdData . Duplicate ( ) ;
projectSource . mEditData . mEditWidget . GetText ( sourceContent ) ;
return true ;
}
}
if ( projectSource . mEditData . mSavedContent ! = null )
{
char8IdData = projectSource . mEditData . mSavedCharIdData . Duplicate ( ) ;
sourceContent . Set ( projectSource . mEditData . mSavedContent ) ;
return true ;
}
}
}
if ( loadOnFail )
{
String text = scope String ( ) ;
bool isValid = false ;
if ( LoadTextFile ( fullPath , text ) case . Ok )
{
mFileWatcher . FileIsValid ( fullPath ) ;
isValid = true ;
}
char8IdData = IdSpan . GetDefault ( ( int32 ) text . Length ) ;
var editData = GetEditData ( projectSource , false ) ;
using ( mMonitor . Enter ( ) )
{
if ( isValid )
{
editData . SetSavedData ( text , char8IdData ) ;
sourceContent . Set ( text ) ;
}
else
{
editData . SetSavedData ( null , IdSpan ( ) ) ;
editData . mFileDeleted = true ;
}
}
return isValid ;
}
return false ;
}
public void SetInDisassemblyView ( bool inDisassemblyView )
{
if ( mShuttingDown )
return ;
if ( mInDisassemblyView ! = inDisassemblyView )
{
// We need to refresh auto watch panel so we can handle displaying registers when switching to disasm
mAutoWatchPanel . MarkWatchesDirty ( false ) ;
mInDisassemblyView = inDisassemblyView ;
}
}
public bool ParseSourceFiles ( BfSystem bfSystem , BfPassInstance passInstance , ProjectFolder projectFolder )
{
bool worked = true ;
for ( var item in projectFolder . mChildItems )
{
if ( item is ProjectSource )
{
var projectSource = ( ProjectSource ) item ;
worked & = ParseSourceFile ( bfSystem , passInstance , projectSource ) ;
}
if ( item is ProjectFolder )
{
var innerProjectFolder = ( ProjectFolder ) item ;
worked & = ParseSourceFiles ( bfSystem , passInstance , innerProjectFolder ) ;
}
}
return worked ;
}
public bool HasPendingBeefFiles ( bool forceQueue , ProjectFolder projectFolder )
{
bool hadBeef = false ;
for ( var item in projectFolder . mChildItems )
{
if ( item . mIncludeKind = = . Ignore )
continue ;
if ( item is ProjectSource )
{
var projectSource = ( ProjectSource ) item ;
if ( IsBeefFile ( projectSource . mPath ) )
{
if ( ( projectSource . HasChangedSinceLastCompile ) | | ( forceQueue ) )
{
hadBeef = true ;
}
}
}
if ( item is ProjectFolder )
{
var innerProjectFolder = ( ProjectFolder ) item ;
hadBeef | = HasPendingBeefFiles ( forceQueue , innerProjectFolder ) ;
}
}
return hadBeef ;
}
public bool QueueParseBeefFiles ( BfCompiler bfCompiler , bool forceQueue , ProjectFolder projectFolder )
{
bool hadBeef = false ;
for ( var item in projectFolder . mChildItems )
{
if ( item . mIncludeKind = = . Ignore )
continue ;
if ( item is ProjectSource )
{
var projectSource = ( ProjectSource ) item ;
if ( IsBeefFile ( projectSource . mPath ) )
{
// if it's the resolve compiler then we take this as an indication that we need to recompile this file
// later on when a build is requested, most likely because the project or workspace configuration has
// changed (such as preprocessor or other setting changes)
if ( ( bfCompiler = = null ) | | ( bfCompiler . mIsResolveOnly ) )
{
projectSource . HasChangedSinceLastCompile = true ;
2019-12-05 06:50:36 -08:00
if ( bfCompiler ! = null )
{
// Process change in resolve compiler
bfCompiler . QueueProjectSource ( projectSource ) ;
}
2019-08-23 11:56:54 -07:00
}
else // Actual build
{
2020-01-15 08:32:38 -08:00
if ( ( projectSource . HasChangedSinceLastCompile ) | | ( projectSource . mLoadFailed ) | | ( forceQueue ) )
2019-08-23 11:56:54 -07:00
{
// mHasChangedSinceLastCompile is safe to set 'false' here since it just determines whether or not
// we rebuild the TypeDefs from the sources. It isn't affected by any compilation errors.
projectSource . mHasChangedSinceLastCompile = false ;
bfCompiler . QueueProjectSource ( projectSource ) ;
hadBeef = true ;
}
}
}
}
if ( item is ProjectFolder )
{
var innerProjectFolder = ( ProjectFolder ) item ;
hadBeef | = QueueParseBeefFiles ( bfCompiler , forceQueue , innerProjectFolder ) ;
}
}
return hadBeef ;
}
#if IDE_C_SUPPORT
public void QueueParseClangFiles ( ClangCompiler clangCompiler , ProjectFolder projectFolder )
{
for ( var item in projectFolder . mChildItems )
{
if ( item is ProjectSource )
{
var projectSource = ( ProjectSource ) item ;
if ( IsClangSourceFile ( projectSource . mPath ) )
clangCompiler . QueueProjectSource ( projectSource ) ;
}
if ( item is ProjectFolder )
{
var innerProjectFolder = ( ProjectFolder ) item ;
QueueParseClangFiles ( clangCompiler , innerProjectFolder ) ;
}
}
}
#endif
public Workspace . Options GetCurWorkspaceOptions ( )
{
return mWorkspace . GetOptions ( mConfigName , mPlatformName ) ;
}
public Workspace . ConfigSelection GetCurConfigSelection ( Project project )
{
var workspaceOptions = mWorkspace . GetOptions ( mConfigName , mPlatformName ) ;
if ( workspaceOptions = = null )
return null ;
Workspace . ConfigSelection configSelection ;
workspaceOptions . mConfigSelections . TryGetValue ( project , out configSelection ) ;
if ( ( configSelection = = null ) | | ( ! configSelection . mEnabled ) )
return null ;
return configSelection ;
}
public Project . Options GetCurProjectOptions ( Project project )
{
if ( project . mFailed )
return null ;
Workspace . ConfigSelection configSelection = GetCurConfigSelection ( project ) ;
if ( configSelection = = null )
return null ;
return project . GetOptions ( configSelection . mConfig , configSelection . mPlatform ) ;
}
public bool IsProjectEnabled ( Project project )
{
return GetCurProjectOptions ( project ) ! = null ;
}
public bool IsProjectSourceEnabled ( ProjectSource projectSource )
{
if ( projectSource . mIncludeKind = = . Ignore )
return false ;
if ( ! IsProjectEnabled ( projectSource . mProject ) )
return false ;
return true ;
}
public void PreConfigureBeefSystem ( BfSystem bfSystem , BfCompiler bfCompiler )
{
if ( ! bfCompiler . mIsResolveOnly )
{
bfCompiler . WaitForBackground ( ) ;
bfSystem . ClearTypeOptions ( ) ;
}
}
// Project options are inherently thread safe. Resolve-system project settings
// Can only be changed from the Resolve BfCompiler thread, and Build settings
// are only changed before background compilation begins. We also call this
// during WorkspaceLoad, but the resolve threads aren't processing then.
public bool SetupBeefProjectSettings ( BfSystem bfSystem , BfCompiler bfCompiler , Project project )
{
bool success = true ;
var bfProject = bfSystem . GetBfProject ( project ) ;
Project . Options options = GetCurProjectOptions ( project ) ;
Workspace . Options workspaceOptions = GetCurWorkspaceOptions ( ) ;
if ( options = = null )
{
//Fail(StackStringFormat!("Failed to retrieve options for {0}", project.mProjectName));
bfProject . SetDisabled ( true ) ;
return false ;
}
bfProject . SetDisabled ( false ) ;
2019-10-01 12:46:38 -07:00
var preprocessorMacros = scope DefinesSet ( ) ;
2019-08-23 11:56:54 -07:00
void AddMacros ( List < String > macros )
{
for ( var macro in macros )
{
preprocessorMacros . Add ( macro ) ;
}
}
AddMacros ( project . mBeefGlobalOptions . mPreprocessorMacros ) ;
AddMacros ( options . mBeefOptions . mPreprocessorMacros ) ;
AddMacros ( mWorkspace . mBeefGlobalOptions . mPreprocessorMacros ) ;
AddMacros ( workspaceOptions . mPreprocessorMacros ) ;
GetBeefPreprocessorMacros ( preprocessorMacros ) ;
var optimizationLevel = workspaceOptions . mBfOptimizationLevel ;
if ( options . mBeefOptions . mOptimizationLevel ! = null )
optimizationLevel = options . mBeefOptions . mOptimizationLevel . Value ;
if ( ( optimizationLevel = = . OgPlus ) & & ( mPlatformName ! = "Win64" ) & & ( bfCompiler = = mBfBuildCompiler ) )
{
OutputLineSmart ( "WARNING: Project '{0}' has Og+ specified, which is only supported for Win64 targets." , project . mProjectName ) ;
optimizationLevel = . O0 ;
}
var ltoType = workspaceOptions . mLTOType ;
if ( options . mBeefOptions . mLTOType ! = null )
ltoType = options . mBeefOptions . mLTOType . Value ;
var targetType = project . mGeneralOptions . mTargetType ;
if ( bfSystem ! = mBfResolveSystem )
{
if ( options . mBuildOptions . mBuildKind = = . Test )
{
if ( workspaceOptions . mBuildKind = = . Test )
{
targetType = . BeefTest ;
if ( mTestManager ! = null )
mTestManager . AddProject ( project ) ;
}
else
{
OutputLineSmart ( "ERROR: Project '{0}' has a Test configuration specified but the workspace is not using a Test configuration" , project . mProjectName ) ;
success = false ;
}
}
2019-10-23 07:12:36 -07:00
else if ( options . mBuildOptions . mBuildKind = = . StaticLib )
{
if ( project . mGeneralOptions . mTargetType . IsBeefApplication )
targetType = . BeefApplication_StaticLib ;
}
else if ( options . mBuildOptions . mBuildKind = = . DynamicLib )
{
if ( project . mGeneralOptions . mTargetType . IsBeefApplication )
targetType = . BeefApplication_DynamicLib ;
}
2019-08-23 11:56:54 -07:00
}
bfProject . SetOptions ( targetType ,
project . mBeefGlobalOptions . mStartupObject ,
2019-10-01 12:46:38 -07:00
preprocessorMacros . mDefines ,
2019-10-23 07:12:36 -07:00
optimizationLevel , ltoType , options . mBeefOptions . mRelocType , options . mBeefOptions . mPICLevel ,
options . mBeefOptions . mMergeFunctions , options . mBeefOptions . mCombineLoads ,
2019-08-23 11:56:54 -07:00
options . mBeefOptions . mVectorizeLoops , options . mBeefOptions . mVectorizeSLP ) ;
List < Project > depProjectList = scope List < Project > ( ) ;
if ( ! GetDependentProjectList ( project , depProjectList ) )
success = false ;
bfProject . ClearDependencies ( ) ;
for ( var depProject in depProjectList )
{
2019-09-18 08:13:00 -07:00
if ( bfSystem . mProjectMap . TryGetValue ( depProject , var depBfProject ) )
bfProject . AddDependency ( depBfProject ) ;
2019-08-23 11:56:54 -07:00
}
if ( ! bfCompiler . mIsResolveOnly )
{
for ( let typeOption in project . mBeefGlobalOptions . mDistinctBuildOptions )
bfSystem . AddTypeOptions ( typeOption ) ;
for ( let typeOption in options . mBeefOptions . mDistinctBuildOptions )
bfSystem . AddTypeOptions ( typeOption ) ;
}
return success ;
}
public void CurrentWorkspaceConfigChanged ( )
{
#if IDE_C_SUPPORT
for ( var val in mDepClang . mProjectBuildString . Values )
delete val ;
mDepClang . mProjectBuildString . Clear ( ) ;
#endif
if ( mBfResolveCompiler ! = null )
{
mBfResolveCompiler . QueueSetWorkspaceOptions ( null , 0 ) ;
mBfResolveCompiler . QueueDeferredResolveAll ( ) ;
}
mWorkspace . FixOptions ( mConfigName , mPlatformName ) ;
for ( var project in mWorkspace . mProjects )
{
ProjectOptionsChanged ( project ) ;
#if IDE_C_SUPPORT
QueueParseClangFiles ( mDepClang , project . mRootFolder ) ;
#endif
}
mWorkspace . ClearProjectNameCache ( ) ;
mProjectPanel . RehupProjects ( ) ;
}
/ * public string GetClangDepConfigName ( Project project )
{
string [ ] clangArgs = GetClangResolveArgs ( project ) ;
string clangArgsStr = String . Join ( "\n" , clangArgs ) ;
long hash = 0 ;
for ( int i = 0 ; i < clangArgsStr . Length ; i + + )
hash = ( hash < < 5 ) - hash + clangArgsStr [ i ] ;
return String . Format ( "{0:X16}" , hash ) ;
} * /
public void ProjectOptionsChanged ( Project project , bool reparseFiles = true )
{
bool isEnabled = IsProjectEnabled ( project ) ;
mWorkspace . ClearProjectNameCache ( ) ;
if ( mBfResolveCompiler ! = null )
{
mBfResolveCompiler . QueueSetupProjectSettings ( project ) ;
}
if ( isEnabled ! = project . mEnabled )
{
project . mEnabled = isEnabled ;
if ( isEnabled )
{
QueueProjectItems ( project ) ;
}
else
{
RemoveProjectItems ( project ) ;
}
mBfResolveCompiler . QueueDeferredResolveAll ( ) ;
mBfResolveCompiler . QueueRefreshViewCommand ( ) ;
return ;
}
#if IDE_C_SUPPORT
mDepClang . mDoDependencyCheck = true ;
#endif
if ( mBfResolveCompiler ! = null )
{
if ( reparseFiles )
QueueParseBeefFiles ( mBfResolveCompiler , false , project . mRootFolder ) ;
mBfResolveCompiler . QueueDeferredResolveAll ( ) ;
mBfResolveCompiler . QueueRefreshViewCommand ( ) ;
}
else
{
if ( reparseFiles )
QueueParseBeefFiles ( mBfResolveCompiler , false , project . mRootFolder ) ;
}
}
public void RenameProject ( Project project , String newName )
{
mWantsBeefClean = true ;
for ( var checkProject in mWorkspace . mProjects )
{
for ( var dep in checkProject . mDependencies )
{
if ( dep . mProjectName = = project . mProjectName )
{
dep . mProjectName . Set ( newName ) ;
checkProject . SetChanged ( ) ;
}
}
}
for ( var dep in mWorkspace . mProjectSpecs )
{
if ( dep . mProjectName = = project . mProjectName )
{
dep . mProjectName . Set ( newName ) ;
mWorkspace . SetChanged ( ) ;
}
}
project . mProjectName . Set ( newName ) ;
project . SetChanged ( ) ;
mWorkspace . ClearProjectNameCache ( ) ;
}
public void RemoveProject ( Project project )
{
RemoveProjectItems ( project ) ;
mWorkspace . SetChanged ( ) ;
mWorkspace . mProjects . Remove ( project ) ;
#if IDE_C_SUPPORT
using ( mDepClang . mMonitor . Enter ( ) )
{
mDepClang . mProjectBuildString . Remove ( project ) ;
}
#endif
if ( mWorkspace . mStartupProject = = project )
mWorkspace . mStartupProject = null ;
mWorkspace . FixOptions ( ) ;
CurrentWorkspaceConfigChanged ( ) ;
var bfCompilers = scope List < BfCompiler > ( ) ;
GetBfCompilers ( bfCompilers ) ;
for ( var bfCompiler in bfCompilers )
{
var bfProject = bfCompiler . mBfSystem . GetBfProject ( project ) ;
bfProject . SetDisabled ( true ) ;
bfCompiler . mBfSystem . RemoveBfProject ( project ) ;
bfCompiler . QueueDeleteBfProject ( bfProject ) ;
}
for ( var checkProject in mWorkspace . mProjects )
{
for ( var dep in checkProject . mDependencies )
{
if ( dep . mProjectName = = project . mProjectName )
{
@dep . Remove ( ) ;
delete dep ;
}
}
}
for ( var dep in mWorkspace . mProjectSpecs )
{
if ( dep . mProjectName = = project . mProjectName )
{
@dep . Remove ( ) ;
delete dep ;
}
}
List < WidgetWindow > closeList = scope . ( ) ;
for ( var window in gApp . mWindows )
{
if ( var widgetWindow = window as WidgetWindow )
{
if ( var projectProperties = widgetWindow . mRootWidget as ProjectProperties )
{
if ( projectProperties . [ Friend ] mProject = = project )
closeList . Add ( widgetWindow ) ;
}
}
}
for ( var window in closeList )
window . Close ( true ) ;
delete project ;
}
BfPassInstance CompileBeef ( Project hotProject , int32 hotIdx , bool lastCompileHadMessages , out bool hadBeef )
{
2019-10-29 04:56:42 -07:00
CompilerLog ( "IDEApp.CompileBeef" ) ;
2019-08-23 11:56:54 -07:00
hadBeef = false ;
mCompilingBeef = true ;
BeefCompileStarted ( ) ;
bool success = true ;
BfSystem bfSystem = mBfBuildSystem ;
BfCompiler bfCompiler = mBfBuildCompiler ;
BfPassInstance passInstance = bfSystem . CreatePassInstance ( ) ;
bfCompiler . QueueSetPassInstance ( passInstance ) ;
bfCompiler . QueueSetWorkspaceOptions ( hotProject , hotIdx ) ;
Workspace . Options workspaceOptions = GetCurWorkspaceOptions ( ) ;
bool tryQueueFiles = true ;
bool doCompile = false ;
if ( lastCompileHadMessages )
doCompile = true ;
if ( ( ! workspaceOptions . mIncrementalBuild ) & & ( ! lastCompileHadMessages ) )
{
tryQueueFiles = false ;
for ( var project in mWorkspace . mProjects )
{
if ( HasPendingBeefFiles ( false , project . mRootFolder ) )
tryQueueFiles = true ;
}
}
if ( hotProject ! = null )
{
mWorkspace . mHadHotCompileSinceLastFullCompile = true ;
}
else
{
if ( mWorkspace . mHadHotCompileSinceLastFullCompile )
{
doCompile = true ;
mWorkspace . mHadHotCompileSinceLastFullCompile = false ;
}
}
if ( mWorkspace . mForceNextCompile )
{
doCompile = true ;
mWorkspace . mForceNextCompile = false ;
}
if ( tryQueueFiles )
{
PreConfigureBeefSystem ( bfSystem , bfCompiler ) ;
for ( var project in mWorkspace . mProjects )
{
if ( SetupBeefProjectSettings ( bfSystem , bfCompiler , project ) )
{
doCompile | = QueueParseBeefFiles ( bfCompiler , ! workspaceOptions . mIncrementalBuild , project . mRootFolder ) ;
}
else if ( IsProjectEnabled ( project ) )
success = false ;
}
}
if ( ! success )
return null ;
for ( var project in mWorkspace . mProjects )
{
if ( ! project . mGeneralOptions . mTargetType . IsBeef )
continue ;
hadBeef = true ;
String projectBuildDir = scope String ( ) ;
GetWorkspaceBuildDir ( projectBuildDir ) ;
projectBuildDir . Append ( "/" , project . mProjectName ) ;
Directory . CreateDirectory ( projectBuildDir ) . IgnoreError ( ) ;
}
if ( ! hadBeef )
doCompile = false ;
if ( doCompile )
{
2019-10-05 10:24:58 -07:00
for ( var project in mWorkspace . mProjects )
{
// Regenerate these
DeleteContainerAndItems ! ( project . mCurBfOutputFileNames ) ;
project . mCurBfOutputFileNames = null ;
}
2019-08-23 11:56:54 -07:00
var dir = scope String ( ) ;
GetWorkspaceBuildDir ( dir ) ;
bfCompiler . QueueCompile ( dir ) ;
}
else
{
bfCompiler . ClearResults ( ) ;
passInstance . mCompileSucceeded = true ;
}
return passInstance ;
}
2019-10-14 17:49:10 -07:00
public bool DoResolveConfigString ( String platformName , Workspace . Options workspaceOptions , Project project , Project . Options options , StringView configString , String error , String result )
2019-08-23 11:56:54 -07:00
{
int i = result . Length ;
result . Append ( configString ) ;
bool hadError = false ;
for ( ; i < result . Length - 2 ; i + + )
{
if ( ( result [ i ] = = '$' ) & & ( result [ i + 1 ] = = '(' ) )
{
2019-09-18 13:01:18 -07:00
int parenPos = - 1 ;
int openCount = 1 ;
bool inString = false ;
char8 prevC = 0 ;
for ( int checkIdx = i + 2 ; checkIdx < result . Length ; checkIdx + + )
{
char8 c = result [ checkIdx ] ;
if ( inString )
{
if ( prevC = = '\\' )
{
// Slashed char
prevC = 0 ;
continue ;
}
if ( c = = '"' )
inString = false ;
}
else
{
if ( c = = '"' )
inString = true ;
else if ( c = = '(' )
openCount + + ;
else if ( c = = ')' )
{
openCount - - ;
if ( openCount = = 0 )
{
parenPos = checkIdx ;
break ;
}
}
}
prevC = c ;
}
2019-08-23 11:56:54 -07:00
if ( parenPos ! = - 1 )
ReplaceBlock :
2019-09-18 13:01:18 -07:00
do
2019-08-23 11:56:54 -07:00
{
String replaceStr = scope String ( result , i + 2 , parenPos - i - 2 ) ;
String newString = null ;
2019-09-18 13:01:18 -07:00
if ( replaceStr . Contains ( ' ' ) )
{
String cmd = scope . ( ) ;
List < String > args = scope . ( ) ;
for ( let str in replaceStr . Split ( ' ' , . RemoveEmptyEntries ) )
{
if ( cmd . IsEmpty )
cmd . Set ( str ) ;
else
{
String arg = scope : ReplaceBlock . ( ) ;
if ( str . StartsWith ( "\"" ) )
{
String unresolvedStr = scope . ( ) ;
str . UnQuoteString ( unresolvedStr ) ;
2019-10-14 17:49:10 -07:00
if ( ! DoResolveConfigString ( platformName , workspaceOptions , project , options , unresolvedStr , error , arg ) )
2019-09-18 13:01:18 -07:00
return false ;
}
else
arg . Append ( str ) ;
args . Add ( arg ) ;
}
}
String cmdErr = null ;
switch ( cmd )
{
case "Slash" :
if ( args . Count = = 1 )
{
newString = scope : ReplaceBlock . ( ) ;
args [ 0 ] . QuoteString ( newString ) ;
}
else
cmdErr = "Invalid number of arguments" ;
}
if ( newString = = null )
{
if ( error ! = null )
{
if ( cmdErr ! = null )
error . Set ( cmdErr ) ;
else
error . Set ( replaceStr ) ;
}
hadError = true ;
break ReplaceBlock ;
}
}
2019-08-23 11:56:54 -07:00
if ( ( newString = = null ) & & ( project ! = null ) )
{
switch ( replaceStr )
{
case "ProjectName" :
newString = project . mProjectName ;
break ;
}
}
if ( ( newString = = null ) & & ( options ! = null ) )
{
switch ( replaceStr )
{
case "Arguments" :
2019-11-28 09:12:49 -08:00
if ( mLaunchData ? . mArgs ! = null )
newString = mLaunchData . mArgs ;
else
newString = options . mDebugOptions . mCommandArguments ;
2019-08-23 11:56:54 -07:00
case "WorkingDir" :
2019-11-28 09:12:49 -08:00
if ( mLaunchData ? . mWorkingDir ! = null )
newString = mLaunchData . mWorkingDir ;
else
newString = options . mDebugOptions . mWorkingDirectory ;
2019-08-29 14:19:07 -07:00
case "TargetDir" :
{
if ( project . IsDebugSession )
{
let targetPath = scope : ReplaceBlock String ( ) ;
2019-10-14 17:49:10 -07:00
DoResolveConfigString ( platformName , workspaceOptions , project , options , options . mBuildOptions . mTargetName , error , targetPath ) ;
2019-08-29 14:19:07 -07:00
newString = scope : ReplaceBlock String ( ) ;
Path . GetDirectoryPath ( targetPath , newString ) ;
break ;
}
String targetDir = scope String ( ) ;
2019-10-14 17:49:10 -07:00
DoResolveConfigString ( platformName , workspaceOptions , project , options , options . mBuildOptions . mTargetDirectory , error , targetDir ) ;
2019-08-29 14:19:07 -07:00
newString = scope : ReplaceBlock String ( ) ;
Path . GetAbsolutePath ( targetDir , project . mProjectDir , newString ) ;
}
2019-08-23 11:56:54 -07:00
case "TargetPath" :
{
if ( project . IsDebugSession )
{
newString = scope : ReplaceBlock String ( ) ;
2019-10-14 17:49:10 -07:00
DoResolveConfigString ( platformName , workspaceOptions , project , options , options . mBuildOptions . mTargetName , error , newString ) ;
2019-08-23 11:56:54 -07:00
break ;
}
String targetDir = scope String ( ) ;
2019-10-14 17:49:10 -07:00
DoResolveConfigString ( platformName , workspaceOptions , project , options , options . mBuildOptions . mTargetDirectory , error , targetDir ) ;
2019-08-23 11:56:54 -07:00
newString = scope : ReplaceBlock String ( ) ;
Path . GetAbsolutePath ( targetDir , project . mProjectDir , newString ) ;
Utils . GetDirWithSlash ( newString ) ;
2019-10-14 17:49:10 -07:00
if ( ! DoResolveConfigString ( platformName , workspaceOptions , project , options , options . mBuildOptions . mTargetName , error , newString ) )
2019-09-18 13:01:18 -07:00
return false ;
2019-10-15 12:28:21 -07:00
let platformType = Workspace . PlatformType . GetFromName ( platformName ) ;
2019-10-23 07:12:36 -07:00
if ( options . mBuildOptions . mBuildKind . IsApplicationLib )
2019-10-15 12:28:21 -07:00
{
2019-10-23 07:12:36 -07:00
switch ( platformType )
{
case . Windows :
newString . Append ( ".lib" ) ;
case . iOS :
if ( options . mBuildOptions . mBuildKind = = . DynamicLib )
newString . Append ( ".dylib" ) ;
else
newString . Append ( ".a" ) ;
default :
if ( options . mBuildOptions . mBuildKind = = . DynamicLib )
newString . Append ( ".so" ) ;
else
newString . Append ( ".a" ) ;
}
}
else
{
switch ( platformType )
{
case . Windows :
if ( project . mGeneralOptions . mTargetType = = . BeefLib )
newString . Append ( ".lib" ) ;
else if ( project . mGeneralOptions . mTargetType = = . BeefDynLib )
newString . Append ( ".dll" ) ;
else if ( project . mGeneralOptions . mTargetType ! = . CustomBuild )
newString . Append ( ".exe" ) ;
case . macOS :
if ( project . mGeneralOptions . mTargetType = = Project . TargetType . BeefLib )
newString . Append ( ".dylib" ) ;
default :
if ( project . mGeneralOptions . mTargetType = = Project . TargetType . BeefLib )
newString . Append ( ".so" ) ;
}
2019-10-15 12:28:21 -07:00
}
2019-08-23 11:56:54 -07:00
}
case "ProjectDir" :
2019-08-27 08:04:41 -07:00
if ( project . IsDebugSession )
{
2019-09-18 13:01:18 -07:00
newString = scope : ReplaceBlock String ( ) ;
2019-08-27 08:04:41 -07:00
Path . GetDirectoryPath ( project . mProjectPath , newString ) ;
}
else
newString = project . mProjectDir ;
2019-08-23 11:56:54 -07:00
case "BuildDir" :
2019-09-18 13:01:18 -07:00
newString = scope : ReplaceBlock String ( ) ;
2019-08-23 11:56:54 -07:00
GetProjectBuildDir ( project , newString ) ;
//Debug.WriteLine("BuildDir: {0}", newString);
case "LinkFlags" :
newString = scope : ReplaceBlock String ( ) ;
2019-08-29 14:19:07 -07:00
if ( ( project . mGeneralOptions . mTargetType = = . BeefConsoleApplication ) | |
( project . mGeneralOptions . mTargetType = = . BeefWindowsApplication ) | |
2019-08-29 16:04:36 -07:00
( project . mGeneralOptions . mTargetType = = . BeefDynLib ) | |
( ( options . mBuildOptions . mBuildKind = = . Test ) & & ( project = = mWorkspace . mStartupProject ) ) )
2019-08-23 11:56:54 -07:00
{
2019-10-15 12:28:21 -07:00
let platformType = Workspace . PlatformType . GetFromName ( platformName ) ;
2019-10-15 14:39:47 -07:00
String rtName = scope String ( ) ;
String dbgName = scope String ( ) ;
BuildContext . GetRtLibNames ( platformType , workspaceOptions , options , false , rtName , dbgName ) ;
2019-10-15 12:28:21 -07:00
switch ( platformType )
2019-08-29 14:19:07 -07:00
{
2019-10-15 12:28:21 -07:00
case . Windows :
newString . Append ( rtName ) ;
if ( ! dbgName . IsEmpty )
newString . Append ( " " , dbgName ) ;
switch ( workspaceOptions . mAllocType )
{
case . JEMalloc :
newString . Append ( " jemalloc.lib" ) ;
case . TCMalloc :
newString . Append ( " tcmalloc.lib" ) ;
default :
}
case . macOS :
2019-10-29 05:01:04 -07:00
newString . AppendF ( "./{} -Wl,-rpath -Wl,@executable_path" , rtName ) ;
2019-10-15 12:28:21 -07:00
case . iOS :
case . Linux :
2019-10-29 09:06:51 -07:00
newString . AppendF ( "./{} -lpthread -ldl -Wl,-rpath -Wl,$ORIGIN" , rtName ) ;
2019-08-29 14:19:07 -07:00
default :
2019-10-15 12:28:21 -07:00
}
2019-08-29 14:19:07 -07:00
}
2019-08-23 11:56:54 -07:00
case "VSToolPath" :
2019-10-14 17:49:10 -07:00
if ( Workspace . PlatformType . GetPtrSizeByName ( platformName ) = = 4 )
2019-08-23 11:56:54 -07:00
newString = gApp . mSettings . mVSSettings . mBin32Path ;
else
newString = gApp . mSettings . mVSSettings . mBin64Path ;
case "VSToolPath_x86" :
newString = gApp . mSettings . mVSSettings . mBin32Path ;
case "VSToolPath_x64" :
newString = gApp . mSettings . mVSSettings . mBin64Path ;
}
}
if ( ( newString = = null ) & & ( mScriptManager ! = null ) )
{
switch ( replaceStr )
{
case "ScriptDir" :
if ( ( mScriptManager ! = null ) & & ( mScriptManager . mCurCmd ! = null ) )
{
2019-09-18 13:01:18 -07:00
newString = scope : ReplaceBlock String ( ) ;
2019-08-23 11:56:54 -07:00
Path . GetDirectoryPath ( mScriptManager . mCurCmd . mSrcFile , newString ) ;
}
}
}
if ( newString = = null )
{
switch ( replaceStr )
{
case "Configuration" :
newString = mConfigName ;
case "Platform" :
newString = mPlatformName ;
case "WorkspaceDir" :
if ( mWorkspace . mDir ! = null )
newString = mWorkspace . mDir ;
2019-08-27 08:04:41 -07:00
else if ( project . IsDebugSession )
{
2019-09-18 13:01:18 -07:00
newString = scope : ReplaceBlock String ( ) ;
2019-08-27 08:04:41 -07:00
Path . GetDirectoryPath ( project . mProjectPath , newString ) ;
}
case "BeefPath" :
newString = gApp . mInstallDir ;
2019-08-23 11:56:54 -07:00
default :
}
}
if ( newString = = null )
{
if ( error ! = null )
error . Set ( replaceStr ) ;
hadError = true ;
break ;
}
if ( newString ! = null )
{
result . Remove ( i , parenPos - i + 1 ) ;
result . Insert ( i , newString ) ;
i - - ;
}
}
}
}
return ! hadError ;
}
2019-10-14 17:49:10 -07:00
public bool ResolveConfigString ( String platformName , Workspace . Options workspaceOptions , Project project , Project . Options options , StringView configString , String errorContext , String outResult )
2019-08-23 11:56:54 -07:00
{
String errorString = scope String ( ) ;
2019-10-14 17:49:10 -07:00
if ( ! DoResolveConfigString ( platformName , workspaceOptions , project , options , configString , errorString , outResult ) )
2019-08-23 11:56:54 -07:00
{
OutputErrorLine ( "Invalid macro in {0}: {1}" , errorContext , errorString ) ;
return false ;
}
return true ;
}
public void GetWorkspaceBuildDir ( String outResult )
{
if ( mWorkspace . mDir = = null )
return ;
outResult . Append ( mWorkspace . mDir , "/build/" , mConfigName , "_" , mPlatformName ) ;
}
public void GetProjectBuildDir ( Project project , String outResult )
{
GetWorkspaceBuildDir ( outResult ) ;
if ( ! outResult . IsEmpty )
outResult . Append ( "/" , project . mProjectName ) ;
}
public void GetClangOutputFilePathWithoutExtension ( ProjectSource projectSource , String outResult )
{
GetProjectBuildDir ( projectSource . mProject , outResult ) ;
outResult . Append ( "/" ) ;
String fullPath = scope String ( ) ;
projectSource . GetFullImportPath ( fullPath ) ;
Path . GetFileNameWithoutExtension ( fullPath , outResult ) ;
}
public void GetClangBuildString ( Project project , Project . Options options , Workspace . Options workspaceOptions , bool isC , String clangOptions )
{
bool isClang = options . mCOptions . mCompilerType = = Project . CCompilerType . Clang ;
if ( options . mCOptions . mEmitDebugInfo )
{
if ( isClang )
{
clangOptions . Append ( "-g -fstandalone-debug " ) ;
if ( workspaceOptions . mToolsetType ! = . GNU )
clangOptions . Append ( "-gcodeview " ) ;
}
else
clangOptions . Append ( "-g " ) ;
}
//TODO:
var simd = workspaceOptions . mCSIMDSetting ;
if ( options . mCOptions . mSIMD ! = null )
simd = options . mCOptions . mSIMD . Value ;
switch ( simd )
{
case . SSE :
clangOptions . Append ( "-msse " ) ;
break ;
case . SSE2 :
clangOptions . Append ( "-msse2 " ) ;
break ;
case . SSE3 :
clangOptions . Append ( "-msse3 " ) ;
break ;
case . SSE4 :
clangOptions . Append ( "-msse4 " ) ;
break ;
case . SSE41 :
clangOptions . Append ( "-msse4.1 " ) ;
break ;
case . AVX :
clangOptions . Append ( "-mavx " ) ;
break ;
case . AVX2 :
clangOptions . Append ( "-mavx2 " ) ;
break ;
default :
}
if ( options . mCOptions . mEnableBeefInterop )
{
2019-10-01 12:46:38 -07:00
var beefPreprocMacros = scope DefinesSet ( ) ;
2019-08-23 11:56:54 -07:00
GetBeefPreprocessorMacros ( beefPreprocMacros ) ;
2019-10-01 12:46:38 -07:00
for ( var beefPreprocMacro in beefPreprocMacros . mDefines )
2019-08-23 11:56:54 -07:00
clangOptions . Append ( "-D" , beefPreprocMacro , " " ) ;
}
if ( options . mCOptions . mAllWarnings )
clangOptions . Append ( "-Wall " ) ;
var optimizationLevel = options . mCOptions . mOptimizationLevel ;
if ( optimizationLevel = = Project . COptimizationLevel . FromWorkspace )
optimizationLevel = ( Project . COptimizationLevel ) workspaceOptions . mCOptimizationLevel ;
clangOptions . AppendF ( "-{0} " , optimizationLevel ) ;
for ( var preprocMacro in options . mCOptions . mPreprocessorMacros )
{
clangOptions . Append ( "-D" , preprocMacro , " " ) ;
}
for ( var includePath in options . mCOptions . mIncludePaths )
{
var fullIncludePath = scope String ( ) ;
project . GetProjectFullPath ( includePath , fullIncludePath ) ;
if ( fullIncludePath . Contains ( ' ' ) )
clangOptions . Append ( "\"-I" , fullIncludePath , "\" " ) ;
else
clangOptions . Append ( "-I" , fullIncludePath , " " ) ;
}
if ( options . mCOptions . mCompilerType = = Project . CCompilerType . GCC )
{
2019-10-14 17:49:10 -07:00
if ( Workspace . PlatformType . GetPtrSizeByName ( gApp . mPlatformName ) = = 4 )
2019-08-23 11:56:54 -07:00
clangOptions . Append ( "-m32 " ) ;
else
clangOptions . Append ( "-m64 " ) ;
}
else
{
clangOptions . Append ( "--target=" ) ;
2019-10-23 07:12:36 -07:00
if ( TargetTriple . IsTargetTriple ( gApp . mPlatformName ) )
clangOptions . Append ( gApp . mPlatformName ) ;
else
Workspace . PlatformType . GetTargetTripleByName ( gApp . mPlatformName , workspaceOptions . mToolsetType , clangOptions ) ;
2019-08-23 11:56:54 -07:00
clangOptions . Append ( " " ) ;
if ( workspaceOptions . mToolsetType = = . GNU )
{
//
}
else
{
clangOptions . Append ( "-I\"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\include\" " ) ;
clangOptions . Append ( "-I\"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\atlmfc\\include\" " ) ;
clangOptions . Append ( "-I\"C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.14393.0\\ucrt\" " ) ;
clangOptions . Append ( "-I\"C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.14393.0\\um\" " ) ;
clangOptions . Append ( "-I\"C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.14393.0\\shared\" " ) ;
clangOptions . Append ( "-I\"C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.14393.0\\winrt\" " ) ;
}
}
if ( options . mCOptions . mNoOmitFramePointers )
clangOptions . Append ( "-fno-omit-frame-pointer " ) ;
if ( options . mCOptions . mGenerateLLVMAsm )
clangOptions . Append ( "-emit-llvm -S " ) ;
else
clangOptions . Append ( "-c " ) ;
if ( ! isC )
{
if ( ! String . IsNullOrEmpty ( options . mCOptions . mOtherCPPFlags ) )
clangOptions . Append ( options . mCOptions . mOtherCPPFlags , " " ) ;
clangOptions . Append ( "-std=c++14 " ) ;
}
else
{
if ( ! String . IsNullOrEmpty ( options . mCOptions . mOtherCFlags ) )
clangOptions . Append ( options . mCOptions . mOtherCFlags , " " ) ;
}
}
static void QuoteIfNeeded ( String str )
{
if ( ! str . Contains ( ' ' ) )
return ;
for ( int32 i = 0 ; i < str . Length ; i + + )
{
char8 c = str [ i ] ;
if ( ( c = = '\\' ) | | ( c = = '"' ) )
{
str . Insert ( i , '\\' ) ;
i + + ;
}
}
str . Insert ( 0 , '"' ) ;
str . Append ( '"' ) ;
}
ExecutionQueueCmd CompileSource ( Project project , Workspace . Options workspaceOptions , Project . Options options , String buildFileName , String addOptions = null )
{
String workspaceBuildDir = scope String ( ) ;
GetWorkspaceBuildDir ( workspaceBuildDir ) ;
String projectBuildDir = scope String ( workspaceBuildDir , "/" , project . mProjectName ) ;
String baseName = scope String ( ) ;
Path . GetFileNameWithoutExtension ( buildFileName , baseName ) ;
String objName = scope String ( projectBuildDir , "/" , baseName , ( options . mCOptions . mGenerateLLVMAsm ? ".ll" : ".obj" ) ) ;
String llvmDir = scope String ( IDEApp . sApp . mInstallDir ) ;
IDEUtils . FixFilePath ( llvmDir ) ;
llvmDir . Append ( "llvm/" ) ;
String gccExePath = "c:/mingw/bin/g++.exe" ;
String clangCppExePath = scope String ( llvmDir , "bin/clang++.exe" ) ;
String clangCExePath = scope String ( llvmDir , "bin/clang.exe" ) ;
String clangOptions = scope String ( buildFileName ) ;
QuoteIfNeeded ( clangOptions ) ;
clangOptions . Append ( " " ) ;
bool isC = false ;
var ext = scope String ( ) ;
Path . GetExtension ( buildFileName , ext ) ;
if ( ext = = ".c" )
isC = true ;
var buildStr = scope String ( ) ;
GetClangBuildString ( project , options , workspaceOptions , isC , buildStr ) ;
clangOptions . Append ( buildStr ) ;
int lastDot = objName . LastIndexOf ( '.' ) ;
String depFileName = scope String ( objName , 0 , lastDot ) ;
QuoteIfNeeded ( depFileName ) ;
depFileName . Append ( ".dep" ) ;
clangOptions . Append ( "-MD -MF " , depFileName , " " ) ;
if ( addOptions ! = null )
clangOptions . Append ( addOptions , " " ) ;
clangOptions . Append ( "-o " ) ;
String quotedObjName = scope String ( objName ) ;
QuoteIfNeeded ( quotedObjName ) ;
clangOptions . Append ( quotedObjName ) ;
String compilerExePath = ( options . mCOptions . mCompilerType = = Project . CCompilerType . GCC ) ? gccExePath : isC ? clangCExePath : clangCppExePath ;
return QueueRun ( compilerExePath , clangOptions , IDEApp . sApp . mInstallDir , . UTF8 ) ;
}
void SkipProjectCompile ( Project project , Project hotProject )
{
Project . Options options = GetCurProjectOptions ( project ) ;
if ( options = = null )
return ;
BfCompiler bfCompiler = mBfBuildCompiler ;
var bfProject = mBfBuildSystem . mProjectMap [ project ] ;
bool bfHadOutputChanges ;
List < String > bfFileNames = scope List < String > ( ) ;
bfCompiler . GetOutputFileNames ( bfProject , false , out bfHadOutputChanges , bfFileNames ) ;
2020-01-06 13:49:35 -08:00
defer ClearAndDeleteItems ( bfFileNames ) ;
2019-08-23 11:56:54 -07:00
if ( bfHadOutputChanges )
project . mNeedsTargetRebuild = true ;
}
2019-10-14 17:49:10 -07:00
void GetTargetPaths ( Project project , String platformName , Workspace . Options workspaceOptions , Project . Options options , List < String > outPaths )
2019-08-23 11:56:54 -07:00
{
String targetPath = scope String ( ) ;
2019-10-14 17:49:10 -07:00
ResolveConfigString ( platformName , workspaceOptions , project , options , "$(TargetPath)" , "Target path" , targetPath ) ;
2019-08-23 11:56:54 -07:00
outPaths . Add ( new String ( targetPath ) ) ;
#if BF_PLATFORM_WINDOWS
if ( ( project . mGeneralOptions . mTargetType = = . BeefConsoleApplication ) | |
( project . mGeneralOptions . mTargetType = = . BeefWindowsApplication ) )
{
if ( workspaceOptions . mToolsetType ! = . GNU )
{
String pdbPath = scope String ( ) ;
2019-08-27 08:04:41 -07:00
BuildContext . GetPdbPath ( targetPath , workspaceOptions , options , pdbPath ) ;
2019-08-23 11:56:54 -07:00
outPaths . Add ( new String ( pdbPath ) ) ;
}
}
#endif
}
2019-08-27 08:04:41 -07:00
public class ArgBuilder
2019-08-23 11:56:54 -07:00
{
String mTarget ;
bool mDoLongBreak ;
int mLastBreak ;
HashSet < String > mLinkPaths = new HashSet < String > ( ) ~ DeleteContainerAndItems ! ( _ ) ;
public this ( String target , bool doLongBreak )
{
mTarget = target ;
mDoLongBreak = doLongBreak ;
if ( mDoLongBreak )
mLastBreak = mTarget . LastIndexOf ( '\n' ) ;
else
mLastBreak = 0 ;
}
public void AddSep ( )
{
if ( mDoLongBreak )
{
if ( mTarget . Length - mLastBreak > 0x1F000 )
{
mLastBreak = mTarget . Length ;
mTarget . Append ( '\n' ) ;
return ;
}
}
mTarget . Append ( ' ' ) ;
}
public void AddFileName ( String filePath )
{
IDEUtils . AppendWithOptionalQuotes ( mTarget , filePath ) ;
/ * int lastSlash = Math . Max ( filePath . LastIndexOf ( '\\' ) , filePath . LastIndexOf ( '/' ) ) ;
if ( lastSlash = = - 1 )
{
IDEUtils . AppendWithOptionalQuotes ( mTarget , filePath ) ;
return ;
}
String fileDir = scope String ( filePath , 0 , lastSlash ) ;
String fileName = scope String ( filePath , lastSlash + 1 ) ;
String * strPtr = null ;
if ( mLinkPaths . TryAdd ( fileDir , out strPtr ) )
{
* strPtr = new String ( fileDir ) ;
mTarget . Append ( "-libpath:" ) ;
IDEUtils . AppendWithOptionalQuotes ( mTarget , fileDir ) ;
AddSep ( ) ;
}
IDEUtils . AppendWithOptionalQuotes ( mTarget , fileName ) ; * /
}
}
Project FindProject ( String projectName )
{
return mWorkspace . FindProject ( projectName ) ;
}
2019-08-27 08:04:41 -07:00
public bool GetDependentProjectList ( Project project , List < Project > orderedProjectList , List < Project > projectStack = null )
2019-08-23 11:56:54 -07:00
{
var useProjectStack = projectStack ;
if ( ( useProjectStack ! = null ) & & ( useProjectStack . Contains ( project ) ) )
{
String projectError = scope String ( "Circular dependency between projects: " ) ;
for ( int32 i = 0 ; i < useProjectStack . Count ; i + + )
{
if ( i > 0 )
projectError . Append ( ", " ) ;
projectError . Append ( useProjectStack [ i ] . mProjectName ) ;
}
2019-12-01 10:19:00 -08:00
OutputErrorLine ( projectError ) ;
2019-08-23 11:56:54 -07:00
return true ;
}
if ( orderedProjectList . Contains ( project ) )
return true ;
bool addSelf = true ;
if ( useProjectStack = = null )
{
useProjectStack = scope : : List < Project > ( ) ;
addSelf = false ;
}
useProjectStack . Add ( project ) ;
for ( var dep in project . mDependencies )
{
Project depProject = FindProject ( dep . mProjectName ) ;
if ( depProject = = null )
{
OutputLine ( StackStringFormat ! ( "Unable to find project '{0}', a dependency of project '{1}'" , dep . mProjectName , project . mProjectName ) ) ;
return false ;
}
if ( ! GetDependentProjectList ( depProject , orderedProjectList , useProjectStack ) )
return false ;
}
if ( addSelf )
{
useProjectStack . RemoveAt ( useProjectStack . Count - 1 ) ;
orderedProjectList . Add ( project ) ;
}
return true ;
}
void GetOrderedProjectList ( List < Project > orderedProjectList )
{
List < Project > projectStack = scope List < Project > ( ) ;
for ( var project in mWorkspace . mProjects )
GetDependentProjectList ( project , orderedProjectList , projectStack ) ;
}
public virtual void LoadFailed ( )
{
if ( mRunningTestScript )
mFailed = true ;
}
public virtual void TestFailed ( )
{
mLastTestFailed = true ;
}
protected virtual void CompileFailed ( )
{
if ( mTestManager ! = null )
mTestManager . BuildFailed ( ) ;
if ( mVerbosity > . Quiet )
OutputLine ( "Compile failed." ) ;
mLastCompileFailed = true ;
if ( mRunningTestScript )
{
if ( ! gApp . mScriptManager . mHadExpectingError )
gApp . mScriptManager . Fail ( "Compile failed" ) ;
}
else
{
Beep ( MessageBeepType . Error ) ;
}
}
void DbgCopyChangedFiles ( DateTime cmpTime , StringView srcDir , StringView destDir )
{
bool isFirstFile = true ;
for ( let fileEntry in Directory . EnumerateFiles ( srcDir ) )
{
var fileWriteTime = fileEntry . GetLastWriteTime ( ) ;
String dates = scope . ( ) ;
cmpTime . ToString ( dates ) ;
dates . Append ( "\n" ) ;
fileWriteTime . ToString ( dates ) ;
if ( fileWriteTime > mDbgHighestTime )
mDbgHighestTime = fileWriteTime ;
if ( fileWriteTime < cmpTime )
{
continue ;
}
String fileName = scope String ( ) ;
fileEntry . GetFileName ( fileName ) ;
if ( isFirstFile )
{
Directory . CreateDirectory ( destDir ) . IgnoreError ( ) ;
isFirstFile = false ;
}
String srcFile = scope . ( ) ;
srcFile . Append ( srcDir ) ;
srcFile . Append ( "/" ) ;
srcFile . Append ( fileName ) ;
String destFile = scope . ( ) ;
destFile . Append ( destDir ) ;
destFile . Append ( "/" ) ;
destFile . Append ( fileName ) ;
File . Copy ( srcFile , destFile ) ;
}
for ( let fileEntry in Directory . EnumerateDirectories ( srcDir ) )
{
String dirName = scope String ( ) ;
fileEntry . GetFileName ( dirName ) ;
String newSrcDir = scope String ( ) ;
newSrcDir . Append ( srcDir ) ;
newSrcDir . Append ( "/" ) ;
newSrcDir . Append ( dirName ) ;
String newDestDir = scope String ( ) ;
newDestDir . Append ( destDir ) ;
newDestDir . Append ( "/" ) ;
newDestDir . Append ( dirName ) ;
DbgCopyChangedFiles ( cmpTime , newSrcDir , newDestDir ) ;
}
}
void CompileResult ( String hotProjectName , bool success )
{
if ( mDbgCompileDir ! = null )
{
String compileResults = scope . ( ) ;
compileResults . AppendF ( "COMPILE {} {} {}: " , mDbgCompileIdx , mConfigName , mPlatformName ) ;
if ( hotProjectName ! = null )
compileResults . Append ( "Hot compile. " ) ;
if ( ! success )
compileResults . Append ( "FAILED\n" ) ;
else
compileResults . Append ( "SUCCESS\n" ) ;
String path = scope . ( ) ;
path . Append ( mDbgCompileDir ) ;
path . Append ( "log.txt" ) ;
File . WriteAllText ( path , compileResults , true ) ;
var prevHighestTime = mDbgHighestTime ;
for ( var project in mWorkspace . mProjects )
{
String buildDir = scope . ( ) ;
GetProjectBuildDir ( project , buildDir ) ;
String toPath = scope . ( ) ;
toPath . Append ( mDbgVersionedCompileDir ) ;
toPath . Append ( project . mProjectName ) ;
toPath . Append ( "/" ) ;
DbgCopyChangedFiles ( prevHighestTime , buildDir , toPath ) ;
}
}
}
void ProcessBeefCompileResults ( BfPassInstance passInstance , bool runAfter , Project hotProject , Stopwatch startStopWatch )
{
bool didCompileSucceed = true ;
if ( passInstance ! = null )
{
if ( mProfileCompileProfileId ! = 0 )
mProfileCompileProfileId . Dispose ( ) ;
while ( true )
{
String str = scope String ( ) ;
if ( ! passInstance . PopOutString ( str ) )
break ;
if ( mVerbosity = = . Quiet )
continue ;
if ( str . StartsWith ( ":" ) )
{
int spacePos = str . IndexOf ( ' ' ) ;
if ( spacePos > 0 )
{
bool wantsDisp = true ;
StringView msgType = StringView ( str , 0 , spacePos ) ;
if ( msgType = = ":warn" )
{
mLastCompileHadMessages = true ;
wantsDisp = mVerbosity > = . Minimal ;
}
else if ( msgType = = ":error" )
{
mLastCompileHadMessages = true ;
}
else if ( msgType = = ":low" )
wantsDisp = mVerbosity > = . Detailed ;
else if ( msgType = = ":med" )
wantsDisp = mVerbosity > = . Normal ;
if ( ! wantsDisp )
continue ;
str . Remove ( 0 , spacePos + 1 ) ;
}
}
str . Append ( "\n" ) ;
OutputSmart ( str ) ;
//OutputLine(str);
}
if ( ( passInstance . mFailed ) & & ( passInstance . mCompileSucceeded ) )
{
// This can happen if we can't load a Beef file
CompileFailed ( ) ;
passInstance . mCompileSucceeded = false ;
}
didCompileSucceed = passInstance . mCompileSucceeded ;
if ( didCompileSucceed )
{
mLastCompileSucceeded = true ;
mWorkspace . WithProjectItems ( scope ( item ) = >
{
if ( var projectSource = item as ProjectSource )
{
if ( IsBeefFile ( projectSource . mPath ) )
{
if ( ! projectSource . mHasChangedSinceLastCompile )
projectSource . mHasChangedSinceLastSuccessfulCompile = false ;
}
}
} ) ;
}
else
mLastCompileHadMessages = true ;
delete passInstance ;
}
if ( ( hotProject ! = null ) & & ( passInstance ! = null ) & & ( didCompileSucceed ) )
{
if ( ! mDebugger . mIsRunning )
{
OutputSmart ( "Hot compile failed - target no longer running" ) ;
CompileFailed ( ) ;
return ;
}
DebugManager . HotResolveFlags hotResolveFlags = . ActiveMethods ;
if ( mBfBuildCompiler . GetHasHotPendingDataChanges ( ) )
{
hotResolveFlags | = . Allocations ;
mHotResolveState = . PendingWithDataChanges ;
}
else
{
mHotResolveState = . Pending ;
}
mHotResolveTryIdx = 0 ;
mDebugger . InitiateHotResolve ( hotResolveFlags ) ;
return ;
}
List < Project > orderedProjectList = scope List < Project > ( ) ;
GetOrderedProjectList ( orderedProjectList ) ;
if ( ! didCompileSucceed )
{
// Failed, bail out
for ( var project in orderedProjectList )
{
SkipProjectCompile ( project , hotProject ) ;
}
CompileResult ( ( hotProject ! = null ) ? hotProject . mProjectName : null , false ) ;
CompileFailed ( ) ;
return ;
}
var completedCompileCmd = new BuildCompletedCmd ( ) ;
if ( hotProject ! = null )
completedCompileCmd . mHotProjectName = new String ( hotProject . mProjectName ) ;
//TODO: Pass in
//Project project = mWorkspace.mProjects[0];
bool success = true ;
List < String > hotFileNames = scope List < String > ( ) ;
defer ClearAndDeleteItems ( hotFileNames ) ;
2019-08-27 08:04:41 -07:00
Debug . Assert ( mBuildContext = = null ) ;
DeleteAndNullify ! ( mBuildContext ) ;
mBuildContext = new . ( ) ;
mBuildContext . mWorkspaceOptions = GetCurWorkspaceOptions ( ) ;
2019-08-23 11:56:54 -07:00
for ( var project in orderedProjectList )
{
2019-08-27 08:04:41 -07:00
if ( ! mBuildContext . QueueProjectCompile ( project , hotProject , completedCompileCmd , hotFileNames , runAfter ) )
2019-08-23 11:56:54 -07:00
success = false ;
}
if ( hotFileNames . Count > 0 )
{
// Why were we rehupping BEFORE hotLoad?
mDebugger . RehupBreakpoints ( false , false ) ;
String [ ] entries = scope String [ hotFileNames . Count ] ;
for ( int32 i = 0 ; i < hotFileNames . Count ; i + + )
entries [ i ] = hotFileNames [ i ] ;
//
mBfBuildCompiler . HotCommit ( ) ;
mDebugger . HotLoad ( entries , mWorkspace . HotCompileIdx ) ;
/ * if ( mDebugger . IsPaused ( ) )
PCChanged ( ) ; * /
//mDebugger.RehupBreakpoints(false);
RefreshWatches ( ) ;
}
if ( ! success )
CompileFailed ( ) ;
if ( ( runAfter ) & & ( success ) )
{
var startDebugCmd = new StartDebugCmd ( ) ;
startDebugCmd . mWasCompiled = true ;
startDebugCmd . mOnlyIfNotFailed = true ;
mExecutionQueue . Add ( startDebugCmd ) ;
}
if ( startStopWatch ! = null )
{
delete completedCompileCmd . mStopwatch ;
var stopwatch = new Stopwatch ( ) ;
stopwatch . CopyFrom ( startStopWatch ) ;
completedCompileCmd . mStopwatch = stopwatch ;
}
mExecutionQueue . Add ( completedCompileCmd ) ;
}
bool CompileAndRun ( )
{
if ( AreTestsRunning ( ) )
return false ;
2019-08-29 14:19:07 -07:00
if ( IsCompiling )
return false ;
2019-08-23 11:56:54 -07:00
if ( ! mExecutionQueue . IsEmpty )
{
if ( var processCompileCmd = mExecutionQueue . Back as ProcessBfCompileCmd )
{
processCompileCmd . mRunAfter = true ;
}
return false ;
}
2019-11-28 09:12:49 -08:00
if ( mInitialized )
DeleteAndNullify ! ( mLaunchData ) ;
2019-08-23 11:56:54 -07:00
mOutputPanel . Clear ( ) ;
OutputLine ( "Compiling..." ) ;
if ( ! Compile ( . RunAfter ) )
return false ;
return true ;
}
public void QueueProfiling ( int threadId , String desc , int sampleRate )
{
var profileCmd = new ProfileCmd ( ) ;
profileCmd . mThreadId = threadId ;
profileCmd . mDesc = new String ( desc ) ;
profileCmd . mSampleRate = sampleRate ;
if ( var processCompileCmd = mExecutionQueue . Back as ProcessBfCompileCmd )
{
processCompileCmd . mProfileCmd = profileCmd ;
}
}
[IDECommand]
void StopRunning ( )
{
if ( AreTestsRunning ( ) )
{
mTestManager . Stop ( ) ;
return ;
}
if ( mCrashDumpPath ! = null )
{
DeleteAndNullify ! ( mCrashDumpPath ) ;
mDebugger . Detach ( ) ;
mDebugger . mIsRunning = false ;
mExecutionPaused = false ;
}
if ( mDebugger . mIsRunning )
{
mDebugger . StopDebugging ( ) ;
}
}
enum CompileKind
{
Normal ,
RunAfter ,
Test
}
2019-11-28 09:12:49 -08:00
public void AutoGenerateStartupCode ( Project project )
{
2019-11-30 13:28:40 -08:00
// We have to save this to ensure any new project is actually created. Maybe overkill,
// but best to stay conservative since this path won't be heavily tested
if ( ! SaveAll ( ) )
return ;
2019-11-28 09:12:49 -08:00
String namespaceName = scope . ( ) ;
String className = scope . ( ) ;
String startupStr = project . mBeefGlobalOptions . mStartupObject ;
int dotPos = startupStr . LastIndexOf ( '.' ) ;
if ( dotPos ! = - 1 )
{
namespaceName . Append ( startupStr , 0 , dotPos ) ;
className . Append ( startupStr , dotPos + 1 ) ;
}
else
{
namespaceName . Append ( project . mProjectName ) ;
className . Append ( startupStr ) ;
}
String startupCode = scope . ( ) ;
startupCode . AppendF (
"" "
using System ;
namespace { }
{ {
class { }
{ {
public static int Main ( String [ ] args )
{ {
return 0 ;
} }
} }
} }
"" ", namespaceName, className);
String srcPath = scope . ( ) ;
project . mRootFolder . GetFullImportPath ( srcPath ) ;
2019-11-30 13:28:40 -08:00
Directory . CreateDirectory ( srcPath ) . IgnoreError ( ) ;
2019-11-28 09:12:49 -08:00
srcPath . Append ( Path . DirectorySeparatorChar ) ;
srcPath . Append ( "Program.bf" ) ;
if ( ! SafeWriteTextFile ( srcPath , startupCode ) )
return ;
OnWatchedFileChanged ( project . mRootFolder , . FileCreated , srcPath ) ;
2020-01-12 09:21:50 -08:00
2019-11-28 09:12:49 -08:00
if ( project . IsEmpty )
return ;
let projectSource = project . mRootFolder . mChildItems [ 0 ] as ProjectSource ;
if ( projectSource = = null )
return ;
ShowSourceFile ( srcPath ) ;
}
2019-08-23 11:56:54 -07:00
protected bool Compile ( CompileKind compileKind = . Normal , Project hotProject = null )
{
2019-08-29 14:19:07 -07:00
Debug . Assert ( mBuildContext = = null ) ;
2019-11-28 09:12:49 -08:00
if ( mWorkspace . mStartupProject ! = null )
{
if ( mWorkspace . mStartupProject . IsEmpty )
{
2020-01-12 09:21:50 -08:00
#if ! CLI
2019-11-28 09:12:49 -08:00
DarkDialog dlg = new DarkDialog ( "Initialize Project?" ,
2020-01-21 09:06:37 -08:00
scope String ( ) . . AppendF ( "Project '{}' does not contain any source code. Do you want to auto-generate some startup code?" , mWorkspace . mStartupProject . mProjectName )
2019-11-28 09:12:49 -08:00
, DarkTheme . sDarkTheme . mIconError ) ;
dlg . mWindowFlags | = . Modal ;
dlg . AddYesNoButtons ( new ( dlg ) = >
{
AutoGenerateStartupCode ( mWorkspace . mStartupProject ) ;
} ,
new ( dlg ) = >
{
} ) ;
dlg . PopupWindow ( GetActiveWindow ( ) ) ;
2020-01-12 09:21:50 -08:00
#else
OutputErrorLine ( "The project '{}' does not contain any source code. Run with '-generate' to auto-generate some startup code." , mWorkspace . mStartupProject . mProjectName ) ;
#endif
2019-11-28 09:12:49 -08:00
OutputLine ( "Aborted - no startup project code found." ) ;
return false ;
}
}
2019-10-01 12:46:38 -07:00
let platform = Workspace . PlatformType . GetFromName ( mPlatformName ) ;
let hostPlatform = Workspace . PlatformType . GetHostPlatform ( ) ;
if ( platform = = . Unknown )
{
OutputErrorLine ( "Failed to compiler for unknown platform '{}'" , mPlatformName ) ;
return false ;
}
bool canCompile = false ;
if ( platform = = hostPlatform )
{
canCompile = true ;
}
else
{
canCompile = false ;
}
2019-10-15 12:28:21 -07:00
//TODO:
canCompile = true ;
2019-10-01 12:46:38 -07:00
if ( ! canCompile )
{
OutputErrorLine ( "Cannot compile for platform '{}' from host platform '{}'" , platform , hostPlatform ) ;
return false ;
}
2019-08-23 11:56:54 -07:00
if ( mDbgCompileDump )
{
mDbgCompileIdx + + ;
String dbgBuildDir = scope . ( ) ;
dbgBuildDir . Append ( mInstallDir ) ;
dbgBuildDir . Append ( "_dbg/" ) ;
String exePath = scope . ( ) ;
Environment . GetExecutableFilePath ( exePath ) ;
Path . GetFileNameWithoutExtension ( exePath , dbgBuildDir ) ;
/ * String exePath = scope . ( ) ;
Environment . GetExecutableFilePath ( exePath ) ;
String exeName = scope . ( ) ;
Path . GetFileNameWithoutExtension ( exePath , exeName ) ;
String dbgBuildDir = scope String ( mInstallDir , "dbg_build_" , exeName ) ; * /
if ( mDbgCompileIdx = = 0 )
{
String tempDirName = scope . ( ) ;
tempDirName . Append ( mInstallDir ) ;
tempDirName . AppendF ( "_dbg/_{0}" , DateTime . Now . Ticks ) ;
if ( Directory . Move ( dbgBuildDir , tempDirName ) case . Err ( let err ) )
{
if ( err ! = . NotFound )
{
Fail ( scope String . . AppendF ( "Failed to rename {0} to {1}" , dbgBuildDir , tempDirName ) ) ;
return false ;
}
}
String delDirName = new String ( tempDirName ) ;
ThreadPool . QueueUserWorkItem ( new ( ) = >
{
Utils . DelTree ( delDirName ) . IgnoreError ( ) ;
delete delDirName ;
} ) ;
bool worked = false ;
for ( int i < 20 )
{
if ( Directory . CreateDirectory ( dbgBuildDir ) case . Ok )
{
worked = true ;
break ;
}
Thread . Sleep ( 100 ) ;
}
Debug . Assert ( worked ) ;
}
dbgBuildDir . Append ( "/" ) ;
if ( mDbgCompileIdx = = 0 )
{
delete mDbgCompileDir ;
mDbgCompileDir = new String ( dbgBuildDir ) ;
for ( var project in mWorkspace . mProjects )
{
String buildDir = scope . ( ) ;
GetProjectBuildDir ( project , buildDir ) ;
String toPath = scope . ( ) ;
toPath . Append ( mDbgCompileDir ) ;
toPath . Append ( "/init/" ) ;
toPath . Append ( project . mProjectName ) ;
toPath . Append ( "/" ) ;
DbgCopyChangedFiles ( default , buildDir , toPath ) ;
}
}
dbgBuildDir . AppendF ( "{0}" , mDbgCompileIdx ) ;
Directory . CreateDirectory ( dbgBuildDir ) ;
DeleteAndNullify ! ( mDbgVersionedCompileDir ) ;
mDbgVersionedCompileDir = new String ( dbgBuildDir ) ;
mDbgVersionedCompileDir . Append ( "/" ) ;
}
if ( ( AreTestsRunning ( ) ) & & ( compileKind ! = . Test ) )
{
return false ;
}
var workspaceOptions = GetCurWorkspaceOptions ( ) ;
if ( compileKind = = . RunAfter )
{
if ( workspaceOptions . mBuildKind = = . Test )
{
OutputLineSmart ( "ERROR: Cannot directly run Test workspace configurations. Use the 'Test' menu to run or debug tests." ) ;
return false ;
}
}
if ( Workspace . PlatformType . GetFromName ( mPlatformName ) = = . Windows )
{
if ( ! mSettings . mVSSettings . IsConfigured ( ) )
mSettings . mVSSettings . SetDefaults ( ) ;
if ( ! mSettings . mVSSettings . IsConfigured ( ) )
{
String err =
"" "
Beef requires the Microsoft C + + build tools for Visual Studio 2013 or later , but they don ' t seem to be installed .
Install just Microsoft Visual C + + Build Tools or the entire Visual Studio suite from :
https : //visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019
"" ";
#if CLI
Fail ( err ) ;
#else
DarkDialog dlg = new DarkDialog ( "Visual C++ Not Found" , err , DarkTheme . sDarkTheme . mIconError ) ;
dlg . mWindowFlags | = . Modal ;
dlg . AddOkCancelButtons ( new ( dlg ) = >
{
ProcessStartInfo psi = scope ProcessStartInfo ( ) ;
psi . SetFileName ( "https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019" ) ;
psi . UseShellExecute = true ;
psi . SetVerb ( "Open" ) ;
var process = scope SpawnedProcess ( ) ;
process . Start ( psi ) . IgnoreError ( ) ;
} ,
new ( dlg ) = >
{
} ) ;
( ( DarkButton ) dlg . mButtons [ 0 ] ) . Label = "Open Link" ;
2019-09-05 08:18:24 -07:00
dlg . PopupWindow ( GetActiveWindow ( ) ) ;
2019-08-23 11:56:54 -07:00
MessageBeep ( . Error ) ;
#endif
}
}
if ( mProfileCompile )
mProfileCompileProfileId = Profiler . StartSampling ( "Compile" ) ;
if ( mWantsBeefClean )
{
// We must finish cleaning before we can compile
while ( mWantsBeefClean )
{
UpdateCompilersAndDebugger ( ) ;
}
}
if ( ( ! workspaceOptions . mIncrementalBuild ) & & ( mCompileSinceCleanCount > 0 ) & & ( hotProject = = null ) )
{
delete mBfBuildCompiler ;
delete mBfBuildSystem ;
mBfBuildSystem = new BfSystem ( ) ;
mBfBuildCompiler = mBfBuildSystem . CreateCompiler ( false ) ;
for ( var project in mWorkspace . mProjects )
{
mBfBuildSystem . AddProject ( project ) ;
}
}
bool lastCompileHadMessages = mLastCompileHadMessages ;
mLastCompileFailed = false ;
mLastCompileSucceeded = false ;
mLastCompileHadMessages = false ;
mCompileSinceCleanCount + + ;
ShowPanel ( mOutputPanel , false ) ;
if ( mDisableBuilding )
{
OutputLineSmart ( "ERROR: Compiling disabled!" ) ;
return false ;
}
if ( mExecutionQueue . Count > 0 )
return false ;
if ( ( mDebugger ! = null ) & & ( mDebugger . mIsRunning ) & & ( hotProject = = null ) )
{
Debug . Assert ( ! mDebugger . mIsRunningCompiled ) ;
Debug . Assert ( compileKind = = . Normal ) ;
}
mHaveSourcesChangedExternallySinceLastCompile = false ;
mHaveSourcesChangedInternallySinceLastCompile = false ;
mWorkspace . SetupProjectCompileInstance ( hotProject ! = null ) ;
int32 hotIdx = mWorkspace . HotCompileIdx ;
if ( hotProject = = null )
{
Debug . Assert ( hotIdx = = 0 ) ;
}
// Set position for breakpoints here only on first one.
// For hotload we do it later.
//if (!mDebugger.mIsRunning)
//mDebugger.RehupBreakpoints(true);
SaveClangFiles ( ) ;
if ( compileKind = = . RunAfter )
{
DeleteAndNullify ! ( mCompileAndRunStopwatch ) ;
mCompileAndRunStopwatch = new Stopwatch ( ) ;
mCompileAndRunStopwatch . Start ( ) ;
}
//mBfBuildCompiler.QueueStartTiming();
mBfBuildCompiler . ClearCompletionPercentage ( ) ;
BfPassInstance passInstance = null ;
passInstance = CompileBeef ( hotProject , hotIdx , lastCompileHadMessages , let hadBeef ) ;
if ( passInstance = = null )
{
CompileFailed ( ) ;
return false ;
}
ProcessBfCompileCmd processCompileCmd = new ProcessBfCompileCmd ( ) ;
processCompileCmd . mBfPassInstance = passInstance ;
processCompileCmd . mRunAfter = compileKind = = . RunAfter ;
processCompileCmd . mHotProject = hotProject ;
processCompileCmd . mStopwatch = new Stopwatch ( ) ;
processCompileCmd . mStopwatch . Start ( ) ;
processCompileCmd . mHadBeef = hadBeef ;
mExecutionQueue . Add ( processCompileCmd ) ;
return true ;
}
void CheckDebugVisualizers ( )
{
scope AutoBeefPerf ( "CheckDebugVisualizers" ) ;
String dbgVis = scope String ( ) ;
dbgVis . Append ( mInstallDir , "BeefDbgVis.toml" ) ;
mWorkspace . WithProjectItems ( scope ( projectItem ) = >
{
var projectSource = projectItem as ProjectSource ;
if ( projectSource = = null )
return ;
if ( ( projectSource . mName . StartsWith ( "BeefDbgVis" ) ) & &
( projectSource . mName . EndsWith ( ".toml" ) ) )
{
dbgVis . Append ( "\n" ) ;
projectSource . GetFullImportPath ( dbgVis ) ;
}
} ) ;
mDebugger . LoadDebugVisualizers ( dbgVis ) ;
//mDebugger.LoadDebugVisualizers(scope String(mInstallDir, "BeefDbgVis.toml"));
}
bool DebugProject ( bool wasCompiled )
{
mProfilePanel . Clear ( ) ;
if ( mWorkspace . mStartupProject = = null )
{
OutputLineSmart ( "ERROR: No startup project started" ) ;
return false ;
}
var project = mWorkspace . mStartupProject ;
var workspaceOptions = GetCurWorkspaceOptions ( ) ;
var options = GetCurProjectOptions ( project ) ;
if ( options = = null )
{
OutputLineSmart ( "ERROR: Startup project '{0}' not enabled" , mWorkspace . mStartupProject . mProjectName ) ;
return false ;
}
mDebugger . ClearInvalidBreakpoints ( ) ;
mTargetDidInitBreak = false ;
mTargetHadFirstBreak = false ;
//options.mDebugOptions.mCommand
2019-09-02 17:39:47 -07:00
String launchPath = scope String ( ) ;
2019-10-14 17:49:10 -07:00
ResolveConfigString ( mPlatformName , workspaceOptions , project , options , options . mDebugOptions . mCommand , "debug command" , launchPath ) ;
2019-08-23 11:56:54 -07:00
String arguments = scope String ( ) ;
2019-10-14 17:49:10 -07:00
ResolveConfigString ( mPlatformName , workspaceOptions , project , options , "$(Arguments)" , "debug command arguments" , arguments ) ;
2019-08-23 11:56:54 -07:00
String workingDirRel = scope String ( ) ;
2019-10-14 17:49:10 -07:00
ResolveConfigString ( mPlatformName , workspaceOptions , project , options , "$(WorkingDir)" , "debug working directory" , workingDirRel ) ;
2019-08-23 11:56:54 -07:00
var workingDir = scope String ( ) ;
Path . GetAbsolutePath ( workingDirRel , project . mProjectDir , workingDir ) ;
2019-09-02 17:39:47 -07:00
String targetPath = scope . ( ) ;
2019-10-14 17:49:10 -07:00
ResolveConfigString ( mPlatformName , workspaceOptions , project , options , "$(TargetPath)" , "Target path" , targetPath ) ;
2019-09-02 17:39:47 -07:00
IDEUtils . FixFilePath ( launchPath ) ;
IDEUtils . FixFilePath ( targetPath ) ;
2019-08-23 11:56:54 -07:00
if ( workingDir . IsEmpty )
2019-09-02 17:39:47 -07:00
Path . GetDirectoryPath ( launchPath , workingDir ) ;
2019-08-23 11:56:54 -07:00
if ( ! Directory . Exists ( workingDir ) )
{
OutputErrorLine ( scope String ( ) . . AppendF ( "Unable to locate working directory '{0}'" , workingDir ) ) ;
return false ;
}
var envVars = scope Dictionary < String , String > ( ) ;
defer { for ( var kv in envVars ) { delete kv . key ; delete kv . value ; } }
Environment . GetEnvironmentVariables ( envVars ) ;
for ( var envVar in options . mDebugOptions . mEnvironmentVars )
{
int eqPos = envVar . IndexOf ( '=' , 1 ) ;
if ( eqPos = = - 1 )
{
OutputErrorLine ( "Invalid environment variable: {0}" , envVar ) ;
}
else
{
Environment . SetEnvironmentVariable ( envVars , StringView ( envVar , 0 , eqPos ) , StringView ( envVar , eqPos + 1 ) ) ;
}
}
var envBlock = scope List < char8 > ( ) ;
Environment . EncodeEnvironmentVariables ( envVars , envBlock ) ;
2019-09-02 17:39:47 -07:00
if ( launchPath . IsWhiteSpace )
2019-08-23 11:56:54 -07:00
{
Fail ( scope String ( ) . . AppendF ( "No debug command specified in '{}' properties" , project . mProjectName ) ) ;
return false ;
}
2019-09-02 17:39:47 -07:00
if ( ! mDebugger . OpenFile ( launchPath , targetPath , arguments , workingDir , envBlock , wasCompiled ) )
2019-08-23 11:56:54 -07:00
{
DeleteAndNullify ! ( mCompileAndRunStopwatch ) ;
return false ;
}
CheckDebugVisualizers ( ) ;
mDebugger . mIsRunning = true ;
WithSourceViewPanels ( scope ( sourceView ) = >
{
sourceView . RehupAlias ( ) ;
} ) ;
mDebugger . RehupBreakpoints ( true ) ;
mDebugger . Run ( ) ;
mModulePanel . ModulesChanged ( ) ;
if ( mCompileAndRunStopwatch ! = null )
{
mCompileAndRunStopwatch . Stop ( ) ;
OutputLine ( "Compile-to-debug time: {0:0.00}s" , mCompileAndRunStopwatch . ElapsedMilliseconds / 1000.0f ) ;
}
if ( ( mTargetStartWithStep ) & & ( mMainBreakpoint = = null ) )
{
// The idea is that we don't want to step into static initializers, so we
// temporarily break on _main and then we single step
//mMainBreakpoint = mDebugger.CreateSymbolBreakpoint("_ZN3Hey4Dude3Bro9TestClass4MainEv");
if ( ( project . mGeneralOptions . mTargetType = = Project . TargetType . BeefConsoleApplication ) | |
( project . mGeneralOptions . mTargetType = = Project . TargetType . BeefWindowsApplication ) )
2019-10-23 11:30:59 -07:00
mMainBreakpoint = mDebugger . CreateSymbolBreakpoint ( "-BeefStartProgram" ) ;
2019-08-23 11:56:54 -07:00
else
2019-08-27 08:04:41 -07:00
{
2019-08-23 11:56:54 -07:00
mMainBreakpoint = mDebugger . CreateSymbolBreakpoint ( "-main" ) ;
2019-08-27 08:04:41 -07:00
#if BF_PLATFORM_WINDOWS
//mMainBreakpoint2 = mDebugger.CreateSymbolBreakpoint("-WinMain");
#endif
}
2019-08-23 11:56:54 -07:00
}
return true ;
}
public void Attach ( Process process , DebugManager . AttachFlags attachFlags )
{
UpdateTitle ( process . ProcessName ) ;
OutputLine ( "Attaching to process id {0}: {1}" , process . Id , process . ProcessName ) ;
mExecutionPaused = false ;
mTargetDidInitBreak = false ;
mTargetHadFirstBreak = false ;
if ( mDebugger . mIsRunning )
{
Fail ( "Already debugging a target" ) ;
return ;
}
if ( ! mDebugger . Attach ( process , attachFlags ) )
{
Fail ( "Failed to attach to process" ) ;
return ;
}
CheckDebugVisualizers ( ) ;
mDebugger . mIsRunning = true ;
mDebugger . RehupBreakpoints ( true ) ;
mDebugger . Run ( ) ;
mIsAttachPendingSourceShow = true ;
}
void ShowPanel ( Widget panel , bool setFocus = true )
{
WithTabs ( scope ( tab ) = >
{
if ( tab . mContent = = panel )
tab . Activate ( setFocus ) ;
} ) ;
}
2019-09-07 06:40:03 -07:00
void ShowStartupFile ( )
{
2019-09-12 09:48:38 -07:00
bool hasSourceShown = false ;
WithSourceViewPanels ( scope [ & ] ( panel ) = >
{
hasSourceShown = true ;
} ) ;
if ( hasSourceShown )
return ;
2019-09-07 06:40:03 -07:00
if ( mWorkspace . mStartupProject ! = null )
{
bool didShow = false ;
mWorkspace . mStartupProject . WithProjectItems ( scope [ & ] ( item ) = >
{
if ( didShow )
return ;
if ( ( item . mName . Equals ( "main.bf" , . OrdinalIgnoreCase ) ) | |
( item . mName . Equals ( "program.bf" , . OrdinalIgnoreCase ) ) )
{
ShowProjectItem ( item , false ) ;
didShow = true ;
}
} ) ;
}
}
2019-08-23 11:56:54 -07:00
public void CreateDefaultLayout ( )
{
//TODO:
//mConfigName.Set("Dbg");
2019-10-05 10:24:58 -07:00
if ( ( ! mRunningTestScript ) & & ( ! mIsFirstRun ) & & ( LoadDefaultLayoutData ( ) ) )
2019-08-23 11:56:54 -07:00
{
return ;
}
bool docOnlyView = false ;
TabbedView projectTabbedView = CreateTabbedView ( ) ;
SetupTab ( projectTabbedView , "Workspace" , 0 , mProjectPanel , false ) ;
2019-10-05 10:24:58 -07:00
projectTabbedView . SetRequestedSize ( GS ! ( 200 ) , GS ! ( 200 ) ) ;
projectTabbedView . mWidth = GS ! ( 200 ) ;
2019-08-23 11:56:54 -07:00
//TabbedView propertiesView = CreateTabbedView();
//propertiesView.AddTab("Properties", 0, mPropertiesPanel, false);
//propertiesView.SetRequestedSize(250, 250);
if ( ! docOnlyView )
{
mDockingFrame . AddDockedWidget ( projectTabbedView , null , DockingFrame . WidgetAlign . Left ) ;
EnsureDocumentArea ( ) ;
//mDockingFrame.AddDockedWidget(propertiesView, null, DockingFrame.WidgetAlign.Right);
}
var outputTabbedView = CreateTabbedView ( ) ;
mDockingFrame . AddDockedWidget ( outputTabbedView , null , DockingFrame . WidgetAlign . Bottom ) ;
2019-10-05 10:24:58 -07:00
outputTabbedView . SetRequestedSize ( GS ! ( 250 ) , GS ! ( 250 ) ) ;
2019-08-23 11:56:54 -07:00
2019-10-05 10:24:58 -07:00
SetupTab ( outputTabbedView , "Output" , GS ! ( 150 ) , mOutputPanel , false ) ;
SetupTab ( outputTabbedView , "Immediate" , GS ! ( 150 ) , mImmediatePanel , false ) ;
2019-08-23 11:56:54 -07:00
//outputTabbedView.AddTab("Find Results", 150, mFindResultsPanel, false);
var watchTabbedView = CreateTabbedView ( ) ;
2019-10-05 10:24:58 -07:00
watchTabbedView . SetRequestedSize ( GS ! ( 250 ) , GS ! ( 250 ) ) ;
2019-08-23 11:56:54 -07:00
mDockingFrame . AddDockedWidget ( watchTabbedView , outputTabbedView , DockingFrame . WidgetAlign . Left ) ;
SetupTab ( watchTabbedView , "Auto" , 150 , mAutoWatchPanel , false ) ;
SetupTab ( watchTabbedView , "Watch" , 150 , mWatchPanel , false ) ;
SetupTab ( watchTabbedView , "Memory" , 150 , mMemoryPanel , false ) ;
SetupTab ( outputTabbedView , "Call Stack" , 150 , mCallStackPanel , false ) ;
2019-09-07 06:40:03 -07:00
SetupTab ( outputTabbedView , "Threads" , 150 , mThreadPanel , false ) ;
2019-08-23 11:56:54 -07:00
}
protected void CreateBfSystems ( )
{
scope AutoBeefPerf ( "IDEApp.CreateBfSystems" ) ;
#if ! CLI
if ( ! mNoResolve )
{
mBfResolveSystem = new BfSystem ( ) ;
mBfResolveCompiler = mBfResolveSystem . CreateCompiler ( true ) ;
mBfResolveHelper = new BfResolveHelper ( ) ;
}
#if IDE_C_SUPPORT
mResolveClang = new ClangCompiler ( true ) ;
#endif
#endif
mCompileSinceCleanCount = 0 ;
mBfBuildSystem = new BfSystem ( ) ;
mBfBuildCompiler = mBfBuildSystem . CreateCompiler ( false ) ;
#if IDE_C_SUPPORT
mDepClang = new ClangCompiler ( false ) ;
mDepClang . mPairedCompiler = mResolveClang ;
mResolveClang . mPairedCompiler = mDepClang ;
#endif
}
void UpdateTitle ( StringView titleOverride = default )
{
String title = scope String ( ) ;
if ( ( mWorkspace ! = null ) & & ( mWorkspace . mName ! = null ) )
{
title . Append ( mWorkspace . mName ) ;
title . Append ( " - " ) ;
}
if ( titleOverride . Ptr ! = null )
{
title . Append ( titleOverride ) ;
title . Append ( " - " ) ;
}
title . Append ( "Beef IDE" ) ;
2019-09-18 08:13:00 -07:00
String extraStr = scope . ( ) ;
String exePath = scope . ( ) ;
Environment . GetExecutableFilePath ( exePath ) ;
if ( exePath . Contains ( @"\host\" ) )
extraStr . Append ( "host" ) ;
String exeFileName = scope . ( ) ;
Path . GetFileNameWithoutExtension ( exePath , exeFileName ) ;
int slashPos = exeFileName . IndexOf ( '_' ) ;
if ( slashPos ! = - 1 )
{
if ( ! extraStr . IsEmpty )
extraStr . Append ( " " ) ;
extraStr . Append ( exeFileName , slashPos + 1 ) ;
}
if ( ! extraStr . IsEmpty )
title . AppendF ( " [{}]" , extraStr ) ;
2019-08-23 11:56:54 -07:00
mMainWindow . SetTitle ( title ) ;
}
public void CreateSpellChecker ( )
{
mSpellChecker = new SpellChecker ( ) ;
if ( mSpellChecker . Init ( scope String ( mInstallDir , "en_US" ) ) case . Err )
{
DeleteAndNullify ! ( mSpellChecker ) ;
}
}
2020-01-24 11:51:31 -08:00
public FileVersionInfo GetVersionInfo ( out DateTime exeTime )
2019-10-09 16:18:11 -07:00
{
2020-01-24 11:51:31 -08:00
exeTime = default ;
2019-10-09 16:18:11 -07:00
if ( mVersionInfo = = null )
{
String exeFilePath = scope . ( ) ;
Environment . GetExecutableFilePath ( exeFilePath ) ;
mVersionInfo = new . ( ) ;
mVersionInfo . GetVersionInfo ( exeFilePath ) . IgnoreError ( ) ;
2020-01-24 13:45:30 -08:00
#if BF_PLATFORM_WINDOWS
2020-01-24 11:51:31 -08:00
exeTime = File . GetLastWriteTime ( exeFilePath ) . GetValueOrDefault ( ) ;
2020-01-24 13:45:30 -08:00
#endif
2019-10-09 16:18:11 -07:00
}
return mVersionInfo ;
}
2019-08-23 11:56:54 -07:00
#if ! CLI
public override void Init ( )
{
scope AutoBeefPerf ( "IDEApp.Init" ) ;
2019-09-27 13:03:47 -07:00
//int zag = 123;
2019-09-22 08:25:38 -07:00
if ( mVerbosity = = . Default )
mVerbosity = . Detailed ;
2019-09-07 06:40:03 -07:00
mStartedWithTestScript = mRunningTestScript ;
2019-08-23 11:56:54 -07:00
mCommands . Init ( ) ;
EnableGCCollect = mEnableGCCollect ;
if ( mConfigName . IsEmpty )
mConfigName . Set ( "Debug" ) ;
if ( mPlatformName . IsEmpty )
2019-10-15 14:39:47 -07:00
mPlatformName . Set ( sPlatform64Name ? ? sPlatform32Name ) ;
2019-08-23 11:56:54 -07:00
Directory . GetCurrentDirectory ( mInitialCWD ) ;
2019-09-18 08:13:00 -07:00
#if DEBUG
//mColorMatrix = Matrix4.Identity;
#endif
2019-08-23 11:56:54 -07:00
base . Init ( ) ;
mSettings . Apply ( ) ;
//Yoop();
/ * for ( int i = 0 ; i < 100 * 1024 * 1024 ; i + + )
{
mTestString . Append ( "Hey, this is a test string!" ) ;
} * /
mAutoDirty = false ;
WidgetWindow . sOnWindowClosed . Add ( new = > HandleWindowClosed ) ;
//mProjectDir = BFApp.mApp.mInstallDir + "../../";
if ( ! mRunningTestScript )
{
// User setting can affect automated testing, so use default settings
2019-10-05 10:24:58 -07:00
if ( ! mIsFirstRun )
mSettings . Load ( ) ;
2019-08-23 11:56:54 -07:00
mSettings . Apply ( ) ;
2019-09-16 09:32:02 -07:00
mIsFirstRun = ! mSettings . mLoadedSettings ;
2019-09-23 14:55:26 -07:00
#if ! CLI & & BF_PLATFORM_WINDOWS
if ( ! mSettings . mTutorialsFinished . mRanDebug )
{
let exePath = scope String ( ) ;
Environment . GetExecutableFilePath ( exePath ) ;
if ( exePath . EndsWith ( "_d.exe" , . OrdinalIgnoreCase ) )
{
if ( Windows . MessageBoxA ( default , "Are you sure you want to run the debug build of the Beef IDE? This is useful for debugging Beef issues but execution speed will be much slower." , "RUN DEBUG?" ,
Windows . MB_ICONQUESTION | Windows . MB_YESNO ) ! = Windows . IDYES )
{
Stop ( ) ;
return ;
}
}
mSettings . mTutorialsFinished . mRanDebug = true ;
}
#endif
2019-08-23 11:56:54 -07:00
}
DarkTheme aTheme = new DarkTheme ( ) ;
aTheme . Init ( ) ;
ThemeFactory . mDefault = aTheme ;
mTinyCodeFont = new Font ( ) ;
mCodeFont = new Font ( ) ;
//mCodeFont = Font.LoadFromFile(BFApp.sApp.mInstallDir + "fonts/SourceCodePro32.fnt");
//mCodeFont = Font.LoadFromFile(BFApp.sApp.mInstallDir + "fonts/SegoeUI24.fnt");
mMainFrame = new MainFrame ( ) ;
mDockingFrame = mMainFrame . mDockingFrame ;
mSquiggleImage = Image . LoadFromFile ( scope String ( mInstallDir , "images/Squiggle.png" ) ) ;
mCircleImage = Image . LoadFromFile ( scope String ( mInstallDir , "images/Circle.png" ) ) ;
RehupScale ( ) ;
CreateBfSystems ( ) ;
if ( mWantsClean )
{
mBfBuildCompiler . ClearBuildCache ( ) ;
mWantsClean = false ;
}
mProjectPanel = new ProjectPanel ( ) ;
mProjectPanel . mAutoDelete = false ;
mClassViewPanel = new ClassViewPanel ( ) ;
mClassViewPanel . mAutoDelete = false ;
mOutputPanel = new OutputPanel ( true ) ;
mOutputPanel . mAutoDelete = false ;
mImmediatePanel = new ImmediatePanel ( ) ;
mImmediatePanel . mAutoDelete = false ;
mFindResultsPanel = new FindResultsPanel ( ) ;
mFindResultsPanel . mAutoDelete = false ;
mAutoWatchPanel = new WatchPanel ( true ) ;
mAutoWatchPanel . mAutoDelete = false ;
mWatchPanel = new WatchPanel ( false ) ;
mWatchPanel . mAutoDelete = false ;
mMemoryPanel = new MemoryPanel ( ) ;
mMemoryPanel . mAutoDelete = false ;
mCallStackPanel = new CallStackPanel ( ) ;
mCallStackPanel . mAutoDelete = false ;
mBreakpointPanel = new BreakpointPanel ( ) ;
mBreakpointPanel . mAutoDelete = false ;
2020-01-06 13:49:35 -08:00
mErrorsPanel = new ErrorsPanel ( ) ;
mErrorsPanel . mAutoDelete = false ;
2019-08-23 11:56:54 -07:00
mModulePanel = new ModulePanel ( ) ;
mModulePanel . mAutoDelete = false ;
mThreadPanel = new ThreadPanel ( ) ;
mThreadPanel . mAutoDelete = false ;
mProfilePanel = new ProfilePanel ( ) ;
mProfilePanel . mAutoDelete = false ;
mPropertiesPanel = new PropertiesPanel ( ) ;
mPropertiesPanel . mAutoDelete = false ;
mAutoCompletePanel = new AutoCompletePanel ( ) ;
mAutoCompletePanel . mAutoDelete = false ;
2020-01-24 11:51:31 -08:00
GetVersionInfo ( var exeDate ) ;
let localExeDate = exeDate . ToLocalTime ( ) ;
String exeDateStr = scope . ( ) ;
localExeDate . ToShortDateString ( exeDateStr ) ;
exeDateStr . Append ( " at " ) ;
localExeDate . ToShortTimeString ( exeDateStr ) ;
OutputLine ( "IDE Started. Version {} built {}." , mVersionInfo . FileVersion , exeDateStr ) ;
2019-08-23 11:56:54 -07:00
/ * if ( ! mRunningTestScript )
{
LoadUserSettings ( ) ; // User setting can affect automated testing, so use default settings
mSettings . Load ( ) ;
mSettings . Apply ( ) ;
} * /
if ( mWorkspace . mDir ! = null )
{
mWorkspace . mName = new String ( ) ;
Path . GetFileName ( mWorkspace . mDir , mWorkspace . mName ) ;
2019-09-05 08:18:24 -07:00
LoadWorkspace ( mVerb ) ;
2019-08-23 11:56:54 -07:00
}
else if ( mWorkspace . IsSingleFileWorkspace )
{
mWorkspace . mName = new String ( ) ;
Path . GetFileNameWithoutExtension ( mWorkspace . mCompositeFile . mFilePath , mWorkspace . mName ) ;
2019-09-05 08:18:24 -07:00
LoadWorkspace ( mVerb ) ;
2019-08-23 11:56:54 -07:00
}
2019-09-16 09:32:02 -07:00
bool loadedWorkspaceUserData = false ;
if ( ( ! mRunningTestScript ) & & ( LoadWorkspaceUserData ( ) ) )
{
loadedWorkspaceUserData = true ;
}
2019-08-23 11:56:54 -07:00
2019-10-15 14:39:47 -07:00
if ( mSetConfigName ! = null )
{
mConfigName . Set ( mSetConfigName ) ;
DeleteAndNullify ! ( mSetConfigName ) ;
}
if ( mSetPlatformName ! = null )
{
mPlatformName . Set ( mSetPlatformName ) ;
DeleteAndNullify ! ( mSetPlatformName ) ;
}
2019-08-23 11:56:54 -07:00
WorkspaceLoaded ( ) ;
2019-09-16 09:32:02 -07:00
if ( ( mIsFirstRun ) & & ( ! loadedWorkspaceUserData ) )
{
GetWorkspaceRect ( var workX , var workY , var workWidth , var workHeight ) ;
int32 height = ( int32 ) ( workHeight * 0.85f ) ;
int32 width = Math . Min ( 4 * height / 3 , ( int32 ) ( workWidth * 0.85f ) ) ;
mRequestedWindowRect = . ( workX + ( workWidth - width ) / 2 , workY + ( workHeight - height ) / 2 , width , height ) ;
}
2019-08-23 11:56:54 -07:00
//
{
2019-08-29 14:19:07 -07:00
BFWindow . Flags flags = . Border | . ThickFrame | . Resizable | . SysMenu |
. Caption | . Minimize | . Maximize | . QuitOnClose | . Menu ;
if ( mRunningTestScript )
flags | = . NoActivate ;
2019-09-27 13:03:47 -07:00
if ( mRequestedShowKind = = . Maximized )
flags | = . ShowMaximized ;
2019-08-23 11:56:54 -07:00
scope AutoBeefPerf ( "IDEApp.Init:CreateMainWindow" ) ;
mMainWindow = new WidgetWindow ( null , "Beef IDE" , ( int32 ) mRequestedWindowRect . mX ,
( int32 ) mRequestedWindowRect . mY , ( int32 ) mRequestedWindowRect . mWidth , ( int32 ) mRequestedWindowRect . mHeight ,
2019-08-29 14:19:07 -07:00
flags , mMainFrame ) ;
2019-08-23 11:56:54 -07:00
}
2019-09-16 09:32:02 -07:00
if ( mIsFirstRun )
{
// If this is our first time running, set up a scale based on DPI
int dpi = mMainWindow . GetDPI ( ) ;
if ( dpi > = 120 )
{
mSettings . mEditorSettings . mUIScale = 100 * Math . Min ( dpi / 96.0f , 4.0f ) ;
2019-10-05 10:24:58 -07:00
mSettings . Apply ( ) ;
2019-09-16 09:32:02 -07:00
}
}
2019-10-05 10:24:58 -07:00
if ( ! loadedWorkspaceUserData )
CreateDefaultLayout ( ) ;
2019-08-23 11:56:54 -07:00
UpdateTitle ( ) ;
mMainWindow . SetMinimumSize ( GS ! ( 480 ) , GS ! ( 360 ) ) ;
mMainWindow . mIsMainWindow = true ;
mMainWindow . mOnWindowKeyDown . Add ( new = > SysKeyDown ) ;
mMainWindow . mOnWindowCloseQuery . Add ( new = > AllowClose ) ;
CreateMenu ( ) ;
UpdateRecentDisplayedFilesMenuItems ( ) ;
if ( mRecentlyDisplayedFiles . Count > 0 )
ShowRecentFile ( 0 ) ;
2019-09-18 08:13:00 -07:00
2019-08-23 11:56:54 -07:00
mProjectPanel . RebuildUI ( ) ;
if ( mProcessAttachId ! = 0 )
{
Process debugProcess = scope Process ( ) ;
switch ( debugProcess . GetProcessById ( mProcessAttachId ) )
{
case . Ok :
case . Err :
Fail ( StackStringFormat ! ( "Unable to locate process id {0}" , mProcessAttachId ) ) ;
}
if ( debugProcess . IsAttached )
{
DebugManager . AttachFlags attachFlags = . None ;
String titleName = scope String ( ) ;
UpdateTitle ( titleName ) ;
OutputLine ( "Attaching to process id {0}: {1}" , mProcessAttachId , titleName ) ;
#if BF_PLATFORM_WINDOWS
if ( ! mProcessAttachHandle . IsInvalid )
attachFlags | = . ShutdownOnExit ;
#endif
Attach ( debugProcess , attachFlags ) ;
#if BF_PLATFORM_WINDOWS
if ( ! mProcessAttachHandle . IsInvalid )
{
Windows . SetEvent ( mProcessAttachHandle ) ;
mTargetDidInitBreak = true ;
mTargetHadFirstBreak = true ;
}
#endif
}
}
else if ( mCrashDumpPath ! = null )
{
if ( mDebugger . OpenMiniDump ( mCrashDumpPath ) )
{
mDebugger . mIsRunning = true ;
mExecutionPaused = false ; // Make this false so we can detect a Pause immediately
mIsAttachPendingSourceShow = true ;
}
else
{
Fail ( StackStringFormat ! ( "Failed to load minidump '{0}'" , mCrashDumpPath ) ) ;
}
}
else if ( mLaunchData ! = null )
{
2019-11-28 09:12:49 -08:00
if ( mLaunchData . mTargetPath = = null )
{
if ( mLaunchData . mPaused )
RunWithStep ( ) ;
else
CompileAndRun ( ) ;
}
else
LaunchDialog . DoLaunch ( null , mLaunchData . mTargetPath , mLaunchData . mArgs ? ? "" , mLaunchData . mWorkingDir ? ? "" , "" , mLaunchData . mPaused , true ) ;
2019-08-23 11:56:54 -07:00
}
mInitialized = true ;
//Profiler.StopSampling();
//if (IsMinidump)
//ShowOutput();
bool needSave = false ;
/ * if ( mWorkspace . mIsLegacyWorkspace )
{
mWorkspace . mIsLegacyWorkspace = false ;
mWorkspace . mHasChanged = true ;
needSave = true ;
} * /
/ * for ( var project in mWorkspace . mProjects )
{
if ( project . mIsLegacyProject )
{
int slashPos = project . mProjectPath . LastIndexOf ( '\\' ) ;
if ( slashPos ! = - 1 )
{
project . mProjectPath . RemoveToEnd ( slashPos + 1 ) ;
project . mProjectPath . Append ( "BeefProj.toml" ) ;
project . mHasChanged = true ;
project . mIsLegacyProject = false ;
needSave = true ;
}
//"BeefProj.toml"
}
} * /
if ( needSave )
SaveAll ( ) ;
ShowPanel ( mOutputPanel , false ) ;
UpdateRecentFileMenuItems ( ) ;
2019-09-07 06:40:03 -07:00
ShowStartupFile ( ) ;
2019-09-23 09:41:21 -07:00
2019-09-30 12:23:27 -07:00
if ( ( mIsFirstRun ) & & ( ! mWorkspace . IsInitialized ) )
2019-09-23 11:50:11 -07:00
ShowWelcome ( ) ;
2019-08-23 11:56:54 -07:00
}
#endif
2019-09-23 11:50:11 -07:00
void ShowWelcome ( )
{
WelcomePanel welcomePanel = new . ( ) ;
TabbedView tabbedView = GetDefaultDocumentTabbedView ( ) ;
let tabButton = SetupTab ( tabbedView , "Welcome" , 0 , welcomePanel , true ) ;
tabButton . Activate ( ) ;
}
2019-08-23 11:56:54 -07:00
void LoadConfig ( )
{
delete mBeefConfig ;
mBeefConfig = new BeefConfig ( ) ;
if ( mWorkspace . IsSingleFileWorkspace )
{
var dir = scope String ( ) ;
Path . GetDirectoryPath ( mWorkspace . mCompositeFile . FilePath , dir ) ;
mBeefConfig . QueuePaths ( dir ) ;
}
else
mBeefConfig . QueuePaths ( mWorkspace . mDir ) ;
mBeefConfig . QueuePaths ( mInstallDir ) ;
mBeefConfig . Load ( ) . IgnoreError ( ) ;
}
void RehupScale ( )
{
if ( mInitialized )
Font . ClearCache ( ) ;
if ( mCodeFont = = null )
return ;
float fontSize = DarkTheme . sScale * mSettings . mEditorSettings . mFontSize ;
float tinyFontSize = fontSize * 8.0f / 9.0f ;
2020-01-15 08:32:38 -08:00
bool failed = false ;
void FontFail ( StringView name )
{
String err = scope String ( ) . . AppendF ( "Failed to load font '{}'" , name ) ;
OutputErrorLine ( err ) ;
if ( ! failed )
Fail ( err ) ;
failed = true ;
}
2019-08-23 11:56:54 -07:00
bool isFirstFont = true ;
for ( let fontName in mSettings . mEditorSettings . mFonts )
{
if ( isFirstFont )
{
mTinyCodeFont . Dispose ( true ) ;
isFirstFont = ! mTinyCodeFont . Load ( fontName , tinyFontSize ) ;
mCodeFont . Dispose ( true ) ;
2020-01-15 08:32:38 -08:00
if ( ! mCodeFont . Load ( fontName , fontSize ) )
FontFail ( fontName ) ;
2019-08-23 11:56:54 -07:00
}
else
{
2019-09-25 07:51:06 -07:00
mTinyCodeFont . AddAlternate ( fontName , tinyFontSize ) . IgnoreError ( ) ;
2020-01-15 08:32:38 -08:00
if ( mCodeFont . AddAlternate ( fontName , fontSize ) case . Err )
FontFail ( fontName ) ;
2019-08-23 11:56:54 -07:00
}
}
if ( mCodeFont . GetHeight ( ) = = 0 )
{
mTinyCodeFont . Load ( "fonts/SourceCodePro-Regular.ttf" , tinyFontSize ) ;
mCodeFont . Load ( "fonts/SourceCodePro-Regular.ttf" , fontSize ) ;
}
// Do we have an extended font?
if ( mCodeFont . GetWidth ( '😊' ) = = 0 )
{
mCodeFont . AddAlternate ( "Segoe UI" , fontSize ) ;
mCodeFont . AddAlternate ( "Segoe UI Symbol" , fontSize ) ;
2019-09-26 10:06:10 -07:00
mCodeFont . AddAlternate ( "Segoe UI Historic" , fontSize ) . IgnoreError ( ) ;
2019-09-25 07:51:06 -07:00
mCodeFont . AddAlternate ( "Segoe UI Emoji" , fontSize ) . IgnoreError ( ) ;
2019-08-23 11:56:54 -07:00
mTinyCodeFont . AddAlternate ( "Segoe UI" , tinyFontSize ) ;
mTinyCodeFont . AddAlternate ( "Segoe UI Symbol" , tinyFontSize ) ;
2019-09-26 10:06:10 -07:00
mTinyCodeFont . AddAlternate ( "Segoe UI Historic" , tinyFontSize ) . IgnoreError ( ) ;
2019-09-25 07:51:06 -07:00
mTinyCodeFont . AddAlternate ( "Segoe UI Emoji" , tinyFontSize ) . IgnoreError ( ) ;
2019-08-23 11:56:54 -07:00
/ * mCodeFont . AddAlternate ( new String ( "fonts/segoeui.ttf" ) , fontSize ) ;
mCodeFont . AddAlternate ( new String ( "fonts/seguisym.ttf" ) , fontSize ) ;
mCodeFont . AddAlternate ( new String ( "fonts/seguihis.ttf" ) , fontSize ) ;
mTinyCodeFont . AddAlternate ( new String ( "fonts/segoeui.ttf" ) , tinyFontSize ) ;
mTinyCodeFont . AddAlternate ( new String ( "fonts/seguisym.ttf" ) , tinyFontSize ) ;
mTinyCodeFont . AddAlternate ( new String ( "fonts/seguihis.ttf" ) , tinyFontSize ) ; * /
}
//mTinyCodeFont.Load(scope String(BFApp.sApp.mInstallDir, "fonts/SourceCodePro-Regular.ttf"), fontSize);
float squiggleScale = DarkTheme . sScale ;
if ( squiggleScale < 3.0f )
squiggleScale = ( float ) Math . Round ( squiggleScale ) ;
mSquiggleImage . Scale ( squiggleScale ) ;
mCircleImage . Scale ( DarkTheme . sScale ) ;
}
void HandleWindowClosed ( BFWindow window )
{
if ( mWindowDatas . GetAndRemove ( window ) case . Ok ( ( ? , var windowData ) ) )
{
delete windowData ;
}
}
WindowData GetWindowData ( BFWindow window )
{
WindowData windowData ;
mWindowDatas . TryGetValue ( window , out windowData ) ;
if ( windowData = = null )
{
windowData = new WindowData ( ) ;
mWindowDatas [ window ] = windowData ;
}
return windowData ;
}
public DrawLayer GetOverlayLayer ( BFWindow window )
{
WindowData windowData = GetWindowData ( window ) ;
if ( windowData . mOverlayLayer = = null )
windowData . mOverlayLayer = new DrawLayer ( window ) ;
return windowData . mOverlayLayer ;
}
void UpdateDrawTracking ( )
{
}
public enum EvalResult
{
Normal ,
Pending
}
public EvalResult DebugEvaluate ( String expectedType , String expr , String outVal , int cursorPos = - 1 , DebugManager . Language language = . NotSet , DebugManager . EvalExpressionFlags expressionFlags = . None , Action < String > pendingHandler = null )
{
defer
{
if ( mPendingDebugExprHandler ! = pendingHandler )
delete pendingHandler ;
}
mIsImmediateDebugExprEval = false ;
String evalStr = scope String ( ) ;
evalStr . Append ( expr ) ;
if ( expectedType ! = null )
{
evalStr . Append ( ", expectedType=" ) ;
evalStr . Append ( expectedType ) ;
}
if ( mDebugger . IsPaused ( ) )
{
String curMethodOwner = scope String ( ) ;
int32 stackLanguage = 0 ;
mDebugger . GetStackMethodOwner ( mDebugger . mActiveCallStackIdx , curMethodOwner , out stackLanguage ) ;
if ( ( curMethodOwner . Length > 0 ) & & ( stackLanguage = = 2 ) & & ( mWorkspace . mStartupProject ! = null ) ) // Beef only
{
String namespaceSearch = scope String ( ) ;
if ( mBfResolveSystem ! = null )
{
mBfResolveSystem . Lock ( 2 ) ;
BfProject startupProject = mBfResolveSystem . GetBfProject ( mWorkspace . mStartupProject ) ;
mBfResolveSystem . GetNamespaceSearch ( curMethodOwner , namespaceSearch , startupProject ) ;
mBfResolveSystem . Unlock ( ) ;
}
if ( ! namespaceSearch . IsEmpty )
{
evalStr . Append ( ", namespaceSearch=\"" ) ;
int namespaceIdx = 0 ;
for ( var namespaceEntry in namespaceSearch . Split ( '\n' ) )
{
if ( namespaceIdx > 0 )
evalStr . Append ( "," ) ;
evalStr . Append ( namespaceEntry ) ;
namespaceIdx + + ;
}
evalStr . Append ( "\"" ) ;
}
}
}
mDebugger . Evaluate ( evalStr , outVal , cursorPos , ( int ) language , expressionFlags ) ;
if ( outVal = = "!pending" )
{
Debug . Assert ( mPendingDebugExprHandler = = null ) ;
mPendingDebugExprHandler = pendingHandler ;
return . Pending ;
}
return . Normal ;
}
void DebuggerPaused ( )
{
mDebugger . mActiveCallStackIdx = 0 ;
mExecutionPaused = true ;
mDebugger . GetRunState ( ) ;
WithWatchPanels ( scope ( watchPanel ) = >
{
watchPanel . SetDisabled ( false ) ;
} ) ;
mMemoryPanel . SetDisabled ( false ) ;
mCallStackPanel . SetDisabled ( false ) ;
}
void WithWatchPanels ( delegate void ( WatchPanel watchPanel ) dlg )
{
dlg ( mWatchPanel ) ;
dlg ( mAutoWatchPanel ) ;
for ( let window in mWindows )
{
if ( let widgetWindow = window as WidgetWindow )
{
if ( let quickWatch = widgetWindow . mRootWidget as QuickWatchDialog )
{
dlg ( quickWatch . [ Friend ] mWatchPanel ) ;
}
}
}
}
void DebuggerUnpaused ( )
{
// Leave target in background for a bit, incase we immediately
// hit another breakpoint
mDebugger . mActiveCallStackIdx = 0 ;
mForegroundTargetCountdown = 30 ;
mExecutionPaused = false ;
WithWatchPanels ( scope ( watchPanel ) = >
{
watchPanel . SetDisabled ( true ) ;
} ) ;
mMemoryPanel . SetDisabled ( true ) ;
mCallStackPanel . SetDisabled ( true ) ;
// If hoverwatch is up, we need to close it so we refresh the value
var sourceViewPanel = GetActiveSourceViewPanel ( ) ;
if ( ( sourceViewPanel ! = null ) & & ( sourceViewPanel . mHoverWatch ! = null ) )
{
sourceViewPanel . mHoverWatch . Close ( ) ;
}
mDebuggerContinueIdx + + ;
}
public void StepIntoSpecific ( int addr )
{
if ( mExecutionPaused )
{
DebuggerUnpaused ( ) ;
mDebugger . StepIntoSpecific ( addr ) ;
}
}
void FinishPendingHotResolve ( )
{
List < uint8 > typeData = scope . ( ) ;
String stackListStr = scope . ( ) ;
if ( ! mDebugger . GetHotResolveData ( typeData , stackListStr ) )
return ;
mBfBuildCompiler . HotResolve_Start ( ( mHotResolveState = = . Pending ) ? . None : . HadDataChanges ) ;
mHotResolveState = . None ;
for ( int typeId < typeData . Count )
{
if ( typeData [ typeId ] ! = 0 )
mBfBuildCompiler . HotResolve_ReportType ( typeId , . Heap ) ;
}
String stackStr = scope . ( ) ;
for ( let stackStrView in stackListStr . Split ( '\n' ) )
{
stackStr . Set ( stackStrView ) ;
if ( stackStr . StartsWith ( "D " ) )
{
stackStr . Remove ( 0 , 2 ) ;
mBfBuildCompiler . HotResolve_AddDelegateMethod ( stackStr ) ;
}
else
mBfBuildCompiler . HotResolve_AddActiveMethod ( stackStr ) ;
}
String hotResult = scope String ( ) ;
mBfBuildCompiler . HotResolve_Finish ( hotResult ) ;
if ( hotResult . IsEmpty )
{
//OutputLineSmart("Hot type data changes have been resolved");
ProcessBeefCompileResults ( null , false , mWorkspace . mStartupProject , null ) ;
}
else
{
if ( mHotResolveTryIdx = = 0 )
{
OutputLineSmart ( "ERROR: Hot type data changes cannot be applied because of the following types" ) ;
for ( var line in hotResult . Split ( '\n' ) )
{
OutputLineSmart ( " {0}" , line ) ;
}
OutputLineSmart ( "Revert changes or put the program into a state where the type is not actively being used" ) ;
var compileInstance = mWorkspace . mCompileInstanceList . Back ;
Debug . Assert ( compileInstance . mCompileResult = = . PendingHotLoad ) ;
compileInstance . mCompileResult = . Failure ;
}
}
if ( mHotResolveState = = . None )
{
var compileInstance = mWorkspace . mCompileInstanceList . Back ;
if ( compileInstance . mCompileResult = = . PendingHotLoad )
compileInstance . mCompileResult = . Success ;
}
}
void QueueProjectItems ( Project project )
{
project . WithProjectItems ( scope ( projectItem ) = >
{
var projectSource = projectItem as ProjectSource ;
if ( projectSource ! = null )
{
if ( projectSource . mIncludeKind = = . Ignore )
return ;
var resolveCompiler = GetProjectCompilerForFile ( projectSource . mPath ) ;
if ( resolveCompiler = = mBfResolveCompiler )
resolveCompiler . QueueProjectSource ( projectSource ) ;
projectSource . mHasChangedSinceLastCompile = true ;
}
} ) ;
}
void RemoveProjectItems ( Project project )
{
project . WithProjectItems ( scope ( projectItem ) = >
{
var projectSource = projectItem as ProjectSource ;
if ( projectSource ! = null )
{
var resolveCompiler = GetProjectCompilerForFile ( projectSource . mPath ) ;
if ( resolveCompiler = = mBfResolveCompiler )
resolveCompiler . QueueProjectSourceRemoved ( projectSource ) ;
if ( IsBeefFile ( projectSource . mPath ) )
{
mBfBuildCompiler . QueueProjectSourceRemoved ( projectSource ) ;
}
}
} ) ;
}
void UpdateCompilersAndDebugger ( )
{
scope AutoBeefPerf ( "UpdateCompilersAndDebugger" ) ;
var msg = scope String ( ) ;
while ( true )
{
DebugManager . RunState runState = . NotStarted ;
if ( mDebugger ! = null )
{
mDebugger . Update ( ) ;
runState = mDebugger . GetRunState ( ) ;
mDebuggerPerformingTask = ( runState = = . DebugEval ) | | ( runState = = . DebugEval_Done ) | | ( runState = = . SearchingSymSrv ) ;
if ( mDebugAutoRun )
{
if ( runState = = DebugManager . RunState . NotStarted )
{
mOutputPanel . Clear ( ) ;
if ( ( mExecutionQueue . Count = = 0 ) & & ( ! mDebugger . mIsRunning ) )
{
mTargetStartWithStep = true ;
var startDbgCmd = new StartDebugCmd ( ) ;
startDbgCmd . mWasCompiled = true ;
startDbgCmd . mOnlyIfNotFailed = true ;
mExecutionQueue . Add ( startDbgCmd ) ;
}
}
else if ( runState = = DebugManager . RunState . Paused )
{
mDebugger . Continue ( ) ;
//mDebugger.Terminate();
}
}
if ( ( mPendingDebugExprHandler ! = null ) & & ( runState ! = . DebugEval ) & & ( runState ! = . SearchingSymSrv ) )
{
var evalResult = scope String ( ) ;
mDebugger . EvaluateContinue ( evalResult ) ;
if ( evalResult ! = "!pending" )
{
mPendingDebugExprHandler ( evalResult ) ;
DeleteAndNullify ! ( mPendingDebugExprHandler ) ;
}
}
if ( mHotResolveState ! = . None )
{
FinishPendingHotResolve ( ) ;
}
}
if ( mDebugAutoBuild )
{
if ( ( ! mBfBuildCompiler . HasQueuedCommands ( ) ) & & ( mExecutionInstances . Count = = 0 ) & & ( mExecutionQueue . Count = = 0 ) )
{
OutputLine ( "Autobuilding..." ) ;
CompileBeef ( null , 0 , mLastCompileSucceeded , let hadBeef ) ;
}
}
bool didClean = false ;
if ( mWantsBeefClean )
{
if ( ( ! mBfBuildCompiler . HasQueuedCommands ( ) ) & &
( ( mBfResolveCompiler = = null ) | | ( ! mBfResolveCompiler . HasQueuedCommands ( ) ) ) )
{
didClean = true ;
OutputLine ( "Cleaned Beef." ) ;
2020-01-06 13:49:35 -08:00
if ( mErrorsPanel ! = null )
mErrorsPanel . ClearParserErrors ( null ) ;
2019-08-23 11:56:54 -07:00
delete mBfResolveCompiler ;
delete mBfResolveSystem ;
delete mBfResolveHelper ;
delete mBfBuildCompiler ;
delete mBfBuildSystem ;
///
mDebugger . FullReportMemory ( ) ;
var workspaceBuildDir = scope String ( ) ;
GetWorkspaceBuildDir ( workspaceBuildDir ) ;
if ( Directory . Exists ( workspaceBuildDir ) )
{
var result = Utils . DelTree ( workspaceBuildDir , scope ( fileName ) = >
{
return fileName . EndsWith ( "build.dat" ) ;
} ) ;
if ( result case . Err )
{
var str = scope String ( "Failed to delete folder: " , workspaceBuildDir ) ;
Fail ( str ) ;
}
}
//ResolveConfigString(project, options, "$(TargetPath)", error, targetPath);
if ( ! mNoResolve )
{
mBfResolveSystem = new BfSystem ( ) ;
mBfResolveCompiler = mBfResolveSystem . CreateCompiler ( true ) ;
mBfResolveHelper = new BfResolveHelper ( ) ;
}
mCompileSinceCleanCount = 0 ;
mBfBuildSystem = new BfSystem ( ) ;
mBfBuildCompiler = mBfBuildSystem . CreateCompiler ( false ) ;
mBfBuildCompiler . ClearBuildCache ( ) ;
/ * foreach ( var project in mWorkspace . mProjects )
{
mBfBuildSystem . AddProject ( project ) ;
if ( mBfResolveSystem ! = null )
mBfResolveSystem . AddProject ( project ) ;
}
foreach ( var project in mWorkspace . mProjects )
{
project . WithProjectItems ( scope ( projectItem ) = >
{
var projectSource = projectItem as ProjectSource ;
if ( projectSource ! = null )
{
var resolveCompiler = GetProjectCompilerForFile ( projectSource . mPath ) ;
if ( resolveCompiler = = mBfResolveCompiler )
resolveCompiler . QueueProjectSource ( projectSource ) ;
}
} ) ;
}
mBfResolveCompiler . QueueDeferredResolveAll ( ) ;
CurrentWorkspaceConfigChanged ( ) ; * /
mWantsBeefClean = false ;
}
}
if ( mWantsClean )
{
if ( ( ! mBfBuildCompiler . HasQueuedCommands ( ) ) & & ( ! mBfResolveCompiler . HasQueuedCommands ( ) )
#if IDE_C_SUPPORT
& & ( ! mDepClang . HasQueuedCommands ( ) ) & & ( ! mResolveClang . HasQueuedCommands ( ) )
#endif
)
{
OutputLine ( "Cleaned." ) ;
2020-01-06 13:49:35 -08:00
if ( mErrorsPanel ! = null )
mErrorsPanel . ClearParserErrors ( null ) ;
2019-08-23 11:56:54 -07:00
let workspaceOptions = GetCurWorkspaceOptions ( ) ;
delete mBfResolveHelper ;
delete mBfResolveCompiler ;
delete mBfResolveSystem ;
#if IDE_C_SUPPORT
delete mResolveClang ;
#endif
delete mBfBuildCompiler ;
delete mBfBuildSystem ;
#if IDE_C_SUPPORT
delete mDepClang ;
#endif
//
CreateBfSystems ( ) ;
mBfBuildCompiler . ClearBuildCache ( ) ;
var workspaceBuildDir = scope String ( ) ;
GetWorkspaceBuildDir ( workspaceBuildDir ) ;
if ( Directory . Exists ( workspaceBuildDir ) )
{
var result = Utils . DelTree ( workspaceBuildDir ) ;
if ( result case . Err )
{
var str = scope String ( "Failed to delete folder: " , workspaceBuildDir ) ;
//result.Exception.ToString(str);
Fail ( str ) ;
//result.Dispose();
}
}
List < String > deleteFails = scope . ( ) ;
for ( var project in mWorkspace . mProjects )
{
2019-08-27 08:04:41 -07:00
// Force running the "if files changed" commands
project . mForceCustomCommands = true ;
project . mNeedsTargetRebuild = true ;
2019-08-23 11:56:54 -07:00
// Don't delete custom build artifacts
if ( project . mGeneralOptions . mTargetType = = . CustomBuild )
continue ;
List < String > projectFiles = scope . ( ) ;
defer ClearAndDeleteItems ( projectFiles ) ;
let options = GetCurProjectOptions ( project ) ;
2019-08-27 08:04:41 -07:00
if ( options = = null )
continue ;
2019-10-14 17:49:10 -07:00
GetTargetPaths ( project , mPlatformName , workspaceOptions , options , projectFiles ) ;
2019-08-23 11:56:54 -07:00
for ( let filePath in projectFiles )
{
if ( File . Delete ( filePath ) case . Err ( let errVal ) )
{
if ( File . Exists ( filePath ) )
deleteFails . Add ( new String ( filePath ) ) ;
}
}
}
if ( ! deleteFails . IsEmpty )
{
String str = scope String ( ) ;
if ( deleteFails . Count = = 1 )
str . AppendF ( "Failed to delete file: {0}" , deleteFails [ 0 ] ) ;
else
{
str . Append ( "Failed to delete files:" ) ;
for ( let fileName in deleteFails )
{
str . Append ( "\n " , fileName ) ;
}
}
Fail ( str ) ;
}
ClearAndDeleteItems ( deleteFails ) ;
didClean = true ;
mWantsClean = false ;
mDbgCompileIdx = - 1 ;
mDbgHighestTime = default ;
}
}
if ( didClean )
{
for ( var project in mWorkspace . mProjects )
{
mBfBuildSystem . AddProject ( project ) ;
if ( mBfResolveSystem ! = null )
mBfResolveSystem . AddProject ( project ) ;
}
if ( mBfResolveSystem ! = null )
{
PreConfigureBeefSystem ( mBfResolveSystem , mBfResolveCompiler ) ;
for ( var project in mWorkspace . mProjects )
{
SetupBeefProjectSettings ( mBfResolveSystem , mBfResolveCompiler , project ) ;
}
}
2020-01-06 13:49:35 -08:00
CurrentWorkspaceConfigChanged ( ) ;
2019-08-23 11:56:54 -07:00
if ( mBfResolveSystem ! = null )
{
2020-01-06 13:49:35 -08:00
/ * for ( var project in mWorkspace . mProjects )
2019-08-23 11:56:54 -07:00
{
if ( IsProjectEnabled ( project ) )
QueueProjectItems ( project ) ;
2020-01-06 13:49:35 -08:00
} * /
2019-08-23 11:56:54 -07:00
mBfResolveCompiler . QueueDeferredResolveAll ( ) ;
}
}
mBfBuildSystem . Update ( ) ;
mBfBuildCompiler . Update ( ) ;
while ( true )
{
#if CLI
if ( mCompilingBeef )
break ;
#endif
msg . Clear ( ) ;
if ( ! mBfBuildCompiler . PopMessage ( msg ) )
break ;
2020-01-15 08:32:38 -08:00
OutputLineSmart ( msg ) ;
2019-08-23 11:56:54 -07:00
}
if ( mBfResolveSystem ! = null )
{
mBfResolveSystem . Update ( ) ;
mBfResolveCompiler . Update ( ) ;
mBfResolveCompiler . ClearMessages ( ) ;
mBfResolveHelper . Update ( ) ;
}
#if IDE_C_SUPPORT
mDepClang . Update ( ) ;
if ( ( ! IsCompiling ) & & ( ! mDepClang . IsPerformingBackgroundOperation ( ) ) )
{
// Only leave mCompileWaitsForQueueEmpty false for a fast initial build
mDepClang . mCompileWaitsForQueueEmpty = true ;
}
while ( true )
{
msg . Clear ( ) ;
if ( ! mDepClang . PopMessage ( msg ) )
break ;
OutputLine ( msg ) ;
}
mResolveClang . Update ( ) ;
mResolveClang . ClearMessages ( ) ;
#endif
bool wantDebuggerDetach = false ;
if ( ( mDebugger ! = null ) & & ( runState = = DebugManager . RunState . Terminated ) )
{
wantDebuggerDetach = true ;
}
String deferredMsgType = scope String ( ) ;
String deferredOutput = scope String ( ) ;
bool hadMessages = false ;
while ( mDebugger ! = null )
{
msg . Clear ( ) ;
if ( ! mDebugger . PopMessage ( msg ) )
{
break ;
}
hadMessages = true ;
int paramIdx = msg . IndexOf ( ' ' ) ;
String cmd = scope String ( ) ;
String param = scope String ( ) ;
if ( paramIdx > 0 )
{
cmd . Append ( msg , 0 , paramIdx ) ;
param . Append ( msg , paramIdx + 1 ) ;
}
else
cmd . Append ( msg ) ;
2019-09-04 07:00:38 -07:00
bool isOutput = ( cmd = = "msg" ) | | ( cmd = = "dbgEvalMsg" ) | | ( cmd = = "log" ) ;
if ( cmd = = "msgLo" )
{
2019-09-04 10:27:37 -07:00
if ( mVerbosity < . Diagnostic )
2019-09-04 07:00:38 -07:00
continue ;
isOutput = true ;
}
if ( isOutput )
2019-08-23 11:56:54 -07:00
{
if ( deferredMsgType ! = cmd )
{
if ( deferredOutput . Length > 0 )
{
OutputFormatted ( deferredOutput , deferredMsgType = = "dbgEvalMsg" ) ;
deferredOutput . Clear ( ) ;
}
deferredMsgType . Set ( cmd ) ;
}
deferredOutput . Append ( param ) ;
}
else if ( cmd = = "error" )
{
2019-09-03 11:17:13 -07:00
if ( ( mRunningTestScript ) & & ( ! IsCrashDump ) & & ( ! mScriptManager . IsErrorExpected ( param ) ) )
2019-08-23 11:56:54 -07:00
mScriptManager . Fail ( param ) ;
bool isFirstMsg = true ;
String tempStr = scope String ( ) ;
bool focusOutput = false ;
while ( true )
{
String errorMsg = null ;
int infoPos = param . IndexOf ( "\x01" ) ;
if ( infoPos = = 0 )
{
Widget addWidget = null ;
LeakWidget leakWidget = null ;
int endPos = param . IndexOf ( "\n" ) ;
if ( endPos = = - 1 )
break ;
String leakStr = scope String ( param , 1 , endPos - 1 ) ;
param . Remove ( 0 , endPos + 1 ) ;
int itemIdx = 0 ;
for ( var itemView in leakStr . Split ( '\t' ) )
{
var item = scope String ( itemView ) ;
if ( itemIdx = = 0 )
{
if ( item = = "LEAK" )
{
focusOutput = true ;
leakWidget = new LeakWidget ( mOutputPanel ) ;
leakWidget . Resize ( 0 , GS ! ( - 2 ) , DarkTheme . sUnitSize , DarkTheme . sUnitSize ) ;
addWidget = leakWidget ;
}
else if ( item = = "TEXT" )
{
OutputLine ( scope String ( leakStr , @itemView . MatchPos + 1 ) ) ;
break ;
}
else
break ;
}
else if ( itemIdx = = 1 )
{
leakWidget . mExpr = new String ( item ) ;
}
else
{
//leakWidget.mStackAddrs.Add()
}
itemIdx + + ;
}
if ( addWidget ! = null )
mOutputPanel . AddInlineWidget ( addWidget ) ;
}
else if ( infoPos ! = - 1 )
{
tempStr . Clear ( ) ;
tempStr . Append ( param , 0 , infoPos ) ;
errorMsg = tempStr ;
param . Remove ( 0 , infoPos ) ;
}
else
errorMsg = param ;
if ( errorMsg ! = null )
{
if ( isFirstMsg )
{
OutputLineSmart ( scope String ( "ERROR: " , errorMsg ) ) ;
2019-09-04 05:57:56 -07:00
if ( gApp . mRunningTestScript )
{
// The 'OutputLineSmart' would already call 'Fail' when running test scripts
}
else
{
Fail ( errorMsg ) ;
}
2019-08-23 11:56:54 -07:00
isFirstMsg = false ;
}
else
Output ( errorMsg ) ;
}
if ( infoPos = = - 1 )
break ;
}
if ( focusOutput )
ShowOutput ( ) ;
}
else if ( cmd = = "memoryBreak" )
{
Breakpoint breakpoint = null ;
int memoryAddress = ( int ) int64 . Parse ( param , System . Globalization . NumberStyles . HexNumber ) ;
for ( var checkBreakpoint in mDebugger . mBreakpointList )
{
if ( checkBreakpoint . mMemoryAddress = = memoryAddress )
breakpoint = checkBreakpoint ;
}
String infoString = StackStringFormat ! ( "Memory breakpoint hit: '0x{0:X08}'" , ( int64 ) memoryAddress ) ;
if ( breakpoint ! = null )
infoString = StackStringFormat ! ( "Memory breakpoint hit: '0x{0:X08}' ({1})" , ( int64 ) memoryAddress , breakpoint . mMemoryWatchExpression ) ;
OutputLine ( infoString ) ;
if ( ! mRunningTestScript )
{
MessageDialog ( "Breakpoint Hit" , infoString ) ;
Beep ( MessageBeepType . Information ) ;
}
}
else if ( cmd = = "newProfiler" )
{
var profiler = mDebugger . PopProfiler ( ) ;
//ShowProfilePanel();
mProfilePanel . Add ( profiler ) ;
}
else if ( cmd = = "showProfiler" )
{
ShowProfilePanel ( ) ;
}
else if ( cmd = = "clearOutput" )
{
mOutputPanel . Clear ( ) ;
}
else if ( cmd = = "dbgInfoLoaded" )
{
//Debug.WriteLine("dbgInfoLoaded {0}", param);
mWantsRehupCallstack = true ;
}
else if ( cmd = = "rehupLoc" )
{
mWantsRehupCallstack = true ;
}
else if ( cmd = = "modulesChanged" )
{
mModulePanel . ModulesChanged ( ) ;
}
else if ( cmd = = "symsrv" )
{
mSymSrvStatus . Set ( param ) ;
}
else
{
Runtime . FatalError ( "Invalid debugger message type" ) ;
}
}
if ( deferredOutput . Length > 0 )
{
OutputFormatted ( deferredOutput , deferredMsgType = = "dbgEvalMsg" ) ;
}
/ * if ( hadMessages )
mNoDebugMessagesTick = 0 ;
else if ( IDEApp . sApp . mIsUpdateBatchStart )
mNoDebugMessagesTick + + ;
if ( mNoDebugMessagesTick < 10 )
wantDebuggerDetach = false ; // Don't detach if we have messages*/
if ( wantDebuggerDetach )
{
OutputLine ( "Detached debugger" ) ;
UpdateTitle ( ) ;
var disassemblyPanel = TryGetDisassemblyPanel ( false ) ;
if ( disassemblyPanel ! = null )
disassemblyPanel . Disable ( ) ;
mDebugger . DisposeNativeBreakpoints ( ) ;
mDebugger . Detach ( ) ;
mDebugger . mIsRunning = false ;
mExecutionPaused = false ;
mHotResolveState = . None ;
mDebuggerPerformingTask = false ;
mWorkspace . StoppedRunning ( ) ;
mBreakpointPanel . BreakpointsChanged ( ) ;
mModulePanel . ModulesChanged ( ) ;
if ( mPendingDebugExprHandler ! = null )
{
mPendingDebugExprHandler ( null ) ;
DeleteAndNullify ! ( mPendingDebugExprHandler ) ;
}
mMemoryPanel . SetDisabled ( true ) ;
WithWatchPanels ( scope ( watchPanel ) = >
{
watchPanel . SetDisabled ( true ) ;
} ) ;
mIsAttachPendingSourceShow = false ;
}
if ( ( mDebugger ! = null ) & & ( mDebugger . IsPaused ( ) ) & & ( ! mDebugger . HasPendingDebugLoads ( ) ) )
{
mForegroundTargetCountdown = 0 ;
if ( ! mExecutionPaused )
{
if ( ! mTargetDidInitBreak )
{
mTargetDidInitBreak = true ;
bool wantsContinue = true ;
if ( mTargetStartWithStep )
{
if ( ( mMainBreakpoint ! = null ) & & ( ! mMainBreakpoint . IsBound ( ) ) )
{
BfLog . LogDbg ( "Deleting mMainBreakpoint 1\n" ) ;
// Couldn't bind to main breakpoint, bind to entry point address
2019-08-27 08:04:41 -07:00
// "." is the magic symbol for "entry point"
String [ ] tryNames = scope . ( "WinMain" , "." ) ;
for ( let name in tryNames )
{
mDebugger . DeleteBreakpoint ( mMainBreakpoint ) ;
mMainBreakpoint = mDebugger . CreateSymbolBreakpoint ( "WinMain" ) ;
if ( ( name = = "." ) | | ( mMainBreakpoint . IsBound ( ) ) )
break ;
}
2019-08-23 11:56:54 -07:00
}
wantsContinue = true ;
}
else
{
if ( mMainBreakpoint ! = null )
{
if ( mMainBreakpoint . IsActiveBreakpoint ( ) )
wantsContinue = true ;
BfLog . LogDbg ( "Deleting mMainBreakpoint 2\n" ) ;
mDebugger . DeleteBreakpoint ( mMainBreakpoint ) ;
//mMainBreakpoint.Dispose();
mMainBreakpoint = null ;
}
}
if ( wantsContinue )
{
DebuggerUnpaused ( ) ;
mDebugger . Continue ( ) ;
}
}
else
{
if ( mMainBreakpoint ! = null )
{
BfLog . LogDbg ( "Deleting mMainBreakpoint 3\n" ) ;
mDebugger . DeleteBreakpoint ( mMainBreakpoint ) ;
mMainBreakpoint = null ;
int addr ;
String fileName = null ;
mDebugger . UpdateCallStack ( ) ;
var stackInfo = scope String ( ) ;
mDebugger . GetStackFrameInfo ( 0 , out addr , fileName , stackInfo ) ;
2019-10-23 11:30:59 -07:00
if ( stackInfo . Contains ( "BeefStartProgram" ) )
2019-08-23 11:56:54 -07:00
{
// Okay, NOW we can do a "step into"
if ( ! IsInDisassemblyMode ( ) )
mDebugger . StepInto ( false ) ;
return ;
}
}
2019-08-29 14:19:07 -07:00
if ( ( ! HasModalDialogs ( ) ) & & ( ! mRunningTestScript ) )
2019-08-23 11:56:54 -07:00
mMainWindow . SetForeground ( ) ;
if ( mRunTimingProfileId ! = 0 )
{
mRunTimingProfileId . Dispose ( ) ;
mRunTimingProfileId = 0 ;
}
BeefPerf . Event ( "Debugger Paused" , "" ) ;
DebuggerPaused ( ) ;
PCChanged ( ) ;
mBreakpointPanel . MarkStatsDirty ( ) ;
mTargetHadFirstBreak = true ;
if ( mDebugger . GetRunState ( ) = = DebugManager . RunState . Exception )
{
String exceptionLine = scope String ( ) ;
mDebugger . GetCurrentException ( exceptionLine ) ;
var exceptionData = String . StackSplit ! ( exceptionLine , '\n' ) ;
String exHeader = StackStringFormat ! ( "Exception {0}" , exceptionData [ 1 ] ) ;
if ( exceptionData . Count > = 3 )
exHeader = exceptionData [ 2 ] ;
String exString = StackStringFormat ! ( "{0} at {1}" , exHeader , exceptionData [ 0 ] ) ;
OutputLine ( exString ) ;
if ( ! IsCrashDump )
Fail ( exString ) ;
}
}
}
break ;
}
else if ( mDebuggerPerformingTask )
{
break ;
}
else
{
if ( mForegroundTargetCountdown > 0 )
{
if ( ( - - mForegroundTargetCountdown = = 0 ) & & ( mDebugger . mIsRunning ) )
mDebugger . ForegroundTarget ( ) ;
}
if ( ( mDebugger ! = null ) & & ( mExecutionPaused ) & & ( mDebugger . mIsRunning ) )
DebuggerUnpaused ( ) ;
break ;
}
}
if ( ( mDebugger ! = null ) & & ( ( mDebugger . IsPaused ( ) ) | | ( ! mDebugger . mIsRunning ) ) & & ( ! IsCompiling ) )
{
if ( mDebugger . mRunToCursorBreakpoint ! = null )
{
BfLog . LogDbg ( "Stopped. Clearing mRunToCursorBreakpoint\n" ) ;
mDebugger . DeleteBreakpoint ( mDebugger . mRunToCursorBreakpoint ) ;
mDebugger . mRunToCursorBreakpoint = null ;
}
}
if ( ( mDebugger ! = null ) & & ( mExecutionPaused ) & & ( mDebugger . IsPaused ( ) ) )
{
if ( mWantsRehupCallstack )
{
mDebugger . RehupCallstack ( ) ;
if ( var deferredShowPCRequest = mDeferredUserRequest as DeferredShowPCLocation )
{
//Debug.WriteLine("Had DeferredShowPCLocation");
var stackIdx = deferredShowPCRequest . mStackIdx ;
IDEApp . sApp . mDebugger . mActiveCallStackIdx = stackIdx ;
ClearDeferredUserRequest ( ) ;
ShowPCLocation ( stackIdx , false , true ) ;
StackPositionChanged ( ) ;
}
mCallStackPanel . MarkCallStackDirty ( ) ;
mThreadPanel . MarkThreadsDirty ( ) ;
mModulePanel . ModulesChanged ( ) ;
mWantsRehupCallstack = false ;
}
}
2019-08-27 08:04:41 -07:00
if ( mBuildContext ! = null )
{
2019-09-28 09:48:37 -07:00
mBuildContext . mUpdateCnt + + ;
2019-08-27 08:04:41 -07:00
bool isCompiling = ( ! mExecutionInstances . IsEmpty ) | | ( ! mExecutionQueue . IsEmpty ) ;
if ( mBuildContext . mScriptManager ! = null )
{
mBuildContext . mScriptManager . Update ( ) ;
if ( ( mBuildContext . mScriptManager . HasQueuedCommands ) & & ( ! mBuildContext . mScriptManager . mFailed ) )
isCompiling = true ;
}
if ( ! isCompiling )
{
DeleteAndNullify ! ( mBuildContext ) ;
}
}
2019-11-28 09:12:49 -08:00
if ( ( mBuildContext = = null ) & & ( ! IsCompiling ) )
DeleteAndNullify ! ( mLaunchData ) ;
2020-01-06 13:49:35 -08:00
2020-01-20 17:12:07 -08:00
mErrorsPanel ? . UpdateAlways ( ) ;
2019-08-23 11:56:54 -07:00
}
public void ShowPassOutput ( BfPassInstance bfPassInstance )
{
while ( true )
{
var outString = scope String ( ) ;
if ( ! bfPassInstance . PopOutString ( outString ) )
break ;
OutputLine ( outString ) ;
}
}
/ * public bool CheckMouseover ( Widget checkWidget , int32 wantTicks , out Point mousePoint )
{
mousePoint = Point ( Int32 . MinValue , Int32 . MinValue ) ;
if ( checkWidget ! = mLastMouseWidget )
return false ;
checkWidget . RootToSelfTranslate ( mLastRelMousePos . x , mLastRelMousePos . y , out mousePoint . x , out mousePoint . y ) ;
return mMouseStillTicks = = wantTicks ;
}
void LastMouseWidgetDeleted ( Widget widget )
{
if ( mLastMouseWidget = = widget )
mLastMouseWidget = null ;
}
void SetLastMouseWidget ( Widget newWidget )
{
if ( mLastMouseWidget ! = null )
mLastMouseWidget . mDeletedHandler . Remove ( scope = > LastMouseWidgetDeleted , true ) ;
mLastMouseWidget = newWidget ;
if ( mLastMouseWidget ! = null )
mLastMouseWidget . mDeletedHandler . Add ( new = > LastMouseWidgetDeleted ) ;
}
void UpdateMouseover ( )
{
if ( mMouseStillTicks ! = - 1 )
mMouseStillTicks + + ;
Widget overWidget = null ;
int32 numOverWidgets = 0 ;
foreach ( var window in mWindows )
{
var widgetWindow = window as WidgetWindow ;
widgetWindow . RehupMouse ( false ) ;
var windowOverWidget = widgetWindow . mCaptureWidget ? ? widgetWindow . mOverWidget ;
if ( ( windowOverWidget ! = null ) & & ( widgetWindow . mAlpha = = 1.0f ) & & ( widgetWindow . mCaptureWidget = = null ) )
{
overWidget = windowOverWidget ;
numOverWidgets + + ;
if ( overWidget ! = mLastMouseWidget )
{
SetLastMouseWidget ( overWidget ) ;
mMouseStillTicks = - 1 ;
}
float actualX = widgetWindow . mClientX + widgetWindow . mMouseX ;
float actualY = widgetWindow . mClientY + widgetWindow . mMouseY ;
if ( ( mLastAbsMousePos . x ! = actualX ) | | ( mLastAbsMousePos . y ! = actualY ) )
{
mMouseStillTicks = 0 ;
mLastAbsMousePos . x = actualX ;
mLastAbsMousePos . y = actualY ;
}
mLastRelMousePos . x = widgetWindow . mMouseX ;
mLastRelMousePos . y = widgetWindow . mMouseY ;
}
}
if ( overWidget = = null )
{
SetLastMouseWidget ( null ) ;
mMouseStillTicks = - 1 ;
}
if ( numOverWidgets > 1 )
{
//int a = 0;
}
Debug . Assert ( numOverWidgets < = 1 ) ;
} * /
public void FileRenamed ( ProjectFileItem projectFileItem , String oldPath , String newPath )
{
String newFileName = scope String ( ) ;
Path . GetFileName ( newPath , newFileName ) ;
RenameEditData ( oldPath , newPath ) ;
WithTabs ( scope ( tab ) = >
{
var sourceViewPanel = tab . mContent as SourceViewPanel ;
if ( sourceViewPanel ! = null )
{
if ( Path . Equals ( sourceViewPanel . mFilePath , oldPath ) )
{
var sourceViewTab = ( IDEApp . SourceViewTab ) tab ;
//TODO: We might have to resize the label here?
//sourceViewPanel.mFilePath.Set(newPath);
sourceViewPanel . PathChanged ( newPath ) ;
tab . Label = newFileName ;
tab . mWantWidth = sourceViewTab . GetWantWidth ( ) ;
//tab.mTabbedView.Resize();
}
}
} ) ;
var recentFileList = mRecentlyDisplayedFiles ;
for ( int32 recentFileIdx = 0 ; recentFileIdx < recentFileList . Count ; recentFileIdx + + )
{
if ( recentFileList [ recentFileIdx ] = = oldPath )
recentFileList [ recentFileIdx ] . Set ( newPath ) ;
}
UpdateRecentDisplayedFilesMenuItems ( ) ;
if ( IsBeefFile ( newPath ) ! = IsBeefFile ( oldPath ) )
{
if ( ( var projectSource = projectFileItem as ProjectSource ) & & ( IsProjectSourceEnabled ( projectSource ) ) )
{
if ( IsBeefFile ( newPath ) )
{
mBfResolveCompiler . QueueProjectSource ( projectSource ) ;
mBfBuildCompiler . QueueProjectSource ( projectSource ) ;
}
else
{
mBfResolveCompiler . QueueProjectSourceRemoved ( projectSource ) ;
mBfBuildCompiler . QueueProjectSourceRemoved ( projectSource ) ;
}
mBfResolveCompiler . QueueDeferredResolveAll ( ) ;
mBfResolveCompiler . QueueRefreshViewCommand ( ) ;
}
}
}
public void OnWatchedFileChanged ( ProjectItem projectItem , WatcherChangeTypes changeType , String newPath )
{
2019-10-29 04:56:42 -07:00
CompilerLog ( "IDEApp.OnWatchedFileChanged {} {} {}" , projectItem . mName , changeType , newPath ) ;
2020-01-12 09:21:50 -08:00
ProjectListViewItem listViewItem = null ;
mProjectPanel ? . mProjectToListViewMap . TryGetValue ( projectItem , out listViewItem ) ;
2019-08-23 11:56:54 -07:00
String newName = null ;
if ( newPath ! = null )
{
newName = scope : : String ( ) ;
Path . GetFileName ( newPath , newName ) ;
}
if ( changeType = = . Renamed )
{
if ( projectItem . mIncludeKind = = . Auto )
{
let projectFileItem = projectItem as ProjectFileItem ;
2020-01-12 09:21:50 -08:00
if ( listViewItem ! = null )
listViewItem . Label = newName ;
2019-08-23 11:56:54 -07:00
String oldPath = scope String ( ) ;
projectFileItem . GetFullImportPath ( oldPath ) ;
projectFileItem . Rename ( newName ) ;
FileRenamed ( projectFileItem , oldPath , newPath ) ;
2020-01-12 09:21:50 -08:00
mProjectPanel ? . SortItem ( ( ProjectListViewItem ) listViewItem . mParentItem ) ;
2019-08-23 11:56:54 -07:00
}
}
else if ( changeType = = . Deleted )
{
if ( projectItem . mIncludeKind = = . Auto )
{
2020-01-12 09:21:50 -08:00
mProjectPanel ? . DoDeleteItem ( listViewItem , null , true ) ;
2019-08-23 11:56:54 -07:00
}
}
else if ( changeType = = . FileCreated )
{
let projectFolder = projectItem as ProjectFolder ;
if ( projectFolder . IsAutoInclude ( ) )
{
if ( ! projectFolder . mChildMap . ContainsKey ( newName ) )
{
let projectSource = new ProjectSource ( ) ;
Path . GetFileName ( newPath , projectSource . mName ) ;
projectSource . mPath = new String ( projectFolder . mPath ) ;
projectSource . mPath . Append ( Path . DirectorySeparatorChar ) ;
projectSource . mPath . Append ( projectSource . mName ) ;
projectSource . mProject = projectFolder . mProject ;
projectSource . mParentFolder = projectFolder ;
projectFolder . AddChild ( projectSource ) ;
projectFolder . MarkAsUnsorted ( ) ;
2020-01-12 09:21:50 -08:00
if ( mProjectPanel ! = null )
{
mProjectPanel . AddProjectItem ( projectSource ) ;
mProjectPanel . QueueSortItem ( listViewItem ) ;
}
2019-08-23 11:56:54 -07:00
}
}
}
else if ( changeType = = . DirectoryCreated )
{
let projectFolder = projectItem as ProjectFolder ;
if ( projectFolder . IsAutoInclude ( ) )
{
if ( ! projectFolder . mChildMap . ContainsKey ( newName ) )
{
let newFolder = new ProjectFolder ( ) ;
Path . GetFileName ( newPath , newFolder . mName ) ;
newFolder . mPath = new String ( projectFolder . mPath ) ;
newFolder . mPath . Append ( Path . DirectorySeparatorChar ) ;
newFolder . mPath . Append ( newFolder . mName ) ;
newFolder . mProject = projectFolder . mProject ;
newFolder . mParentFolder = projectFolder ;
projectFolder . AddChild ( newFolder ) ;
projectFolder . MarkAsUnsorted ( ) ;
2020-01-12 09:21:50 -08:00
if ( mProjectPanel ! = null )
{
mProjectPanel . AddProjectItem ( newFolder ) ;
mProjectPanel . QueueSortItem ( listViewItem ) ;
}
2019-08-23 11:56:54 -07:00
newFolder . mAutoInclude = true ;
2020-01-12 09:21:50 -08:00
if ( mProjectPanel ! = null )
mProjectPanel . QueueRehupFolder ( newFolder ) ;
2019-08-23 11:56:54 -07:00
}
}
}
else if ( changeType = = . Failed )
{
2020-01-12 09:21:50 -08:00
if ( mProjectPanel ! = null )
{
if ( let projectFolder = projectItem as ProjectFolder )
mProjectPanel . QueueRehupFolder ( projectFolder ) ;
}
2019-08-23 11:56:54 -07:00
}
}
void UpdateWorkspace ( )
{
mFileWatcher . Update ( ) ;
bool appHasFocus = false ;
for ( var window in mWindows )
appHasFocus | = window . mHasFocus ;
if ( mRunningTestScript )
appHasFocus = true ;
// Is this enough to get the behavior we want?
if ( ! appHasFocus )
return ;
if ( mLastFileChangeId ! = mFileWatcher . mChangeId )
{
if ( ( mFileChangedDialog ! = null ) & & ( ! mFileChangedDialog . mClosed ) )
{
mFileChangedDialog . Rehup ( ) ;
}
mLastFileChangeId = mFileWatcher . mChangeId ;
}
var app = gApp ;
Debug . Assert ( app ! = null ) ;
while ( true )
{
var dep = mFileWatcher . PopChangedDependency ( ) ;
if ( dep = = null )
break ;
var projectSourceDep = dep as ProjectSource ;
if ( projectSourceDep ! = null )
{
// We process these projectSources directly from the filename below
}
}
while ( /*(appHasFocus) && */ ( ( mFileChangedDialog = = null ) | | ( mFileChangedDialog . mClosed ) ) )
{
while ( mExternalChangeDeferredOpen . Count > 0 )
{
String filePath = mExternalChangeDeferredOpen . PopFront ( ) ;
ShowSourceFile ( filePath ) ;
delete filePath ;
}
var changedFile = mFileWatcher . PopChangedFile ( ) ;
if ( changedFile = = null )
{
if ( mFileChangedDialog ! = null )
mFileChangedDialog = null ;
break ;
}
String fileName = changedFile . mPath ;
defer
{
delete changedFile ;
}
#if IDE_C_SUPPORT
if ( ( IsClangSourceFile ( fileName ) ) | | ( IsClangSourceHeader ( fileName ) ) )
{
mDepClang . mDoDependencyCheck = true ;
}
#endif
FileChanged ( fileName ) ;
var editData = GetEditData ( fileName , false , false ) ;
if ( editData = = null )
continue ;
//TODO: Check to see if this file is in the dependency list of the executing project
2019-09-24 08:58:04 -07:00
if ( ! editData . mProjectSources . IsEmpty )
mHaveSourcesChangedExternallySinceLastCompile = true ;
2019-08-23 11:56:54 -07:00
editData . SetSavedData ( null , IdSpan ( ) ) ;
if ( editData . mQueuedContent = = null )
editData . mQueuedContent = new String ( ) ;
editData . mQueuedContent . Clear ( ) ;
2019-09-28 09:48:37 -07:00
if ( LoadTextFile ( fileName , editData . mQueuedContent , false , scope ( ) = >
{
2019-11-22 12:27:13 -08:00
editData . BuildHash ( editData . mQueuedContent ) ;
2019-09-28 09:48:37 -07:00
} ) case . Err ( let err ) )
2019-08-23 11:56:54 -07:00
{
if ( err case . FileOpenError ( . SharingViolation ) )
{
// Put back on the list and try later
mFileWatcher . AddChangedFile ( changedFile ) ;
changedFile = null ;
break ;
}
editData . mFileDeleted = true ;
}
using ( mMonitor . Enter ( ) )
{
for ( var projectSource in editData . mProjectSources )
{
projectSource . HasChangedSinceLastCompile = true ;
}
}
var sourceViewPanel = FindSourceViewPanel ( fileName ) ;
if ( sourceViewPanel ! = null )
{
FileChangedDialog . DialogKind dialogKind = File . Exists ( fileName ) ? . Changed : . Deleted ;
if ( ( sourceViewPanel . mEditData ! = null ) & & ( sourceViewPanel . mEditData . mFileDeleted ) )
sourceViewPanel . mEditData . IsFileDeleted ( ) ; // Rehup
if ( ( sourceViewPanel . HasUnsavedChanges ( ) ) | | ( dialogKind = = . Deleted ) )
{
if ( ( mFileChangedDialog ! = null ) & & ( mFileChangedDialog . mApplyAllResult [ ( int ) dialogKind ] . HasValue ) )
{
bool closeAll = mFileChangedDialog . mApplyAllResult [ ( int ) dialogKind ] . Value ;
if ( closeAll )
gApp . CloseDocument ( sourceViewPanel ) ;
continue ;
}
else
{
mFileChangedDialog = new FileChangedDialog ( ) ;
mFileChangedDialog . Show ( sourceViewPanel ) ;
}
break ;
}
else
{
sourceViewPanel . Reload ( ) ;
//FileChanged(fileName);
}
}
else
{
editData . Reload ( ) ;
FileChanged ( editData ) ;
}
}
if ( mWorkspace . IsSingleFileWorkspace )
{
if ( mWorkspace . mCompositeFile . HasPendingSave )
mWorkspace . mCompositeFile . Save ( ) ;
}
}
public void FileChanged ( String path )
{
OpenFileInSolutionDialog . ClearWriteTime ( path ) ;
}
public void FileChanged ( FileEditData editData )
{
if ( ! IsBeefFile ( editData . mFilePath ) )
return ;
using ( mMonitor . Enter ( ) )
{
for ( var projectSource in editData . mProjectSources )
{
if ( mBfResolveCompiler ! = null )
{
mBfResolveCompiler . QueueProjectSource ( projectSource ) ;
mBfResolveCompiler . QueueDeferredResolveAll ( ) ;
mBfResolveCompiler . QueueRefreshViewCommand ( ) ;
}
}
}
}
#if ! CLI
void UpdateIPC ( )
{
bool hasFocus = false ;
for ( var window in mWindows )
{
if ( window . mHasFocus )
hasFocus = true ;
}
bool gotFocus = hasFocus & & ! mIPCHadFocus ;
mIPCHadFocus = hasFocus ;
//hasFocus = true;
if ( gotFocus )
{
// Keep trying to create IPCHelper until we finally succeed
if ( mIPCHelper = = null )
{
mIPCHelper = new IPCHelper ( ) ;
if ( ! mIPCHelper . Init ( "BF_IDE" ) )
DeleteAndNullify ! ( mIPCHelper ) ;
else
{
#if ! DEBUG
OutputLine ( "IPC: Hosting" ) ; //
#endif
}
}
}
if ( mIPCHelper ! = null )
{
mIPCHelper . Update ( ) ;
var message = mIPCHelper . PopMessage ( ) ;
if ( message ! = null )
{
defer delete message ;
var msgParts = String . StackSplit ! ( message , '|' ) ;
if ( msgParts . Count > = 0 )
{
String cmd = scope String ( msgParts [ 0 ] ) ;
if ( cmd = = "ShowFile" )
{
// These loads any file changes before we try to do a goto
mMainWindow . SetForeground ( ) ;
UpdateWorkspace ( ) ;
String fileName = scope String ( msgParts [ 1 ] ) ;
int32 lineNum = int32 . Parse ( scope String ( msgParts [ 2 ] ) ) . GetValueOrDefault ( ) ;
var sourceViewPanel = ShowSourceFileLocation ( fileName , - 1 , IDEApp . sApp . mWorkspace . GetHighestCompileIdx ( ) , lineNum - 1 , 0 , LocatorType . Always , false ) ;
if ( sourceViewPanel ! = null )
sourceViewPanel . mWidgetWindow . SetForeground ( ) ;
}
else if ( cmd = = "StopIPC" )
{
#if ! DEBUG
OutputLine ( "IPC: Stopping" ) ;
#endif
delete mIPCHelper ;
mIPCHelper = null ;
}
}
}
}
}
#endif
void DoLongUpdateCheck ( )
{
uint32 timeNow = Utils . GetTickCount ( ) ;
if ( mLastLongUpdateCheck ! = 0 )
{
int ticksDiff = ( int32 ) ( timeNow - mLastLongUpdateCheck ) ;
if ( ticksDiff > 200 )
{
int lastErrTicks = ( int32 ) ( timeNow - mLastLongUpdateCheckError ) ;
if ( lastErrTicks > 2000 )
{
// Show this profile!
mLongUpdateProfileId . Dispose ( ) ;
mLongUpdateProfileId = Profiler . StartSampling ( "LongUpdate" ) ;
mLastLongUpdateCheckError = timeNow ;
}
}
}
Profiler . ClearSampling ( ) ;
mLastLongUpdateCheck = Utils . GetTickCount ( ) ;
}
public void SetDeferredUserRequest ( DeferredUserRequest deferredUserRequest )
{
//Debug.WriteLine("SetDeferredUserRequest");
delete mDeferredUserRequest ;
mDeferredUserRequest = deferredUserRequest ;
}
public void ClearDeferredUserRequest ( )
{
//Debug.WriteLine("ClearDeferredUserRequest");
DeleteAndNullify ! ( mDeferredUserRequest ) ;
}
2019-09-05 08:18:24 -07:00
void UpdateDeferredOpens ( )
{
void DoDeferredOpen ( DeferredOpenKind openKind )
{
switch ( openKind )
{
case . NewWorkspaceOrProject :
var dialog = ThemeFactory . mDefault . CreateDialog ( "Create Workspace?" ,
"Do you want to create an empty workspace or a new project?" ) ;
dialog . AddButton ( "Empty Workspace" , new ( evt ) = >
{
mDeferredOpen = . NewWorkspace ;
} ) ;
dialog . AddButton ( "New Project" , new ( evt ) = >
{
CloseWorkspace ( ) ;
FinishShowingNewWorkspace ( ) ;
Cmd_NewProject ( ) ;
} ) ;
dialog . PopupWindow ( GetActiveWindow ( ) ) ;
case . NewWorkspace :
if ( mDeferredOpenFileName ! = null )
{
let directoryPath = scope String ( ) ;
Path . GetDirectoryPath ( mDeferredOpenFileName , directoryPath ) ;
if ( File . Exists ( mDeferredOpenFileName ) )
{
var dialog = ThemeFactory . mDefault . CreateDialog ( "Already Exists" ,
scope String ( ) . . AppendF ( "A Beef workspace already exists at '{}'. Do you want to open it?" , directoryPath ) ,
DarkTheme . sDarkTheme . mIconWarning ) ;
dialog . mDefaultButton = dialog . AddButton ( "Yes" , new ( evt ) = >
{
2020-01-12 09:21:50 -08:00
DoOpenWorkspace ( true ) ;
2019-09-05 08:18:24 -07:00
} ) ;
dialog . AddButton ( "No" , new ( evt ) = >
{
DeleteAndNullify ! ( mDeferredOpenFileName ) ;
} ) ;
dialog . PopupWindow ( GetActiveWindow ( ) ) ;
return ;
}
else if ( ! IDEUtils . IsDirectoryEmpty ( directoryPath ) )
{
var dialog = ThemeFactory . mDefault . CreateDialog ( "Already Exists" ,
scope String ( ) . . AppendF ( "A non-empty directory already exists at '{}'. Are you sure you want to create a workspace there?" , directoryPath ) ,
DarkTheme . sDarkTheme . mIconWarning ) ;
dialog . mDefaultButton = dialog . AddButton ( "Yes" , new ( evt ) = >
{
2020-01-12 09:21:50 -08:00
DoOpenWorkspace ( true ) ;
2019-09-05 08:18:24 -07:00
} ) ;
dialog . AddButton ( "No" , new ( evt ) = >
{
DeleteAndNullify ! ( mDeferredOpenFileName ) ;
} ) ;
dialog . PopupWindow ( GetActiveWindow ( ) ) ;
return ;
}
}
2020-01-12 09:21:50 -08:00
DoOpenWorkspace ( true ) ;
2019-09-05 08:18:24 -07:00
if ( mDeferredOpen ! = . None )
mDeferredOpen = _ ;
case . Workspace :
DoOpenWorkspace ( ) ;
case . CrashDump :
DoOpenCrashDump ( ) ;
default :
}
}
var deferredOpen = mDeferredOpen ;
mDeferredOpen = . None ;
switch ( deferredOpen )
{
case . File :
DoOpenFile ( ) ;
case . CrashDump :
DoOpenCrashDump ( ) ;
case . Workspace , . NewWorkspace , . NewWorkspaceOrProject :
if ( ( mDeferredOpenFileName = = null ) & & ( deferredOpen = = . Workspace ) )
{
DoDeferredOpen ( _ ) ;
break ;
}
if ( CheckCloseWorkspace ( mMainWindow ,
new ( ) = >
{
DoDeferredOpen ( _ ) ;
} ,
new ( ) = >
{
DoDeferredOpen ( _ ) ;
} ,
new ( ) = >
{
DeleteAndNullify ! ( mDeferredOpenFileName ) ;
}
) )
{
DoDeferredOpen ( _ ) ;
}
case . DebugSession :
DoOpenDebugSession ( ) ;
default :
}
}
2019-08-23 11:56:54 -07:00
public override void Update ( bool batchStart )
{
scope AutoBeefPerf ( "IDEApp.Update" ) ;
2019-09-02 17:39:47 -07:00
/ * using ( mWorkspace . mMonitor . Enter ( ) )
{
} * /
2019-08-23 11:56:54 -07:00
if ( mDbgFastUpdate )
{
RefreshRate = 240 ;
MarkDirty ( ) ;
}
else
{
RefreshRate = 60 ;
}
bool hasFocus = false ;
for ( let window in mWindows )
{
hasFocus | = window . mHasFocus ;
}
if ( mEnableGCCollect )
{
/ * if ( hasFocus )
GC . SetAutoCollectPeriod ( 10 ) ;
else
GC . SetAutoCollectPeriod ( 2000 ) ; * /
}
while ( ! mDeferredFails . IsEmpty )
{
var error = mDeferredFails . PopFront ( ) ;
Fail ( error ) ;
delete error ;
}
if ( mStopping )
return ;
if ( batchStart )
{
//BFApp_CheckMemory();
}
#if ! CLI
2019-09-18 08:13:00 -07:00
if ( mSettings . mEnableDevMode )
UpdateIPC ( ) ;
2019-08-23 11:56:54 -07:00
#endif
if ( mRunTest )
{
if ( mRunTestDelay > 0 )
{
mRunTestDelay - - ;
}
else if ( IsCompiling )
{
}
else if ( mDebugger . mIsRunning )
{
mDebugger . Terminate ( ) ;
mRunTestDelay = 30 ;
}
else
{
mTargetStartWithStep = false ;
CompileAndRun ( ) ;
mRunTestDelay = 200 ;
}
}
if ( mProfilePanel ! = null )
mProfilePanel . ForcedUpdate ( ) ;
if ( mLongUpdateProfileId ! = 0 )
DoLongUpdateCheck ( ) ;
if ( mWakaTime ! = null )
mWakaTime . Update ( ) ;
if ( mFindResultsPanel ! = null )
mFindResultsPanel . Update ( ) ;
if ( mBfResolveSystem ! = null )
mBfResolveSystem . PerfZoneStart ( "IDEApp.Update" ) ;
UpdateWorkspace ( ) ;
if ( ThemeFactory . mDefault ! = null )
ThemeFactory . mDefault . Update ( ) ;
base . Update ( batchStart ) ;
DarkTooltipManager . UpdateTooltip ( ) ;
mGlobalUndoManager . Update ( ) ;
for ( var project in mWorkspace . mProjects )
project . Update ( ) ;
UpdateCompilersAndDebugger ( ) ;
if ( mScriptManager ! = null )
mScriptManager . Update ( ) ;
if ( mTestManager ! = null )
{
mTestManager . Update ( ) ;
if ( mTestManager . mIsDone )
{
if ( mMainFrame ! = null )
mMainFrame . mStatusBar . SelectConfig ( mTestManager . mPrevConfigName ) ;
DeleteAndNullify ! ( mTestManager ) ;
}
}
UpdateExecution ( ) ;
if ( mBfResolveSystem ! = null )
mBfResolveSystem . PerfZoneEnd ( ) ;
2019-09-05 08:18:24 -07:00
UpdateDeferredOpens ( ) ;
2019-08-23 11:56:54 -07:00
mHaveSourcesChangedInternallySinceLastCompile = false ;
WithSourceViewPanels ( scope ( sourceViewPanel ) = >
{
mHaveSourcesChangedInternallySinceLastCompile | = sourceViewPanel . mHasChangedSinceLastCompile ;
} ) ;
if ( ( mCloseDelay > 0 ) & & ( - - mCloseDelay = = 0 ) )
mMainWindow . Close ( ) ;
ProcessIdleDeferredDeletes ( ) ;
/ * if ( ( mUpdateCnt % ( 60 * 3 ) = = 0 ) & & ( mEnableGCCollect ) )
{
scope AutoBeefPerf ( "GC.Collect" ) ;
GC . Collect ( ) ;
} * /
if ( mDebugAutoShutdownCounter > 0 )
{
if ( - - mDebugAutoShutdownCounter = = 0 )
Stop ( ) ;
}
if ( ( mRunningTestScript ) & & ( ! IsCompiling ) & & ( ! AreTestsRunning ( ) ) )
{
if ( ( mFailed ) | | ( ! mScriptManager . HasQueuedCommands ) )
{
if ( + + mScriptManager . mDoneTicks > = 2 )
{
OutputLine ( "Total script time: {0}ms" , mScriptManager . mTimeoutStopwatch . ElapsedMilliseconds ) ;
if ( mExitWhenTestScriptDone )
Stop ( ) ;
else
mRunningTestScript = false ;
}
}
}
for ( var sourceViewPanel in mPostRemoveUpdatePanels )
{
if ( sourceViewPanel . NeedsPostRemoveUpdate )
{
sourceViewPanel . Update ( ) ;
}
else
{
//Debug.WriteLine("Removing sourceViewPanel from mPostRemoveUpdatePanel {0} from IDEApp.Update", sourceViewPanel);
sourceViewPanel . [ Friend ] mInPostRemoveUpdatePanels = false ;
@sourceViewPanel . Remove ( ) ;
}
}
if ( IDEApp . sApp . mSpellChecker ! = null )
IDEApp . sApp . mSpellChecker . CheckThreadDone ( ) ;
///
//TODO: REMOVE
//mDebugger.InitiateHotResolve(.ActiveMethods | .Allocations);
}
public override void Draw ( )
{
scope AutoBeefPerf ( "IDEApp.Draw" ) ;
#if CLI
return ;
#endif
# unwarn
if ( mBfResolveSystem ! = null )
{
mBfResolveSystem . PerfZoneStart ( "IDEApp.Draw" ) ;
base . Draw ( ) ;
mBfResolveSystem . PerfZoneEnd ( ) ;
if ( mBfResolveSystem . mIsTiming )
{
mBfResolveSystem . StopTiming ( ) ;
mBfResolveSystem . DbgPrintTimings ( ) ;
}
}
else
base . Draw ( ) ;
}
public void DrawSquiggle ( Graphics g , float x , float y , float width )
{
Image squiggleImage = IDEApp . sApp . mSquiggleImage ;
int32 segSize = 30 ;
float height = mSquiggleImage . mHeight ;
2019-09-30 12:23:27 -07:00
2019-08-23 11:56:54 -07:00
float curX = x ;
float curWidth = width ;
2019-09-30 12:23:27 -07:00
float drawY = y + gApp . mCodeFont . GetHeight ( ) ;
2019-08-23 11:56:54 -07:00
while ( curWidth > 0 )
{
float drawWidth = Math . Min ( curWidth , segSize - ( curX % segSize ) ) ;
float u1 = ( ( int32 ) curX % segSize ) / ( float ) squiggleImage . mSrcWidth ;
float u2 = u1 + drawWidth / ( float ) squiggleImage . mSrcWidth ;
2019-09-30 12:23:27 -07:00
g . DrawQuad ( squiggleImage , curX , drawY , u1 , 0 , drawWidth , height , u2 , 1.0f ) ;
2019-08-23 11:56:54 -07:00
curWidth - = drawWidth ;
curX + = drawWidth ;
}
}
public enum MessageBeepType
{
Default = - 1 ,
Ok = 0x00000000 ,
Error = 0x00000010 ,
Question = 0x00000020 ,
Warning = 0x00000030 ,
Information = 0x00000040 ,
}
public static void Beep ( MessageBeepType type )
{
#if BF_PLATFORM_WINDOWS
MessageBeep ( type ) ;
#endif
}
#if BF_PLATFORM_WINDOWS
[Import("user32.lib"), CLink, StdCall]
public static extern bool MessageBeep ( MessageBeepType type ) ;
#endif
}
static
{
public static IDEApp gApp ;
/ * public static mixin GS ( int val )
{
( int ) ( val * DarkTheme . sScale )
}
public static mixin GS ( float val )
{
float fVal = val * DarkTheme . sScale ;
fVal
} * /
}
}