private void OnEditorUpdate()
        {
            TypeSafeUtil.ReportCodeRefreshCompleted();

            Settings settings = Settings.Instance;

            if (settings == null)
            {
                return;
            }

            if (!WelcomeWindow.HasOpenedBefore() || !settings.HasShownWelcome)
            {
                TSLog.Log(LogCategory.Trace,
                          string.Format("Opening welcome window (HasOpenedBefore={0}, HasShownWelcome={1})", WelcomeWindow.HasOpenedBefore(), settings.HasShownWelcome));
                WelcomeWindow.Open();
            }
            else if (WelcomeWindow.GetPreviousOpenedVersion() != Strings.Version)
            {
                TSLog.Log(LogCategory.Trace,
                          string.Format("Opening changelog window (previousVersion={0}, currentVersion={1})", WelcomeWindow.GetPreviousOpenedVersion(), Strings.Version));
                WelcomeWindow.Open(true);

                TSLog.Log(LogCategory.Trace, "Clearing AssetTypeCache (new TypeSafe version detected)");
                AssetTypeCache.ClearCache();
            }

            Step();
        }
        private void OnDisable()
        {
            TSLog.Log(LogCategory.Trace, "TypeSafeController.OnDisable");

            TypeSafeUtil.ReportCodeRefreshStarted();

            if (State != States.Idle)
            {
                Cancel();
                Queue();
            }

            TSLog.CloseLog();
        }
        private void OnEnable()
        {
            TSLog.Log(LogCategory.Trace,
                      string.Format("TypeSafeController.OnEnable (Version={0}, ", Strings.Version) +
                      string.Format("UnityVersion={0}, ", Application.unityVersion) +
                      string.Format("TypeSafePath={0}, ", PathUtility.GetTypeSafePath()) +
                      string.Format("TypeSafeEditorPath={0})", PathUtility.GetTypeSafeEditorPath()));

            _instance = this;

            TypeSafeUtil.EnsureCorrectUnityVersion();

            EditorApplication.update += OnEditorUpdate;
        }
Exemple #4
0
        private static TypeCache GetInstance(bool autoCreate)
        {
            if (!TypeSafeUtil.IsEnabled())
            {
                throw new InvalidOperationException(
                          "Attempted to create settings instance while TypeSafe is disabled. Something should be checking TypeSafeUtil.IsEnabled() before running.");
            }

            var cachePath = PathUtility.GetTypeCachePath();

            TSLog.Log(LogCategory.Trace, string.Format("Checking for TypeCache asset at {0}", cachePath));

            var fileExists = File.Exists(cachePath);
            var instance   = AssetDatabase.LoadAssetAtPath <TypeCache>(cachePath);

            if (instance == null && fileExists)
            {
                TSLog.Log(LogCategory.Trace, "TypeCache asset exists, but AssetDatabase doesn't know it. Likely project reimport in progress.");
                return(null);
            }

            if (instance == null)
            {
                TSLog.Log(LogCategory.Trace, string.Format("TypeCache asset not found at {0} (fileExists={1}, instance=null)", cachePath, fileExists));

                if (!autoCreate)
                {
                    return(null);
                }

                // Create instance
                instance = CreateInstance <TypeCache>();

                TSLog.Log(LogCategory.Info, string.Format("Creating TypeCache asset at {0}", cachePath));

                try
                {
                    AssetDatabase.CreateAsset(instance, cachePath);
                }
                catch (Exception e)
                {
                    TSLog.LogError(LogCategory.Info, "Error creating TypeCache asset.");
                    TSLog.LogError(LogCategory.Info, e.ToString());
                }
            }

            return(instance);
        }
        private void BeginScan()
        {
            if (_state != States.Idle && _state != States.ScanQueued)
            {
                throw new InvalidOperationException();
            }

            TSLog.BeginBuffer(LogCategory.Compile);
            TSLog.Log(LogCategory.Trace, "BeginScan");
            TypeSafeUtil.CheckForRemovedAssets();

            _stopwatch.Reset();
            _stopwatch.Start();

            _scanController = new ScanController();
            _scanController.Begin();

            _state = States.Scanning;
        }
