diff --git a/External/Plugins/HaXeContext/Completion/CodeComplete.cs b/External/Plugins/HaXeContext/Completion/CodeComplete.cs index 6fa9f5c369..4d99c4810b 100644 --- a/External/Plugins/HaXeContext/Completion/CodeComplete.cs +++ b/External/Plugins/HaXeContext/Completion/CodeComplete.cs @@ -1319,7 +1319,16 @@ protected override void GetInstanceMembers(bool autoHide, ASResult expr, ClassMo return; } } - Context.TryResolveStaticExtensions(exprType, ASContext.Context.CurrentModel, out exprType); + if (expr.IsStatic && (exprType.Flags & FlagType.Enum) != 0 && (exprType.Flags & FlagType.Abstract) == 0) + { + var type = ResolveType("Enum", null); + if (Context.TryResolveStaticExtensions(type, ASContext.Context.CurrentModel, out var tmp)) + { + foreach (MemberModel it in tmp.Members) it.Flags |= FlagType.Static; + exprType.Members.Merge(tmp.Members); + } + } + else Context.TryResolveStaticExtensions(exprType, ASContext.Context.CurrentModel, out exprType); base.GetInstanceMembers(autoHide, expr, exprType, mask, dotIndex, result); } @@ -1518,7 +1527,27 @@ protected override void FindMemberEx(string token, ClassModel inClass, ASResult */ if (result.IsNull() && !string.IsNullOrEmpty(result.Path) && result.RelClass != null && !result.RelClass.IsVoid()) { - if (Context.TryResolveStaticExtensions(inClass, ASContext.Context.CurrentModel, out inClass)) + var hasStaticExtensions = false; + + /** + * for example: + * EnumType.createAll( + */ +// if (result.IsStatic +// && inClass.Flags.HasFlag(FlagType.Enum) +// && !inClass.Flags.HasFlag(FlagType.Abstract)) +// { +// var type = ResolveType("Enum", null); +// if (Context.TryResolveStaticExtensions(type, ASContext.Context.CurrentModel, out var tmp)) +// { +// foreach (MemberModel it in tmp.Members) it.Flags |= FlagType.Static; +// inClass.Members.Merge(tmp.Members); +// hasStaticExtensions = true; +// } +// } +// else + hasStaticExtensions = Context.TryResolveStaticExtensions(inClass, ASContext.Context.CurrentModel, out inClass); + if (hasStaticExtensions) { base.FindMemberEx(token, inClass, result, mask, access); if (result.Member != null && result.Member.Flags.HasFlag(FlagType.Using)) diff --git a/External/Plugins/HaXeContext/Context.cs b/External/Plugins/HaXeContext/Context.cs index fd982ee6b9..9a42ca59fe 100644 --- a/External/Plugins/HaXeContext/Context.cs +++ b/External/Plugins/HaXeContext/Context.cs @@ -1503,12 +1503,32 @@ internal static bool TryResolveStaticExtensions(ClassModel type, FileModel inFil { result = type; var imports = Context.ResolveImports(inFile); - if ((type.Flags & FlagType.Enum) != 0 && (type.Flags & FlagType.Abstract) == 0 - && Context.ResolveType("haxe.EnumTools.EnumValueTools", null) is ClassModel @using && !@using.IsVoid()) - { - @using = (ClassModel)@using.Clone(); - @using.Flags |= FlagType.Using; - imports.Add(@using); + /** + * for example: + * ``` + * enum EEnum {} + * ... + * EEnum. + * ``` + */ + if ((type.Flags & FlagType.Class) != 0 && type.Name == "Enum") + { + var @using = ResolveUsing("haxe.EnumTools", null); + if (!@using.IsVoid()) imports.Add(@using); + } + /** + * for example: + * ``` + * enum EEnum {} + * ... + * var e:EEnum; + * e. + * ``` + */ + else if ((type.Flags & FlagType.Enum) != 0 && (type.Flags & FlagType.Abstract) == 0) + { + var @using = ResolveUsing("haxe.EnumTools.EnumValueTools", null); + if (!@using.IsVoid()) imports.Add(@using); } if (imports.Count == 0) return false; var extensions = new MemberList(); @@ -1573,10 +1593,18 @@ bool CanBeExtended(ClassModel target, MemberModel extension, Visibility access) break; } } + if ((target.Flags & (FlagType.Abstract | FlagType.Class)) == (FlagType.Abstract | FlagType.Class) + && target.Name == "Enum" && target.Type == "Enum") + { + // for example: Enum. + return firstParamType.StartsWithOrdinal("Enum<"); + } if ((target.Flags & FlagType.Enum) != 0 && (target.Flags & FlagType.Abstract) == 0 && firstParamType == "EnumValue") { + // for example: EnumValue. + return true; } - else if (firstParamType != "Dynamic" && !firstParamType.StartsWithOrdinal("Dynamic<")) + if (firstParamType != "Dynamic" && !firstParamType.StartsWithOrdinal("Dynamic<")) { var targetType = type.Type; var index = targetType.IndexOf('<'); @@ -1623,6 +1651,14 @@ bool CanBeExtended(ClassModel target, MemberModel extension, Visibility access) } return true; } + ClassModel ResolveUsing(string name, FileModel file) + { + var @using = Context.ResolveType(name, file); + if (@using.IsVoid()) return ClassModel.VoidClass; + @using = (ClassModel) @using.Clone(); + @using.Flags |= FlagType.Using; + return @using; + } } public override string GetDefaultValue(string type) @@ -1746,7 +1782,7 @@ public override IEnumerable DecomposeTypes(IEnumerable types) /// /// Checks completion mode changes to start/restart/stop the haXe completion server if needed. /// - private void OnCompletionModeChange() + void OnCompletionModeChange() { if (completionModeHandler != null) { diff --git a/Tests/External/Plugins/HaxeContext.Tests/Completion/CodeCompleteTests.cs b/Tests/External/Plugins/HaxeContext.Tests/Completion/CodeCompleteTests.cs index cac98cc462..e41390220d 100644 --- a/Tests/External/Plugins/HaxeContext.Tests/Completion/CodeCompleteTests.cs +++ b/Tests/External/Plugins/HaxeContext.Tests/Completion/CodeCompleteTests.cs @@ -1237,6 +1237,18 @@ static IEnumerable OnCharAndReplaceTextIssue2757TestCases } } + static IEnumerable OnCharAndReplaceTextIssue2759TestCases + { + get + { + yield return new TestCaseData("BeforeOnCharAndReplaceText_issue2759_1", '.', false) + .Returns(CodeCompleteTests.ReadAllText("AfterOnCharAndReplaceText_issue2759_1")) + .SetName("ConcreteEnum. Issue 2759. Case 1") + .SetDescription("https://github.com/fdorg/flashdevelop/issues/2759"); + + } + } + [ Test, TestCaseSource(nameof(OnCharAndReplaceTextTestCases)), @@ -1263,6 +1275,7 @@ static IEnumerable OnCharAndReplaceTextIssue2757TestCases TestCaseSource(nameof(OnCharAndReplaceTextIssue2726TestCases)), TestCaseSource(nameof(OnCharAndReplaceTextIssue2750TestCases)), TestCaseSource(nameof(OnCharAndReplaceTextIssue2757TestCases)), + TestCaseSource(nameof(OnCharAndReplaceTextIssue2759TestCases)), ] public string OnCharAndReplaceText(string fileName, char addedChar, bool autoHide) { diff --git a/Tests/External/Plugins/HaxeContext.Tests/HaxeContext.Tests.csproj b/Tests/External/Plugins/HaxeContext.Tests/HaxeContext.Tests.csproj index 984cb57c22..0b22872aca 100644 --- a/Tests/External/Plugins/HaxeContext.Tests/HaxeContext.Tests.csproj +++ b/Tests/External/Plugins/HaxeContext.Tests/HaxeContext.Tests.csproj @@ -1275,6 +1275,8 @@ + + diff --git a/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/AfterOnCharAndReplaceText_enums_1.hx b/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/AfterOnCharAndReplaceText_enums_1.hx index 21b01169a1..0316c9b2a7 100644 --- a/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/AfterOnCharAndReplaceText_enums_1.hx +++ b/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/AfterOnCharAndReplaceText_enums_1.hx @@ -1,10 +1,10 @@ package; class Bar { static function main() { - EType.EnumInstance + EType.AEnumInstance } } enum EType { - EnumInstance; + AEnumInstance; } \ No newline at end of file diff --git a/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/AfterOnCharAndReplaceText_issue2759_1.hx b/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/AfterOnCharAndReplaceText_issue2759_1.hx new file mode 100644 index 0000000000..be8ca91e70 --- /dev/null +++ b/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/AfterOnCharAndReplaceText_issue2759_1.hx @@ -0,0 +1,8 @@ +package; +using haxe.EnumTools; +private enum PIssue2759 {} +class Issue2759_1 { + function foo() { + PIssue2759.createAll + } +} \ No newline at end of file diff --git a/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/BeforeOnCharAndReplaceText_enums_1.hx b/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/BeforeOnCharAndReplaceText_enums_1.hx index a886dc5c28..056858f92f 100644 --- a/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/BeforeOnCharAndReplaceText_enums_1.hx +++ b/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/BeforeOnCharAndReplaceText_enums_1.hx @@ -6,5 +6,5 @@ class Bar { } enum EType { - EnumInstance; + AEnumInstance; } \ No newline at end of file diff --git a/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/BeforeOnCharAndReplaceText_issue2759_1.hx b/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/BeforeOnCharAndReplaceText_issue2759_1.hx new file mode 100644 index 0000000000..daef0a616e --- /dev/null +++ b/Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/BeforeOnCharAndReplaceText_issue2759_1.hx @@ -0,0 +1,8 @@ +package; +using haxe.EnumTools; +private enum PIssue2759 {} +class Issue2759_1 { + function foo() { + PIssue2759.$(EntryPoint) + } +} \ No newline at end of file