diff --git a/CodeCompletion/DomSyntaxTreeVisitor.cs b/CodeCompletion/DomSyntaxTreeVisitor.cs index c0c45a360..b88ad0a84 100644 --- a/CodeCompletion/DomSyntaxTreeVisitor.cs +++ b/CodeCompletion/DomSyntaxTreeVisitor.cs @@ -2651,6 +2651,19 @@ namespace CodeCompletion for (int i=0; i 0) { if (obj != null) diff --git a/CodeCompletion/ExpressionVisitor.cs b/CodeCompletion/ExpressionVisitor.cs index 5e6c8f23d..213d0382c 100644 --- a/CodeCompletion/ExpressionVisitor.cs +++ b/CodeCompletion/ExpressionVisitor.cs @@ -28,6 +28,7 @@ namespace CodeCompletion private bool on_bracket; internal bool mouse_hover = false; private DomSyntaxTreeVisitor stv = null; + private SymScope[] selected_methods = null; public ExpressionVisitor(SymScope entry_scope, DomSyntaxTreeVisitor stv) { @@ -225,7 +226,7 @@ namespace CodeCompletion { List lst = tleft.FindOverloadNamesOnlyInType (PascalABCCompiler.TreeConverter.name_reflector.get_name(_bin_expr.operation_type)); - ProcScope ps = select_method(lst.ToArray(), _bin_expr.left, _bin_expr.right); + ProcScope ps = select_method(lst.ToArray(), tleft, tright, null, _bin_expr.left, _bin_expr.right); if (ps != null) returned_scope = new ElementScope(ps.return_type); else @@ -860,7 +861,88 @@ namespace CodeCompletion throw new NotImplementedException(); } - private ProcScope select_method(SymScope[] procs, params expression[] args) + private ProcScope select_method(SymScope[] meths, TypeScope tleft, TypeScope tright, TypeScope obj, params expression[] args) + { + List arg_types = new List(); + List arg_types2 = new List(); + SymScope[] saved_selected_methods = selected_methods; + selected_methods = meths; + if (tleft != null || tright != null) + { + if (tleft != null) + { + arg_types.Add(tleft); + arg_types2.Add(tleft); + } + if (tright != null) + { + arg_types.Add(tright); + arg_types2.Add(tright); + } + } + else if (args != null) + { + foreach (expression e in args) + { + e.visit(this); + returned_scopes.Clear(); + if (returned_scope is ElementScope) + returned_scope = (returned_scope as ElementScope).sc; + if (returned_scope is ProcScope) + returned_scope = (returned_scope as ProcScope).return_type; + arg_types.Add(returned_scope); + arg_types2.Add(returned_scope as TypeScope); + } + } + selected_methods = saved_selected_methods; + List good_procs = new List(); + for (int i = 0; i < meths.Length; i++) + { + if (meths[i] is ProcScope) + { + if (DomSyntaxTreeVisitor.is_good_overload(meths[i] as ProcScope, arg_types)) + if (!meths[i].si.not_include || by_dot) + good_procs.Add(meths[i] as ProcScope); + } + else if (meths[i] is ProcType) + { + if (DomSyntaxTreeVisitor.is_good_overload((meths[i] as ProcType).target, arg_types)) + if (!meths[i].si.not_include || by_dot) + good_procs.Add((meths[i] as ProcType).target); + } + } + if (good_procs.Count > 1) + for (int i = 0; i < good_procs.Count; i++) + if (DomSyntaxTreeVisitor.is_good_exact_overload(good_procs[i] as ProcScope, arg_types)) + return good_procs[i].GetInstance(arg_types2); + if (good_procs.Count == 0) + { + for (int i = 0; i < meths.Length; i++) + { + if (meths[i] is ProcScope) + { + if (obj != null && !(meths[i] as ProcScope).IsStatic) + { + good_procs.Add(meths[i] as ProcScope); + } + } + } + } + if (good_procs.Count > 0) + { + if (obj != null) + { + if (obj.GetElementType() != null && good_procs[0].IsExtension && !(good_procs[0].parameters[0].sc is TemplateParameterScope)) + obj = obj.GetElementType(); + arg_types2.Insert(0, obj); + } + + return good_procs[0].GetInstance(arg_types2); + } + return null; + } + + /*private ProcScope select_method(SymScope[] procs, params expression[] args) { List arg_types = new List(); if (args != null) @@ -885,10 +967,6 @@ namespace CodeCompletion List good_procs = new List(); for (int i = 0; i < procs.Length; i++) { - /*if (procs[i] is ElementScope && (procs[i] as ElementScope).sc is ProcType) - { - procs[i] = ((procs[i] as ElementScope).sc as ProcType).target; - }*/ if (procs[i] is ProcScope) { if (DomSyntaxTreeVisitor.is_good_overload(procs[i] as ProcScope, arg_types)) @@ -903,7 +981,7 @@ namespace CodeCompletion if (good_procs.Count > 0) return good_procs[0]; return null; - } + }*/ public override void visit(method_call _method_call) { @@ -922,7 +1000,38 @@ namespace CodeCompletion returned_scope = names[0]; return; } - ProcScope ps = select_method(names, _method_call.parameters != null ? _method_call.parameters.expressions.ToArray() : null); + TypeScope obj = null; + foreach (SymScope ss in names) + { + if (ss is ProcScope && (ss as ProcScope).is_extension) + { + ProcScope proc = ss as ProcScope; + if (_method_call.dereferencing_value is dot_node) + { + (_method_call.dereferencing_value as dot_node).left.visit(this); + if (returned_scope is ElementScope) + returned_scope = (returned_scope as ElementScope).sc; + obj = returned_scope as TypeScope; + if (obj != null && proc.parameters != null && proc.parameters.Count > 0 && !(proc.parameters[0].sc is TemplateParameterScope || proc.parameters[0].sc is UnknownScope)) + { + TypeScope param_type = proc.parameters[0].sc as TypeScope; + if (obj.implemented_interfaces != null) + { + foreach (TypeScope interf in obj.implemented_interfaces) + { + if (interf.original_type != null && param_type.original_type != null && interf.original_type == param_type.original_type) + { + List generic_args = interf.GetInstances(); + if (generic_args != null && generic_args.Count > 0) + obj = generic_args[0]; + } + } + } + } + } + } + } + ProcScope ps = select_method(names, null, null, obj, _method_call.parameters != null ? _method_call.parameters.expressions.ToArray() : null); returned_scope = ps; if (ps == null && names.Length > 0) { @@ -1440,7 +1549,7 @@ namespace CodeCompletion if (!on_bracket) { ProcScope[] constrs = cnstrs.ToArray(); - ProcScope ps = select_method(constrs, _new_expr.params_list != null ? _new_expr.params_list.expressions.ToArray() : null); + ProcScope ps = select_method(constrs, null, null, null, _new_expr.params_list != null ? _new_expr.params_list.expressions.ToArray() : null); if (ps != null) returned_scope = ps; else diff --git a/CodeCompletion/SymTable.cs b/CodeCompletion/SymTable.cs index 77312f5f9..4a3d8ee1d 100644 --- a/CodeCompletion/SymTable.cs +++ b/CodeCompletion/SymTable.cs @@ -4654,7 +4654,8 @@ namespace CodeCompletion if (ctn.BaseType != null) baseScope = TypeTable.get_compiled_type(ctn.BaseType); Type t = ctn.GetElementType(); - //get_default_property(); + if (t == null && ctn == typeof(string)) + t = typeof(char); if (t != null) { elementType = TypeTable.get_compiled_type(t); diff --git a/ReleaseGenerators/sect_VisualPABCNET.nsh b/ReleaseGenerators/sect_VisualPABCNET.nsh index 7eef92248..1a4a76bae 100644 --- a/ReleaseGenerators/sect_VisualPABCNET.nsh +++ b/ReleaseGenerators/sect_VisualPABCNET.nsh @@ -14,6 +14,7 @@ File "..\bin\template.pct" File "..\bin\samples.pct" File "..\bin\Pause.exe" + File "..\bin\nuget.exe" File "..\bin\FormatterOptions.ini" File "..\bin\ProgrammRunner.exe" File "..\bin\pabcworknet.ini" @@ -32,6 +33,7 @@ ${AddFile} "template.pct" ${AddFile} "samples.pct" ${AddFile} "Pause.exe" + ${AddFile} "nuget.exe" ${AddFile} "FormatterOptions.ini" ${AddFile} "ProgrammRunner.exe" diff --git a/TestSuite/intellisense_tests/extensionmethods2.pas b/TestSuite/intellisense_tests/extensionmethods2.pas index 11511f872..68b44ac20 100644 --- a/TestSuite/intellisense_tests/extensionmethods2.pas +++ b/TestSuite/intellisense_tests/extensionmethods2.pas @@ -1,5 +1,6 @@ begin var a:=MatrRandom(4,5); var b{@var b: sequence of IEnumerable;@}:=a.Rows.SelectMany(x->x); - + var arr1: array of integer; + var i{@var i: integer;@} := arr1.Find(x->x=2); end. \ No newline at end of file diff --git a/VisualPascalABCNET/Projects/NuGetTasks.cs b/VisualPascalABCNET/Projects/NuGetTasks.cs new file mode 100644 index 000000000..981b2a3c9 --- /dev/null +++ b/VisualPascalABCNET/Projects/NuGetTasks.cs @@ -0,0 +1,86 @@ +// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace VisualPascalABC +{ + delegate void NugetPackageInstallHandler(bool result, string[] dlls, string[] xmls); + delegate void NugetPackageOutputHandler(string output); + + class NuGetTasks + { + public static void InstallPackage(string packageId, string workingDir, NugetPackageInstallHandler finishAction, NugetPackageOutputHandler outputAction) + { + string dir = Path.Combine(workingDir, "nuget"); + dir = Path.Combine(dir, packageId); + Directory.CreateDirectory(dir); + Process nugetProcess = new Process(); + nugetProcess.StartInfo.FileName = Path.Combine(PascalABCCompiler.Tools.GetExecutablePath(), "nuget.exe"); + nugetProcess.StartInfo.UseShellExecute = false; + nugetProcess.StartInfo.Arguments = "install "+packageId+ " -NonInteractive"; + nugetProcess.StartInfo.CreateNoWindow = true; + nugetProcess.StartInfo.RedirectStandardOutput = true; + nugetProcess.StartInfo.RedirectStandardError = true; + nugetProcess.StartInfo.WorkingDirectory = dir; + nugetProcess.EnableRaisingEvents = true; + nugetProcess.StartInfo.StandardOutputEncoding = System.Text.Encoding.UTF8; + nugetProcess.Exited += new EventHandler(delegate (object o, EventArgs a) { + string[] dlls; + string[] xmls; + bool result = getPackage(dir, out dlls, out xmls); + finishAction(result, dlls, xmls); + }); + nugetProcess.Start(); + nugetProcess.WaitForExit(); + } + + static bool getPackage(string workingDir, out string[] dlls, out string[] xmls) + { + dlls = null; + xmls = null; + List dllList = new List(); + List xmlList = new List(); + bool result = false; + foreach (string dir in Directory.EnumerateDirectories(workingDir)) + { + string libDir = Path.Combine(dir, "lib"); + if (Directory.Exists(libDir)) + { + string dotnetDir = Path.Combine(libDir, "net40"); + if (!Directory.Exists(dotnetDir)) + dotnetDir = Path.Combine(libDir, "net45"); + if (!Directory.Exists(dotnetDir)) + dotnetDir = Path.Combine(libDir, "net46"); + if (!Directory.Exists(dotnetDir)) + dotnetDir = Path.Combine(libDir, "net"); + if (!Directory.Exists(dotnetDir)) + dotnetDir = libDir; + if (Directory.Exists(dotnetDir)) + { + string[] dllFiles = Directory.GetFiles(dotnetDir, "*.dll"); + if (dllFiles.Length > 0) + { + dllList.AddRange(dllFiles); + dlls = dllFiles; + string[] xmlFiles = Directory.GetFiles(dotnetDir, "*.xml"); + if (xmlFiles.Length > 0) + xmlList.AddRange(xmlFiles); + result = true; + } + } + } + } + dlls = dllList.ToArray(); + xmls = xmlList.ToArray(); + return result; + } + } +} \ No newline at end of file diff --git a/VisualPascalABCNET/Projects/ProjectTasks.cs b/VisualPascalABCNET/Projects/ProjectTasks.cs index 9a17a7388..7819c7cd0 100644 --- a/VisualPascalABCNET/Projects/ProjectTasks.cs +++ b/VisualPascalABCNET/Projects/ProjectTasks.cs @@ -51,13 +51,28 @@ namespace VisualPascalABC { string[] assemblies = ReferenceForm.Instance.GetSelectedFileAssemblies(); List assm_lst = new List(); - foreach (string s in assemblies) + foreach (string dll in assemblies) { - if (string.Compare(s, Path.Combine(ProjectFactory.Instance.ProjectDirectory, Path.GetFileName(s)), true) != 0) - File.Copy(s, Path.Combine(ProjectFactory.Instance.ProjectDirectory, Path.GetFileName(s)), true); + if (string.Compare(dll, Path.Combine(ProjectFactory.Instance.ProjectDirectory, Path.GetFileName(dll)), true) != 0) + File.Copy(dll, Path.Combine(ProjectFactory.Instance.ProjectDirectory, Path.GetFileName(dll)), true); + string xml = Path.ChangeExtension(dll, ".xml"); + if (File.Exists(xml)) + { + if (string.Compare(xml, Path.Combine(ProjectFactory.Instance.ProjectDirectory, Path.GetFileName(xml)), true) != 0) + File.Copy(xml, Path.Combine(ProjectFactory.Instance.ProjectDirectory, Path.GetFileName(xml)), true); + } //assm_lst.Add(Path.GetFileNameWithoutExtension(s)); //ProjectExplorerWindow.AddReferenceNode(Path.GetFileNameWithoutExtension(s)); - PascalABCCompiler.IReferenceInfo ri = ProjectFactory.Instance.AddReference(Path.GetFileNameWithoutExtension(s)); + try + { + PascalABCCompiler.NetHelper.NetHelper.LoadAssembly(dll); + } + catch + { + continue; + } + + PascalABCCompiler.IReferenceInfo ri = ProjectFactory.Instance.AddReference(Path.GetFileNameWithoutExtension(dll)); ProjectExplorerWindow.AddReferenceNode(ri); try { diff --git a/VisualPascalABCNET/Projects/ReferenceForm.Designer.cs b/VisualPascalABCNET/Projects/ReferenceForm.Designer.cs index 5987ebe83..29a8fc2e1 100644 --- a/VisualPascalABCNET/Projects/ReferenceForm.Designer.cs +++ b/VisualPascalABCNET/Projects/ReferenceForm.Designer.cs @@ -36,18 +36,27 @@ namespace VisualPascalABC this.chVersion = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.tpAssemblies = new System.Windows.Forms.TabPage(); this.button1 = new System.Windows.Forms.Button(); + this.tpNuGet = new System.Windows.Forms.TabPage(); + this.label2 = new System.Windows.Forms.Label(); + this.tbLog = new System.Windows.Forms.TextBox(); + this.btnSearchPackages = new System.Windows.Forms.Button(); + this.btnInstallPackage = new System.Windows.Forms.Button(); + this.tbPackageName = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); this.btnOk = new System.Windows.Forms.Button(); this.btnCancel = new System.Windows.Forms.Button(); this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); this.tabControl1.SuspendLayout(); this.tpGAC.SuspendLayout(); this.tpAssemblies.SuspendLayout(); + this.tpNuGet.SuspendLayout(); this.SuspendLayout(); // // tabControl1 // this.tabControl1.Controls.Add(this.tpGAC); this.tabControl1.Controls.Add(this.tpAssemblies); + this.tabControl1.Controls.Add(this.tpNuGet); this.tabControl1.Location = new System.Drawing.Point(0, 0); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; @@ -110,6 +119,76 @@ namespace VisualPascalABC this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.Button1Click); // + // tpNuGet + // + this.tpNuGet.Controls.Add(this.label2); + this.tpNuGet.Controls.Add(this.tbLog); + this.tpNuGet.Controls.Add(this.btnSearchPackages); + this.tpNuGet.Controls.Add(this.btnInstallPackage); + this.tpNuGet.Controls.Add(this.tbPackageName); + this.tpNuGet.Controls.Add(this.label1); + this.tpNuGet.Location = new System.Drawing.Point(4, 22); + this.tpNuGet.Name = "tpNuGet"; + this.tpNuGet.Size = new System.Drawing.Size(440, 232); + this.tpNuGet.TabIndex = 2; + this.tpNuGet.Text = "PRJ_NUGET"; + this.tpNuGet.UseVisualStyleBackColor = true; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(16, 110); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(73, 13); + this.label2.TabIndex = 5; + this.label2.Text = "NUGET_LOG"; + this.label2.Visible = false; + // + // tbLog + // + this.tbLog.Location = new System.Drawing.Point(17, 126); + this.tbLog.Multiline = true; + this.tbLog.Name = "tbLog"; + this.tbLog.Size = new System.Drawing.Size(407, 82); + this.tbLog.TabIndex = 4; + this.tbLog.Visible = false; + // + // btnSearchPackages + // + this.btnSearchPackages.Location = new System.Drawing.Point(273, 34); + this.btnSearchPackages.Name = "btnSearchPackages"; + this.btnSearchPackages.Size = new System.Drawing.Size(29, 20); + this.btnSearchPackages.TabIndex = 3; + this.btnSearchPackages.Text = "..."; + this.btnSearchPackages.UseVisualStyleBackColor = true; + this.btnSearchPackages.Click += new System.EventHandler(this.btnSearchPackages_Click); + // + // btnInstallPackage + // + this.btnInstallPackage.Location = new System.Drawing.Point(17, 69); + this.btnInstallPackage.Name = "btnInstallPackage"; + this.btnInstallPackage.Size = new System.Drawing.Size(118, 22); + this.btnInstallPackage.TabIndex = 2; + this.btnInstallPackage.Text = "NUGET_INSTALL"; + this.btnInstallPackage.UseVisualStyleBackColor = true; + this.btnInstallPackage.Click += new System.EventHandler(this.btnInstallPackage_Click); + // + // tbPackageName + // + this.tbPackageName.Location = new System.Drawing.Point(19, 34); + this.tbPackageName.Name = "tbPackageName"; + this.tbPackageName.Size = new System.Drawing.Size(249, 20); + this.tbPackageName.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(14, 15); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(101, 13); + this.label1.TabIndex = 0; + this.label1.Text = "NUGET_PACKAGE"; + // // btnOk // this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK; @@ -155,6 +234,8 @@ namespace VisualPascalABC this.tabControl1.ResumeLayout(false); this.tpGAC.ResumeLayout(false); this.tpAssemblies.ResumeLayout(false); + this.tpNuGet.ResumeLayout(false); + this.tpNuGet.PerformLayout(); this.ResumeLayout(false); } @@ -168,5 +249,12 @@ namespace VisualPascalABC private System.Windows.Forms.TabPage tpAssemblies; private System.Windows.Forms.TabPage tpGAC; private System.Windows.Forms.TabControl tabControl1; - } + private System.Windows.Forms.TabPage tpNuGet; + private System.Windows.Forms.TextBox tbPackageName; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button btnInstallPackage; + private System.Windows.Forms.Button btnSearchPackages; + private System.Windows.Forms.TextBox tbLog; + private System.Windows.Forms.Label label2; + } } diff --git a/VisualPascalABCNET/Projects/ReferenceForm.cs b/VisualPascalABCNET/Projects/ReferenceForm.cs index f84f1d562..e5df9c687 100644 --- a/VisualPascalABCNET/Projects/ReferenceForm.cs +++ b/VisualPascalABCNET/Projects/ReferenceForm.cs @@ -70,6 +70,7 @@ namespace VisualPascalABC assembly_files.Clear(); assemblyType = AssemblyType.GAC; lvGac.Items.Clear(); + tbLog.Text = ""; //lvCom.Items.Clear(); } @@ -153,5 +154,42 @@ namespace VisualPascalABC } } - } + private void nugetInstalled(bool result, string[] dlls, string[] xmls) + { + assemblyType = AssemblyType.File; + if (result) + { + foreach (string dll in dlls) + assembly_files.Add(dll); + this.DialogResult = DialogResult.OK; + } + else + this.DialogResult = DialogResult.Cancel; + this.Close(); + } + + private void nugetOutput(string output) + { + tbLog.Text += output; + } + + private void btnInstallPackage_Click(object sender, EventArgs e) + { + NuGetTasks.InstallPackage(tbPackageName.Text, + ProjectFactory.Instance.CurrentProject.ProjectDirectory, + new NugetPackageInstallHandler(nugetInstalled), + new NugetPackageOutputHandler(nugetOutput)); + + } + + private void btnSearchPackages_Click(object sender, EventArgs e) + { + System.Diagnostics.Process.Start("https://www.nuget.org/packages"); + } + + private void textBox1_TextChanged(object sender, EventArgs e) + { + + } + } } diff --git a/VisualPascalABCNET/VisualPascalABCNET.csproj b/VisualPascalABCNET/VisualPascalABCNET.csproj index 8270c1714..0bea85cbd 100644 --- a/VisualPascalABCNET/VisualPascalABCNET.csproj +++ b/VisualPascalABCNET/VisualPascalABCNET.csproj @@ -368,6 +368,7 @@ + Form diff --git a/bin/Lng/Eng/VisualPascalABCNET.dat b/bin/Lng/Eng/VisualPascalABCNET.dat index 5a4f7e681..7d1df480f 100644 --- a/bin/Lng/Eng/VisualPascalABCNET.dat +++ b/bin/Lng/Eng/VisualPascalABCNET.dat @@ -331,6 +331,10 @@ PRJ_COMPANY=Company PRJ_TRADEMARK=Trademark PRJ_COPYRIGHT=Copyright PRJ_GENERATE_XML_DOC=Generate XML doc +PRJ_NUGET=NuGet +NUGET_PACKAGE=Package Id +NUGET_INSTALL=Install package +NUGET_LOG=Log VERSION_IS_UP_DO_DATE=PascalABC.NET is up to date UPDATE_AVAILABLE=New version of PascalABC.NET is available. Do you want to visit the download page? UPDATE_AVAILABLE_CURRENT_VESION{0}=Installed version: {0} diff --git a/bin/Lng/Rus/VisualPascalABCNET.dat b/bin/Lng/Rus/VisualPascalABCNET.dat index f7ea481c9..841fc54ab 100644 --- a/bin/Lng/Rus/VisualPascalABCNET.dat +++ b/bin/Lng/Rus/VisualPascalABCNET.dat @@ -331,7 +331,10 @@ PRJ_COMPANY=Компания PRJ_TRADEMARK=Торговая марка PRJ_COPYRIGHT=Copyright PRJ_GENERATE_XML_DOC=Генерировать XML документацию -VERSION_IS_UP_DO_DATE=Вы используете актуальную версию PascalABC.NET +PRJ_NUGET=NuGet +NUGET_PACKAGE=Идентификатор пакета +NUGET_INSTALL=Установить пакет +NUGET_LOG=Лог UPDATE_AVAILABLE=Доступна новая версия PascalABC.NET. Перейти на страницу скачивания? UPDATE_AVAILABLE_CURRENT_VESION{0}=Установленная версия: {0} UPDATE_AVAILABLE_NEW_VESION{0}=Доступная версия: {0} diff --git a/bin/nuget.exe b/bin/nuget.exe new file mode 100644 index 000000000..856263ded Binary files /dev/null and b/bin/nuget.exe differ