From d9fcd1faa9b519355d112a2feb61740fa0694464 Mon Sep 17 00:00:00 2001 From: slavara Date: Mon, 15 Apr 2019 22:27:02 +0300 Subject: [PATCH 1/2] [Haxe][CodeComplete] Added completion for 'using haxe.EnumTools'. fixes #2759 --- .../HaXeContext/Completion/CodeComplete.cs | 24 ++++++++++++++++++- .../Completion/CodeCompleteTests.cs | 13 ++++++++++ .../HaxeContext.Tests.csproj | 2 ++ .../AfterOnCharAndReplaceText_issue2759_1.hx | 8 +++++++ .../BeforeOnCharAndReplaceText_issue2759_1.hx | 8 +++++++ 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/AfterOnCharAndReplaceText_issue2759_1.hx create mode 100644 Tests/External/Plugins/HaxeContext.Tests/Test Files/completion/BeforeOnCharAndReplaceText_issue2759_1.hx diff --git a/External/Plugins/HaXeContext/Completion/CodeComplete.cs b/External/Plugins/HaXeContext/Completion/CodeComplete.cs index 6fa9f5c369..cdb60cf2d4 100644 --- a/External/Plugins/HaXeContext/Completion/CodeComplete.cs +++ b/External/Plugins/HaXeContext/Completion/CodeComplete.cs @@ -1319,7 +1319,29 @@ protected override void GetInstanceMembers(bool autoHide, ASResult expr, ClassMo return; } } - Context.TryResolveStaticExtensions(exprType, ASContext.Context.CurrentModel, out exprType); + if ((exprType.Flags & FlagType.Enum) != 0 && (exprType.Flags & FlagType.Abstract) == 0 && expr.IsStatic) + { + /** + * for example: + * using haxe.EnumTools; + * enum ETest { + * A; + * B; + * } + * class Test { + * function test() { + * ETest. + * } + * } + */ + var type = ResolveType("Enum", ASContext.Context.CurrentModel); + if (!type.IsVoid() && Context.TryResolveStaticExtensions(type, ASContext.Context.CurrentModel, out var tmpExprType)) + { + exprType = tmpExprType; + mask &= ~FlagType.Static; + } + } + else Context.TryResolveStaticExtensions(exprType, ASContext.Context.CurrentModel, out exprType); base.GetInstanceMembers(autoHide, expr, exprType, mask, dotIndex, result); } 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 a3d3b7a8d3..1a54e4cce4 100644 --- a/Tests/External/Plugins/HaxeContext.Tests/HaxeContext.Tests.csproj +++ b/Tests/External/Plugins/HaxeContext.Tests/HaxeContext.Tests.csproj @@ -1272,6 +1272,8 @@ + + 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_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 From 858bdddd71af1615ae850a040c9a98206b03ec7e Mon Sep 17 00:00:00 2001 From: slavara Date: Fri, 10 May 2019 21:38:30 +0300 Subject: [PATCH 2/2] WIP --- .../HaXeContext/Completion/CodeComplete.cs | 45 +++++++++------- External/Plugins/HaXeContext/Context.cs | 52 ++++++++++++++++--- .../AfterOnCharAndReplaceText_enums_1.hx | 4 +- .../BeforeOnCharAndReplaceText_enums_1.hx | 2 +- 4 files changed, 73 insertions(+), 30 deletions(-) diff --git a/External/Plugins/HaXeContext/Completion/CodeComplete.cs b/External/Plugins/HaXeContext/Completion/CodeComplete.cs index cdb60cf2d4..4d99c4810b 100644 --- a/External/Plugins/HaXeContext/Completion/CodeComplete.cs +++ b/External/Plugins/HaXeContext/Completion/CodeComplete.cs @@ -1319,26 +1319,13 @@ protected override void GetInstanceMembers(bool autoHide, ASResult expr, ClassMo return; } } - if ((exprType.Flags & FlagType.Enum) != 0 && (exprType.Flags & FlagType.Abstract) == 0 && expr.IsStatic) + if (expr.IsStatic && (exprType.Flags & FlagType.Enum) != 0 && (exprType.Flags & FlagType.Abstract) == 0) { - /** - * for example: - * using haxe.EnumTools; - * enum ETest { - * A; - * B; - * } - * class Test { - * function test() { - * ETest. - * } - * } - */ - var type = ResolveType("Enum", ASContext.Context.CurrentModel); - if (!type.IsVoid() && Context.TryResolveStaticExtensions(type, ASContext.Context.CurrentModel, out var tmpExprType)) + var type = ResolveType("Enum", null); + if (Context.TryResolveStaticExtensions(type, ASContext.Context.CurrentModel, out var tmp)) { - exprType = tmpExprType; - mask &= ~FlagType.Static; + foreach (MemberModel it in tmp.Members) it.Flags |= FlagType.Static; + exprType.Members.Merge(tmp.Members); } } else Context.TryResolveStaticExtensions(exprType, ASContext.Context.CurrentModel, out exprType); @@ -1540,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/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/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