Exemple #6
0
 /// <summary>
 /// Format a string with the class prefix/suffix specified in the Settings window.
 /// </summary>
 /// <param name="baseName"></param>
 /// <returns>A string in the format {prefix}{baseName}{suffix}</returns>
 public static string FormatTypeName(string baseName)
 {
     return(TypeSafeUtil.GetFinalClassName(baseName));
 }
        private static void DoCompile(CompileParameters p)
        {
            using (var provider = new CSharpCodeProvider())
            {
                var compileUnits = new List <CodeCompileUnit>();

                if (p.ResourceDatabase != null)
                {
                    var compiler = new ResourceCompiler();

                    compiler.ClassName = TypeSafeUtil.GetFinalClassName(Strings.ResourcesTypeName);
                    compiler.Namespace = Settings.Instance.Namespace;

                    try
                    {
                        var u = compiler.Compile(p.ResourceDatabase);
                        compileUnits.Add(u);
                    }
                    catch (Exception e)
                    {
                        TSLog.LogError(LogCategory.Compile, "Exception occured while compiling resources unit.");
                        TSLog.LogError(LogCategory.Compile, e.ToString());
                    }
                }

                if (p.DataUnits != null)
                {
                    var compiler = new DataUnitCompiler();
                    compiler.Namespace = Settings.Instance.Namespace;

                    foreach (var dataUnit in p.DataUnits)
                    {
                        try
                        {
                            compileUnits.Add(compiler.Compile(dataUnit));
                        }
                        catch (Exception e)
                        {
                            TSLog.LogError(LogCategory.Compile, string.Format("Exception occured while compiling data unit {0}", dataUnit.ClassName));
                            TSLog.LogError(LogCategory.Compile, e.ToString());
                        }
                    }
                }

                var results = new List <string>();

                var didSucceed = false;

                switch (p.CompileMode)
                {
                case CompileModes.Dll:

                    string path;
                    didSucceed = CompileToDll(provider, compileUnits, p, out path);
                    results.Add(path);
                    break;

                case CompileModes.SourceFiles:

                    IList <string> r;
                    didSucceed = CompileToSourceFiles(provider, compileUnits, p, out r);
                    results.AddRange(r);
                    break;
                }

                if (p.OnComplete != null)
                {
                    p.OnComplete(didSucceed, results);
                }
            }
        }
        private IEnumerable ScanProcess()
        {
            TSLog.Log(LogCategory.Scanner, "ScanController.ScanProcess start");

            ResourceDatabase db;

            var sw = new Stopwatch();

            sw.Start();

            using (var scanIterator = ResourceScanProcess().GetEnumerator())
            {
                while (scanIterator.MoveNext())
                {
                    if (sw.Elapsed.TotalSeconds > MaxUpdateProcessingTime)
                    {
                        TSLog.Log(LogCategory.Scanner, "ScanProcess Suspending");

                        Resources.UnloadUnusedAssets();

                        sw.Stop();
                        sw.Reset();

                        yield return(null);

                        sw.Start();
                    }
                }

                db = scanIterator.Current;
            }

            var dataUnits = new List <TypeSafeDataUnit>();

            TSLog.Log(LogCategory.Scanner, "Beginning ITypeSafeDataSource hooks");

            foreach (var dataSource in TypeSafeUtil.GetCustomDataSources())
            {
                if (Settings.Instance.DisabledDataSources.Contains(dataSource.GetType().AssemblyQualifiedName))
                {
                    TSLog.Log(LogCategory.Scanner, string.Format("Skipping {0}", dataSource.GetType().FullName));
                    continue;
                }

                TSLog.Log(LogCategory.Scanner, string.Format("Processing {0}", dataSource.GetType().FullName));

                try
                {
                    var data = dataSource.GetTypeSafeDataUnit();

                    if (ValidateDataUnit(data))
                    {
                        dataUnits.Add(data);
                    }
                }
                catch (Exception e)
                {
                    TSLog.LogError(LogCategory.Info,
                                   string.Format("Exception occured inside data source ({0})", dataSource.GetType().FullName));
                    TSLog.LogError(LogCategory.Info, e.ToString());
                }
            }

            TSLog.Log(LogCategory.Scanner, "Done running ITypeSafeDataSource hooks");

            Result = new ScanResult(db, dataUnits);

            TSLog.Log(LogCategory.Scanner, "ScanProcess Done");

            IsDone        = true;
            WasSuccessful = true;
        }
        private bool ValidateDataUnit(TypeSafeDataUnit unit, bool isNested = false)
        {
            if (string.IsNullOrEmpty(unit.ClassName) || string.IsNullOrEmpty(unit.ClassName.Trim()))
            {
                TSLog.LogError(LogCategory.Compile, string.Format("Error validating TypeSafeDataUnit ({0})", unit.ClassName));
                TSLog.LogError(LogCategory.Compile, Strings.Error_NameMustNotBeEmpty);
                return(false);
            }

            string errorMessage;

            if (!isNested && !TypeSafeUtil.ValidateTypeName(unit.ClassName, out errorMessage))
            {
                TSLog.LogError(LogCategory.Compile, string.Format("Error validating TypeSafeDataUnit ({0})", unit.ClassName));
                TSLog.LogError(LogCategory.Compile, errorMessage);
                return(false);
            }

            if (!isNested && !TypeSafeUtil.TestTypeNameConflicts(unit.ClassName))
            {
                TSLog.LogError(LogCategory.Compile, string.Format("Error validating TypeSafeDataUnit ({0})", unit.ClassName));
                TSLog.LogError(LogCategory.Compile, Strings.Error_ConflictsWithExistingType);
                return(false);
            }

            foreach (var nestedUnit in unit.NestedUnits)
            {
                if (!ValidateDataUnit(nestedUnit, true))
                {
                    return(false);
                }
            }

            foreach (var data in unit.Data)
            {
                if (string.IsNullOrEmpty(data.PropertyName.Trim()))
                {
                    TSLog.LogError(LogCategory.Compile, "Error validating data entry");
                    TSLog.LogError(LogCategory.Compile, Strings.Error_NameMustNotBeEmpty);
                    return(false);
                }

                var dataType = /*data.OverrideDataType ??*/ unit.DataType;

                if ((dataType.IsPrimitive || dataType == typeof(string)) && data.Parameters.Length == 1 &&
                    data.Parameters[0] != null && data.Parameters[0].GetType() == dataType)
                {
                    continue;
                }

                foreach (var parameter in data.Parameters)
                {
                    if (parameter == null)
                    {
                        TSLog.LogError(LogCategory.Compile, "Data parameter must not be null");
                        return(false);
                    }

                    var pType = parameter.GetType();

                    if (pType.IsPrimitive)
                    {
                        continue;
                    }

                    if (pType == typeof(string))
                    {
                        continue;
                    }

                    TSLog.LogError(LogCategory.Compile, "Data constructor parameter must be primitive or string");

                    return(false);
                }

                var pTypeArray = data.Parameters.Select(p => p.GetType()).ToArray();

                var constructor = dataType.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, pTypeArray,
                                                          null);

                if (constructor == null)
                {
                    var sig = string.Join(", ", pTypeArray.Select(p => p.FullName).ToArray());
                    TSLog.LogError(LogCategory.Compile,
                                   string.Format("Data Type does not have constructor that matches provided data ({0})", sig));
                }
            }

            return(true);
        }
        private void Step()
        {
            switch (State)
            {
            case States.Idle:
                break;

            case States.ScanQueued:

                if (!TypeSafeUtil.ShouldBeOperating())
                {
                    break;
                }

                BeginScan();

                break;

            case States.Scanning:

                if (_scanController == null)
                {
                    TSLog.LogError(LogCategory.Trace, "ScanController = null, but State = Scanning");
                    _state = States.Idle;
                    break;
                }

                if (!TypeSafeUtil.ShouldBeOperating())
                {
                    TSLog.Log(LogCategory.Trace, "Aborting scan due to script reload in progress.");

                    Cancel();
                    Queue();
                    break;
                }

                _scanController.Update();

                ItemsCompleted = _scanController.ItemsCompleted;
                TotalItems     = _scanController.TotalItems;

                if (_scanController.IsDone)
                {
                    TSLog.Log(LogCategory.Trace, string.Format("Scan complete (took {0}s).", _stopwatch.Elapsed.TotalSeconds));

                    if (_scanController.WasSuccessful)
                    {
                        _scanResult     = _scanController.Result;
                        _scanController = null;
                        BeginCompile();
                    }
                    else
                    {
                        TSLog.LogError(LogCategory.Info, "Error occured while scanning. Aborting process.");
                        _state = States.Idle;
                    }
                }

                break;

            case States.Compiling:
            case States.Waiting:

                if (_compileController == null)
                {
                    TSLog.LogError(LogCategory.Trace, "CompileController = null, but State = Compiling");
                    _state = States.Idle;
                    break;
                }

                if (!TypeSafeUtil.ShouldBeOperating())
                {
                    TSLog.Log(LogCategory.Trace, "Aborting compile.");
                    Cancel();
                    Queue();
                    break;
                }

                if (_compileController.IsDone)
                {
                    if (_state != States.Waiting)
                    {
                        // Perform a dry run of the deploy step to see if there were any changes since the last compile
                        int changeCount;
                        TypeSafeUtil.DeployBuildArtifacts(_compileController.Output, out changeCount, true);

                        // Delay for minimum build time if not user initiated and there were changes
                        if (Settings.Instance.EnableWaiting && changeCount > 0 && !_userInitiated &&
                            _stopwatch.Elapsed.TotalSeconds < Settings.Instance.MinimumBuildTime)
                        {
                            _state = States.Waiting;
                            break;
                        }
                    }
                    else
                    {
                        // Wait for wait stage to elapse
                        if (!_abortWait && _stopwatch.Elapsed.TotalSeconds < Settings.Instance.MinimumBuildTime)
                        {
                            break;
                        }
                    }

                    _abortWait = false;

                    TSLog.Log(LogCategory.Trace,
                              string.Format("Compile Complete (WasSuccessful={0})", _compileController.WasSuccessful));

                    if (_compileController.WasSuccessful)
                    {
                        int updatedFileCount;
                        var deployResult = TypeSafeUtil.DeployBuildArtifacts(_compileController.Output,
                                                                             out updatedFileCount);

                        TSLog.Log(LogCategory.Trace,
                                  string.Format("Deploy Complete (WasSuccessful={0}, updatedFileCount={1})", deployResult, updatedFileCount));

                        var shouldReport = _userInitiated || updatedFileCount > 0;

                        TSLog.EndBuffer(LogCategory.Compile, shouldReport);

                        if (!deployResult)
                        {
                            TSLog.LogError(LogCategory.Info, "Compile failed.");
                        }
                        else if (shouldReport)
                        {
                            if (updatedFileCount == 0)
                            {
                                TSLog.Log(LogCategory.Info, "Compile complete, no changes.");
                            }
                            else
                            {
                                TSLog.Log(LogCategory.Info,
                                          string.Format("Compile completed. (Took {0}s)", _stopwatch.Elapsed.Seconds));
                            }
                        }
                    }

                    _compileController = null;
                    _state             = States.Idle;
                }

                break;
            }
        }