diff --git a/External/Plugins/ASCompletion/ASCompletion.csproj b/External/Plugins/ASCompletion/ASCompletion.csproj index cd662c73b4..65870bec44 100644 --- a/External/Plugins/ASCompletion/ASCompletion.csproj +++ b/External/Plugins/ASCompletion/ASCompletion.csproj @@ -150,6 +150,10 @@ PluginCore False + + {78101c01-e186-4954-b1dd-debb7905fad8} + ProjectManager + diff --git a/External/Plugins/ASCompletion/Helpers/ASTCache.cs b/External/Plugins/ASCompletion/Helpers/ASTCache.cs index de9679faa4..790ef2a4af 100644 --- a/External/Plugins/ASCompletion/Helpers/ASTCache.cs +++ b/External/Plugins/ASCompletion/Helpers/ASTCache.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Windows.Forms; using ASCompletion.Context; using ASCompletion.Model; @@ -16,12 +18,14 @@ internal class ASTCache { public event Action FinishedUpdate; - Dictionary cache = new Dictionary(new ClassModelComparer()); - readonly List outdatedModels = new List(); + Dictionary cache = new Dictionary(CacheHelper.classModelComparer); + readonly HashSet outdatedModels = new HashSet(CacheHelper.classModelComparer); /// /// A list of ClassModels that extend / implement something that does not exist yet /// - readonly HashSet unfinishedModels = new HashSet(); + readonly HashSet unfinishedModels = new HashSet(CacheHelper.classModelComparer); + + private int outdateUpdateCount; public CachedClassModel GetCachedModel(ClassModel cls) { @@ -34,15 +38,18 @@ public void Clear() { lock (outdatedModels) outdatedModels.Clear(); - lock (cache) - cache.Clear(); + lock (unfinishedModels) + unfinishedModels.Clear(); + cache.Clear(); } public void Remove(ClassModel cls) { lock (cache) { - var cachedClassModel = GetOrCreate(cache, cls); + var cachedClassModel = GetCachedModel(cls); + + if (cachedClassModel == null) return; var implementing = cachedClassModel.Implementing; var overriding = cachedClassModel.Overriding; @@ -71,72 +78,68 @@ public void Remove(ClassModel cls) public void MarkAsOutdated(ClassModel cls) { lock (outdatedModels) - if (!outdatedModels.Contains(cls)) - outdatedModels.Add(cls); + outdatedModels.Add(cls); } public void UpdateOutdatedModels() { - var action = new Action(() => + var context = ASContext.GetLanguageContext(PluginBase.CurrentProject.Language); + if (context?.Classpath == null) + return; + + HashSet outdated; + lock (outdatedModels) { - var context = ASContext.GetLanguageContext(PluginBase.CurrentProject.Language); - if (context == null || context.Classpath == null) - return; + outdated = new HashSet(outdatedModels, outdatedModels.Comparer); + outdatedModels.Clear(); + } - List outdated; - lock (outdatedModels) - { - outdated = new List(outdatedModels); - outdatedModels.Clear(); - } - - foreach (var cls in outdated) - { - cls.ResolveExtends(); + var newModels = outdated.Any(m => GetCachedModel(m) == null); - lock (cache) - { - //get the old CachedClassModel - var cachedClassModel = GetCachedModel(cls); - var connectedClasses = cachedClassModel?.ConnectedClassModels; + Interlocked.Increment(ref outdateUpdateCount); + + foreach (var cls in outdated) + { + cls.ResolveExtends(); - //remove old cls - Remove(cls); + lock (cache) + { + //get the old CachedClassModel + var cachedClassModel = GetCachedModel(cls); + var connectedClasses = cachedClassModel?.ConnectedClassModels; - UpdateClass(cls, cache); + //remove old cls + Remove(cls); - //also update all classes / interfaces that are connected to cls - if (connectedClasses != null) - foreach (var connection in connectedClasses) - if (GetCachedModel(connection) != null) //only update existing connections, so a removed class is not reintroduced - UpdateClass(connection, cache); - } + UpdateClass(cls, cache); + + //also update all classes / interfaces that are connected to cls + if (connectedClasses != null) + foreach (var connection in connectedClasses) + if (GetCachedModel(connection) != null) //only update existing connections, so a removed class is not reintroduced + UpdateClass(connection, cache); } + } + + //for new ClassModels, we need to update everything in the list of classes that extend / implement something that does not exist + if (newModels) + { + HashSet toUpdate; + lock (unfinishedModels) + toUpdate = new HashSet(unfinishedModels, unfinishedModels.Comparer); - var newModels = outdated.Any(m => GetCachedModel(m) == null); - //for new ClassModels, we need to update everything in the list of classes that extend / implement something that does not exist - if (newModels) + foreach (var model in toUpdate) { - HashSet toUpdate; lock (unfinishedModels) - toUpdate = new HashSet(unfinishedModels); - - foreach (var model in toUpdate) - { - lock (unfinishedModels) - unfinishedModels.Remove(model); //will be added back by UpdateClass if needed + unfinishedModels.Remove(model); //will be added back by UpdateClass if needed - lock (cache) - UpdateClass(model, cache); - } + lock (cache) + UpdateClass(model, cache); } - - if (FinishedUpdate != null) - PluginBase.RunAsync(new MethodInvoker(FinishedUpdate)); - - }); + } - action.BeginInvoke(null, null); + if (Interlocked.Decrement(ref outdateUpdateCount) == 0 && FinishedUpdate != null) + PluginBase.RunAsync(new MethodInvoker(FinishedUpdate)); } /// @@ -144,38 +147,34 @@ public void UpdateOutdatedModels() /// public void UpdateCompleteCache() { - var action = new Action(() => + var context = ASContext.GetLanguageContext(PluginBase.CurrentProject.Language); + if (context?.Classpath == null || PathExplorer.IsWorking) { - var context = ASContext.GetLanguageContext(PluginBase.CurrentProject.Language); - if (context == null || context.Classpath == null || PathExplorer.IsWorking) - { - if (FinishedUpdate != null) - PluginBase.RunAsync(new MethodInvoker(FinishedUpdate)); - return; - } + if (FinishedUpdate != null) + PluginBase.RunAsync(new MethodInvoker(FinishedUpdate)); + return; + } - var c = new Dictionary(cache.Comparer); + var c = new Dictionary(CacheHelper.classModelComparer); - foreach (MemberModel memberModel in context.GetAllProjectClasses()) - { - if (PluginBase.MainForm.ClosingEntirely) - return; //make sure we leave if the form is closing, so we do not block it + foreach (MemberModel memberModel in context.GetAllProjectClasses()) + { + if (PluginBase.MainForm.ClosingEntirely) + return; //make sure we leave if the form is closing, so we do not block it - var cls = GetClassModel(memberModel); - UpdateClass(cls, c); - } + var cls = GetClassModel(memberModel); + UpdateClass(cls, c); + } - lock(cache) - cache = c; - if (FinishedUpdate != null) - PluginBase.RunAsync(new MethodInvoker(FinishedUpdate)); - }); - action.BeginInvoke(null, null); + lock (cache) + cache = c; + if (FinishedUpdate != null) + PluginBase.RunAsync(new MethodInvoker(FinishedUpdate)); } internal HashSet ResolveInterfaces(ClassModel cls) { - if (cls == null || cls.IsVoid()) return new HashSet(); + if (cls == null || cls.IsVoid()) return new HashSet(CacheHelper.classModelComparer); if (cls.Implements == null) return ResolveInterfaces(cls.Extends); var context = ASContext.GetLanguageContext(PluginBase.CurrentProject.Language); @@ -189,7 +188,7 @@ internal HashSet ResolveInterfaces(ClassModel cls) set.Add(interf); return set; }) - .Union(ResolveInterfaces(cls.Extends)).ToHashSet(); + .Union(ResolveInterfaces(cls.Extends)).ToHashSet(CacheHelper.classModelComparer); } /// @@ -244,7 +243,7 @@ void RemoveConnections(ClassModel cls, CacheDictionary goThrough, Func - void UpdateClass(ClassModel cls, Dictionary cache) + void UpdateClass(ClassModel cls, Dictionary classModelCache) { var context = ASContext.GetLanguageContext(PluginBase.CurrentProject.Language); @@ -254,14 +253,14 @@ void UpdateClass(ClassModel cls, Dictionary cache) return; } cls.ResolveExtends(); - var cachedClassModel = GetOrCreate(cache, cls); + var cachedClassModel = GetOrCreate(classModelCache, cls); //look for functions / variables in cls that originate from interfaces of cls var interfaces = ResolveInterfaces(cls); foreach (var interf in interfaces) { - var cachedInterf = GetOrCreate(cache, interf); + var cachedInterf = GetOrCreate(classModelCache, interf); cachedClassModel.ConnectedClassModels.Add(interf); //cachedClassModel is connected to interf.Key cachedInterf.ConnectedClassModels.Add(cls); //the inverse is also true @@ -277,12 +276,12 @@ void UpdateClass(ClassModel cls, Dictionary cache) if (implementing.Count == 0) continue; - cachedClassModel.Implementing.AddUnion(member, implementing.Keys); + cachedClassModel.Implementing.AddUnion(member, implementing.Keys, CacheHelper.classModelComparer); //now that we know member is implementing the interfaces in implementing, we can add cls as implementor for them foreach (var interf in implementing) { - var cachedModel = GetOrCreate(cache, interf.Key); - var set = CacheHelper.GetOrCreateSet(cachedModel.Implementors, interf.Value); + var cachedModel = GetOrCreate(classModelCache, interf.Key); + var set = CacheHelper.GetOrCreateSet(cachedModel.Implementors, interf.Value, CacheHelper.classModelComparer); set.Add(cls); } } @@ -294,7 +293,7 @@ void UpdateClass(ClassModel cls, Dictionary cache) var currentParent = cls.Extends; while (currentParent != null && !currentParent.IsVoid()) { - var cachedParent = GetOrCreate(cache, currentParent); + var cachedParent = GetOrCreate(classModelCache, currentParent); cachedClassModel.ConnectedClassModels.Add(currentParent); //cachedClassModel is connected to currentParent cachedParent.ConnectedClassModels.Add(cls); //the inverse is also true @@ -310,12 +309,12 @@ void UpdateClass(ClassModel cls, Dictionary cache) if (overridden == null || overridden.Count <= 0) continue; - cachedClassModel.Overriding.AddUnion(member, overridden.Keys); + cachedClassModel.Overriding.AddUnion(member, overridden.Keys, CacheHelper.classModelComparer); //now that we know member is overriding the classes in overridden, we can add cls as overrider for them foreach (var over in overridden) { - var cachedModel = GetOrCreate(cache, over.Key); - var set = CacheHelper.GetOrCreateSet(cachedModel.Overriders, over.Value); + var cachedModel = GetOrCreate(classModelCache, over.Key); + var set = CacheHelper.GetOrCreateSet(cachedModel.Overriders, over.Value, CacheHelper.classModelComparer); set.Add(cls); } } @@ -326,7 +325,7 @@ void UpdateClass(ClassModel cls, Dictionary cache) lock (unfinishedModels) unfinishedModels.Add(cls); } - + /// /// Gets all ClassModels from and the interfaces they extend that contain a definition of /// @@ -335,7 +334,7 @@ internal Dictionary GetDefiningInterfaces(MemberModel m { //look for all ClassModels with variables / functions of the same name as member //this could give faulty results if there are variables / functions of the same name with different signature in the interface - var implementors = new Dictionary(); + var implementors = new Dictionary(CacheHelper.classModelComparer); foreach (var interf in interfaces) { @@ -357,7 +356,7 @@ internal Dictionary GetOverriddenClasses(ClassModel cls if (cls.Extends == null || cls.Extends.IsVoid()) return null; if ((function.Flags & FlagType.Function) == 0 || (function.Flags & FlagType.Override) == 0) return null; - var parentFunctions = new Dictionary(); + var parentFunctions = new Dictionary(CacheHelper.classModelComparer); var currentParent = cls.Extends; while (currentParent != null && !currentParent.IsVoid()) @@ -379,7 +378,7 @@ internal Dictionary GetOverriddenClasses(ClassModel cls /// static HashSet ResolveExtends(ClassModel cls) { - var set = new HashSet(); + var set = new HashSet(CacheHelper.classModelComparer); var current = cls.Extends; while (current != null && !current.IsVoid()) @@ -399,7 +398,7 @@ static CachedClassModel GetOrCreate(Dictionary cac cached = new CachedClassModel(); cache.Add(cls, cached); } - + return cached; } @@ -416,29 +415,29 @@ static ClassModel GetClassModel(MemberModel cls) class CachedClassModel { - public HashSet ConnectedClassModels = new HashSet(); + public HashSet ConnectedClassModels = new HashSet(CacheHelper.classModelComparer); /// /// A set of ClassModels that extend this ClassModel /// - public HashSet ChildClassModels = new HashSet(); + public HashSet ChildClassModels = new HashSet(CacheHelper.classModelComparer); /// /// If this ClassModel is an interface, this contains a set of classes that implement this interface /// - public HashSet ImplementorClassModels = new HashSet(); + public HashSet ImplementorClassModels = new HashSet(CacheHelper.classModelComparer); /// /// If this ClassModel is an interface, this contains a set of classes - for each member - that implement the given members /// public CacheDictionary Implementors = new CacheDictionary(); - + /// /// Contains a set of interfaces - for each member - that contain the member. /// public CacheDictionary Implementing = new CacheDictionary(); - + /// /// Contains a set of classes - for each member - that override the member. /// @@ -452,26 +451,28 @@ class CachedClassModel static class CacheHelper { - internal static HashSet ToHashSet(this IEnumerable e) + internal static ClassModelComparer classModelComparer = new ClassModelComparer(); + + internal static HashSet ToHashSet(this IEnumerable e, IEqualityComparer comparer) { - if (e == null) return new HashSet(); + if (e == null) return new HashSet(comparer); - return new HashSet(e); + return new HashSet(e, comparer); } - internal static void AddUnion(this Dictionary> dict, S key, IEnumerable value) + internal static void AddUnion(this Dictionary> dict, S key, IEnumerable value, IEqualityComparer comparer) { - var set = GetOrCreateSet(dict, key); + var set = GetOrCreateSet(dict, key, comparer); set.UnionWith(value); } - internal static ISet GetOrCreateSet(Dictionary> dict, S key) + internal static ISet GetOrCreateSet(Dictionary> dict, S key, IEqualityComparer comparer) { HashSet set; if (!dict.TryGetValue(key, out set)) { - set = new HashSet(); //TODO: maybe supply new ClassModelComparer() + set = new HashSet(comparer); dict.Add(key, set); } return set; @@ -484,9 +485,12 @@ public bool Equals(ClassModel x, ClassModel y) { if (x == null || y == null) return x == y; - return x.Type == y.Type; + return x.Type == y.Type && x.InFile?.FileName == y.InFile?.FileName; } - public int GetHashCode(ClassModel obj) => obj.BaseType.GetHashCode(); + public int GetHashCode(ClassModel obj) => + !string.IsNullOrEmpty(obj.InFile?.FileName) + ? obj.InFile.FileName.GetHashCode() ^ obj.BaseType.GetHashCode() + : obj.BaseType.GetHashCode(); } } diff --git a/External/Plugins/ASCompletion/PluginMain.cs b/External/Plugins/ASCompletion/PluginMain.cs index cb580cbce4..8247cf72b0 100644 --- a/External/Plugins/ASCompletion/PluginMain.cs +++ b/External/Plugins/ASCompletion/PluginMain.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Reflection; using System.Text.RegularExpressions; +using System.Threading; using System.Timers; using System.Windows.Forms; using ASCompletion.Commands; @@ -23,13 +24,14 @@ using PluginCore.Localization; using PluginCore.Managers; using PluginCore.Utilities; +using ProjectManager.Projects; using ScintillaNet; using WeifenLuo.WinFormsUI.Docking; using Timer = System.Timers.Timer; namespace ASCompletion { - public class PluginMain: IPlugin + public class PluginMain : IPlugin { private string pluginName = "ASCompletion"; private string pluginGuid = "078c7c1a-c667-4f54-9e47-d45c0e835c4e"; @@ -81,7 +83,8 @@ public class PluginMain: IPlugin Bitmap upDownArrow; readonly ASTCache astCache = new ASTCache(); - bool initializedCache = true; + bool initializedCache; + bool cacheNeedsRecheck; IProject lastProject; Timer astCacheTimer; @@ -157,7 +160,7 @@ public virtual void Initialize() ASContext.GlobalInit(this); ModelsExplorer.CreatePanel(); } - catch(Exception ex) + catch (Exception ex) { ErrorManager.ShowError(/*"Failed to initialize the completion engine.\n"+ex.Message,*/ ex); } @@ -276,6 +279,8 @@ public void HandleEvent(Object sender, NotifyEvent e, HandlingPriority priority) astCache.Clear(); foreach (var document in PluginBase.MainForm.Documents) { + if (!document.IsEditable) continue; + //remove the markers UpdateMarkersFromCache(document.SplitSci1); UpdateMarkersFromCache(document.SplitSci2); @@ -338,7 +343,7 @@ public void HandleEvent(Object sender, NotifyEvent e, HandlingPriority priority) if (info != null && info.ContainsKey("language")) { IASContext context = ASContext.GetLanguageContext(info["language"] as string); - if (context != null && context.Settings != null + if (context != null && context.Settings != null && context.Settings.UserClasspath != null) info["cp"] = new List(context.Settings.UserClasspath); } @@ -385,7 +390,7 @@ public void HandleEvent(Object sender, NotifyEvent e, HandlingPriority priority) { case "AS2": name = "AS2Context"; break; case "AS3": name = "AS3Context"; break; - default: + default: name = cmdData.Substring(0, 1).ToUpper() + cmdData.Substring(1) + "Context"; break; } @@ -482,16 +487,31 @@ public void HandleEvent(Object sender, NotifyEvent e, HandlingPriority priority) { if (lastProject != PluginBase.CurrentProject) { + if (lastProject is Project) + ((Project) lastProject).ClasspathChanged -= Project_ClassPathChanged; lastProject = PluginBase.CurrentProject; + if (lastProject is Project) + ((Project) lastProject).ClasspathChanged += Project_ClassPathChanged; initializedCache = false; + astCacheTimer.Stop(); + astCache.Clear(); + foreach (var document in PluginBase.MainForm.Documents) + { + if (!document.IsEditable) continue; + + //remove the markers + ClearMarkersFromCache(document.SplitSci1); + ClearMarkersFromCache(document.SplitSci2); + } + } + else if (command == "ProjectManager.Menu") + { + var image = PluginBase.MainForm.FindImage("202"); + var item = new ToolStripMenuItem(TextHelper.GetString("Label.TypesExplorer"), image, + TypesExplorer, Keys.Control | Keys.J); + PluginBase.MainForm.RegisterShortcutItem("FlashToolsMenu.TypeExplorer", item); + ((ToolStripMenuItem) de.Data).DropDownItems.Insert(6, item); } - } - else if (command == "ProjectManager.Menu") - { - var image = PluginBase.MainForm.FindImage("202"); - var item = new ToolStripMenuItem(TextHelper.GetString("Label.TypesExplorer"), image, TypesExplorer, Keys.Control | Keys.J); - PluginBase.MainForm.RegisterShortcutItem("FlashToolsMenu.TypeExplorer", item); - ((ToolStripMenuItem)de.Data).DropDownItems.Insert(6, item); } break; } @@ -504,7 +524,7 @@ public void HandleEvent(Object sender, NotifyEvent e, HandlingPriority priority) switch (e.Type) { case EventType.ProcessArgs: - TextEvent te = (TextEvent) e; + TextEvent te = (TextEvent)e; if (reArgs.IsMatch(te.Value)) { // resolve current element @@ -607,7 +627,7 @@ public void HandleEvent(Object sender, NotifyEvent e, HandlingPriority priority) } } } - catch(Exception ex) + catch (Exception ex) { ErrorManager.ShowError(ex); } @@ -835,18 +855,17 @@ private void AddEventHandlers() // application events EventManager.AddEventHandler(this, eventMask); EventManager.AddEventHandler(this, EventType.UIStarted, HandlingPriority.Low); - + // cursor position changes tracking timerPosition = new Timer(); timerPosition.SynchronizingObject = PluginBase.MainForm as Form; timerPosition.Interval = 200; - timerPosition.Elapsed += new ElapsedEventHandler(timerPosition_Elapsed); + timerPosition.Elapsed += TimerPosition_Elapsed; //Cache update astCache.FinishedUpdate += UpdateOpenDocumentMarkers; astCacheTimer = new Timer { - SynchronizingObject = PluginBase.MainForm as Form, AutoReset = false, Enabled = false }; @@ -861,7 +880,7 @@ void UpdateCompleteCache() { if (PluginBase.CurrentProject == null) return; - astCache.UpdateCompleteCache(); + ThreadPool.QueueUserWorkItem(s => astCache.UpdateCompleteCache()); } void UpdateOpenDocumentMarkers() @@ -878,7 +897,7 @@ void UpdateOpenDocumentMarkers() void ApplyMarkers(ScintillaControl sci) { if (settingObject.DisableInheritanceNavigation || sci == null) return; - + //Register marker sci.MarkerDefineRGBAImage(MarkerDown, downArrow); sci.MarkerDefineRGBAImage(MarkerUp, upArrow); @@ -894,18 +913,24 @@ void ApplyMarkers(ScintillaControl sci) UpdateMarkersFromCache(sci); } - void UpdateMarkersFromCache(ScintillaControl sci) + void ClearMarkersFromCache(ScintillaControl sci) { - var marginWidth = 16; sci.SetMarginWidthN(Margin, 0); //margin is only made visible if something is found sci.MarkerDeleteAll(MarkerUp); sci.MarkerDeleteAll(MarkerDown); sci.MarkerDeleteAll(MarkerUpDown); + } + + void UpdateMarkersFromCache(ScintillaControl sci) + { + ClearMarkersFromCache(sci); if (settingObject.DisableInheritanceNavigation) return; if (PluginBase.CurrentProject == null) return; + + const int marginWidth = 16; var context = ASContext.GetLanguageContext(PluginBase.CurrentProject.Language) as ASContext; if (context == null) return; @@ -1081,37 +1106,51 @@ private void SetItemsEnabled(bool enabled, bool canBuild) void OnFileRemove(FileModel obj) { - PluginBase.RunAsync(() => + ThreadPool.QueueUserWorkItem(s => { - - foreach (var cls in obj.Classes) + try { - var cached = astCache.GetCachedModel(cls); - astCache.Remove(cls); - if (cached != null) - foreach (var c in cached.ConnectedClassModels) //need to update all connected stuff - astCache.MarkAsOutdated(c); - } + astCacheTimer.Stop(); - astCacheTimer.Stop(); - astCacheTimer.Start(); - - var sci1 = DocumentManager.FindDocument(obj.FileName)?.SplitSci1; - var sci2 = DocumentManager.FindDocument(obj.FileName)?.SplitSci2; + foreach (var cls in obj.Classes) + { + var cached = astCache.GetCachedModel(cls); + astCache.Remove(cls); + if (cached != null) + foreach (var c in cached.ConnectedClassModels) //need to update all connected stuff + astCache.MarkAsOutdated(c); + } - if (sci1 != null) - { - sci1.MarkerDeleteAll(MarkerUp); - sci1.MarkerDeleteAll(MarkerDown); - sci1.MarkerDeleteAll(MarkerUpDown); + if (initializedCache) astCacheTimer.Start(); } - if (sci2 != null) + catch { - sci2.MarkerDeleteAll(MarkerUp); - sci2.MarkerDeleteAll(MarkerDown); - sci2.MarkerDeleteAll(MarkerUpDown); + //TODO: Look into Timer problem } + PluginBase.RunAsync(() => + { + var doc = DocumentManager.FindDocument(obj.FileName); + if (doc != null) + { + var sci1 = doc.SplitSci1; + var sci2 = doc.SplitSci2; + + if (sci1 != null) + { + sci1.MarkerDeleteAll(MarkerUp); + sci1.MarkerDeleteAll(MarkerDown); + sci1.MarkerDeleteAll(MarkerUpDown); + } + if (sci2 != null) + { + sci2.MarkerDeleteAll(MarkerUp); + sci2.MarkerDeleteAll(MarkerDown); + sci2.MarkerDeleteAll(MarkerUpDown); + } + } + }); + EventManager.DispatchEvent(this, new DataEvent(EventType.Command, "ASCompletion.FileModelUpdated", obj)); }); } @@ -1122,17 +1161,25 @@ void OnFileRemove(FileModel obj) /// void OnFileUpdate(FileModel obj) { - PluginBase.RunAsync(() => + ThreadPool.QueueUserWorkItem(s => { if (PluginBase.CurrentProject == null) return; - foreach (var cls in obj.Classes) + try { - astCache.MarkAsOutdated(cls); - } + astCacheTimer.Stop(); - astCacheTimer.Stop(); - astCacheTimer.Start(); + foreach (var cls in obj.Classes) + { + astCache.MarkAsOutdated(cls); + } + + if (initializedCache) astCacheTimer.Start(); + } + catch + { + //TODO: Possible multi-threaded problem with timer + } EventManager.DispatchEvent(this, new DataEvent(EventType.Command, "ASCompletion.FileModelUpdated", obj)); }); @@ -1140,7 +1187,27 @@ void OnFileUpdate(FileModel obj) void AstCacheTimer_Elapsed(object sender, ElapsedEventArgs e) { - astCache.UpdateOutdatedModels(); + try + { + astCache.UpdateOutdatedModels(); + } + catch + { + //TODO: Handle some inner cases more properly + } + } + + void Project_ClassPathChanged(Project project) + { + try + { + astCacheTimer.Stop(); + if (initializedCache) astCacheTimer.Start(); + } + catch + { + //TODO: Potential timer problem + } } void Sci_MarginClick(ScintillaControl sender, int modifiers, int position, int margin) @@ -1156,12 +1223,11 @@ void Sci_MarginClick(ScintillaControl sender, int modifiers, int position, int m if (cached == null) return; - if (declaration.InClass.LineFrom == line) { ReferenceList.Show( ReferenceList.ConvertClassCache(cached.ImplementorClassModels).ToList(), - new List(0), + new List(0), ReferenceList.ConvertClassCache(cached.ChildClassModels).ToList(), new List(0) ); @@ -1257,7 +1323,7 @@ private void OnTextChanged(ScintillaControl sender, int position, int length, in sender.MarkerDelete(i, MarkerUpDown); } } - + } private void OnUpdateCallTip(ScintillaControl sci, int position) @@ -1278,7 +1344,7 @@ private void OnUpdateSimpleTip(ScintillaControl sci, Point mousePosition) OnMouseHover(sci, lastHoverPosition); } - void timerPosition_Elapsed(object sender, ElapsedEventArgs e) + void TimerPosition_Elapsed(object sender, ElapsedEventArgs e) { ScintillaControl sci = ASContext.CurSciControl; if (sci == null) return; @@ -1309,7 +1375,7 @@ private void ContextChanged() if (isValid) ASComplete.ResolveContext(sci); } else ASComplete.ResolveContext(null); - + bool enableItems = isValid && !doc.IsUntitled; pluginUI.OutlineTree.Enabled = ASContext.Context.CurrentModel != null; SetItemsEnabled(enableItems, ASContext.Context.CanBuild); diff --git a/External/Plugins/HaXeContext/ExternalToolchain.cs b/External/Plugins/HaXeContext/ExternalToolchain.cs index 284ae53a2f..fba906a799 100644 --- a/External/Plugins/HaXeContext/ExternalToolchain.cs +++ b/External/Plugins/HaXeContext/ExternalToolchain.cs @@ -246,9 +246,7 @@ private static void UpdateProject() var form = PluginBase.MainForm as System.Windows.Forms.Form; if (form.InvokeRequired) { - form.BeginInvoke((System.Windows.Forms.MethodInvoker)delegate { - UpdateProject(); - }); + form.BeginInvoke((Action)UpdateProject); return; } @@ -259,14 +257,11 @@ private static void UpdateProject() string args = GetCommand(hxproj, "display"); if (args == null) { - var msg = String.Format("No external 'display' command found for platform '{0}'", hxproj.MovieOptions.Platform); + var msg = $"No external 'display' command found for platform '{hxproj.MovieOptions.Platform}'"; TraceManager.Add(msg, -3); return; } - string config = hxproj.TargetBuild; - if (String.IsNullOrEmpty(config)) config = "flash"; - ProcessStartInfo pi = new ProcessStartInfo(); pi.FileName = Environment.ExpandEnvironmentVariables(exe); pi.Arguments = args; @@ -303,7 +298,7 @@ private static void UpdateProject() args = GetCommand(hxproj, "build", false); if (args == null) { - var msg = String.Format("No external 'build' command found for platform '{0}'", hxproj.MovieOptions.Platform); + var msg = $"No external 'build' command found for platform '{hxproj.MovieOptions.Platform}'"; TraceManager.Add(msg, -3); } else if (string.IsNullOrEmpty(hxproj.PreBuildEvent)) @@ -381,8 +376,8 @@ static string GetCommand(HaxeProject project, string name, bool processArguments var version = platform.GetVersion(project.MovieOptions.Version); if (version.Commands == null) { - throw new Exception(String.Format("No external commands found for target {0} and version {1}", - project.MovieOptions.Platform, project.MovieOptions.Version)); + throw new Exception( + $"No external commands found for target {project.MovieOptions.Platform} and version {project.MovieOptions.Version}"); } if (version.Commands.ContainsKey(name)) { diff --git a/External/Plugins/HaXeContext/Linters/DiagnosticsLinter.cs b/External/Plugins/HaXeContext/Linters/DiagnosticsLinter.cs index 512e7179b2..6eb063e90f 100644 --- a/External/Plugins/HaXeContext/Linters/DiagnosticsLinter.cs +++ b/External/Plugins/HaXeContext/Linters/DiagnosticsLinter.cs @@ -108,6 +108,8 @@ void AddDiagnosticsResults(List list, HaxeCompleteStatus status, { var range = res.Range ?? res.Args.Range; + if (range == null) continue; + var result = new LintingResult { File = range.Path,